Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/bridge: samsung-dsim: update PLL reference clock

The PLL requires a clock frequency in a certain platform-dependent range
after the pre-divider. The reference clock for the PLL may change due to
changes to it's parent clock. Thus, the frequency may be out of range or
unsuited for generating the high speed clock for MIPI DSI.

Try to keep the pre-devider small, and set the reference clock close to
the upper limit before recalculating the PLL configuration. Use a
divider with a power of two for the reference clock as this seems to
work best in my tests.

Reviewed-by: Marco Felsch <m.felsch@pengutronix.de>
Tested-by: Frieder Schrempf <frieder.schrempf@kontron.de> # Kontron BL i.MX8MM + Waveshare 10.1inch HDMI LCD (E)
Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Link: https://lore.kernel.org/r/20230818-samsung-dsim-v2-3-846603df0e0a@pengutronix.de
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20230818-samsung-dsim-v2-3-846603df0e0a@pengutronix.de

authored by

Michael Tretter and committed by
Neil Armstrong
84630718 eb26c6ab

+27 -2
+25 -2
drivers/gpu/drm/bridge/samsung-dsim.c
··· 410 410 .num_bits_resol = 11, 411 411 .pll_p_offset = 13, 412 412 .reg_values = reg_values, 413 + .pll_fin_min = 6, 414 + .pll_fin_max = 12, 413 415 .m_min = 41, 414 416 .m_max = 125, 415 417 .min_freq = 500, ··· 429 427 .num_bits_resol = 11, 430 428 .pll_p_offset = 13, 431 429 .reg_values = reg_values, 430 + .pll_fin_min = 6, 431 + .pll_fin_max = 12, 432 432 .m_min = 41, 433 433 .m_max = 125, 434 434 .min_freq = 500, ··· 446 442 .num_bits_resol = 11, 447 443 .pll_p_offset = 13, 448 444 .reg_values = reg_values, 445 + .pll_fin_min = 6, 446 + .pll_fin_max = 12, 449 447 .m_min = 41, 450 448 .m_max = 125, 451 449 .min_freq = 500, ··· 463 457 .num_bits_resol = 12, 464 458 .pll_p_offset = 13, 465 459 .reg_values = exynos5433_reg_values, 460 + .pll_fin_min = 6, 461 + .pll_fin_max = 12, 466 462 .m_min = 41, 467 463 .m_max = 125, 468 464 .min_freq = 500, ··· 480 472 .num_bits_resol = 12, 481 473 .pll_p_offset = 13, 482 474 .reg_values = exynos5422_reg_values, 475 + .pll_fin_min = 6, 476 + .pll_fin_max = 12, 483 477 .m_min = 41, 484 478 .m_max = 125, 485 479 .min_freq = 500, ··· 501 491 */ 502 492 .pll_p_offset = 14, 503 493 .reg_values = imx8mm_dsim_reg_values, 494 + .pll_fin_min = 2, 495 + .pll_fin_max = 30, 504 496 .m_min = 64, 505 497 .m_max = 1023, 506 498 .min_freq = 1050, ··· 626 614 u16 m; 627 615 u32 reg; 628 616 629 - if (dsi->pll_clk) 617 + if (dsi->pll_clk) { 618 + /* 619 + * Ensure that the reference clock is generated with a power of 620 + * two divider from its parent, but close to the PLLs upper 621 + * limit. 622 + */ 623 + fin = clk_get_rate(clk_get_parent(dsi->pll_clk)); 624 + while (fin > driver_data->pll_fin_max * MHZ) 625 + fin /= 2; 626 + clk_set_rate(dsi->pll_clk, fin); 627 + 630 628 fin = clk_get_rate(dsi->pll_clk); 631 - else 629 + } else { 632 630 fin = dsi->pll_clk_rate; 631 + } 633 632 dev_dbg(dsi->dev, "PLL ref clock freq %lu\n", fin); 634 633 635 634 fout = samsung_dsim_pll_find_pms(dsi, fin, freq, &p, &m, &s);
+2
include/drm/bridge/samsung-dsim.h
··· 61 61 unsigned int num_bits_resol; 62 62 unsigned int pll_p_offset; 63 63 const unsigned int *reg_values; 64 + unsigned int pll_fin_min; 65 + unsigned int pll_fin_max; 64 66 u16 m_min; 65 67 u16 m_max; 66 68 };