summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Tretter <m.tretter@pengutronix.de>2023-10-06 18:07:05 +0300
committerNeil Armstrong <neil.armstrong@linaro.org>2023-10-09 12:06:22 +0300
commit846307185f0ffbbe6b34d53b97c31c0fc392cff0 (patch)
treeb0b845e1a96e837f1f1e93031388590bf0b85f93
parenteb26c6ab2a11e6c595ee88ce30c7de9578d957aa (diff)
downloadlinux-846307185f0ffbbe6b34d53b97c31c0fc392cff0.tar.xz
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
-rw-r--r--drivers/gpu/drm/bridge/samsung-dsim.c27
-rw-r--r--include/drm/bridge/samsung-dsim.h2
2 files changed, 27 insertions, 2 deletions
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 71fc0a8766ff..60d5ab2e0989 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -410,6 +410,8 @@ static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
.num_bits_resol = 11,
.pll_p_offset = 13,
.reg_values = reg_values,
+ .pll_fin_min = 6,
+ .pll_fin_max = 12,
.m_min = 41,
.m_max = 125,
.min_freq = 500,
@@ -427,6 +429,8 @@ static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
.num_bits_resol = 11,
.pll_p_offset = 13,
.reg_values = reg_values,
+ .pll_fin_min = 6,
+ .pll_fin_max = 12,
.m_min = 41,
.m_max = 125,
.min_freq = 500,
@@ -442,6 +446,8 @@ static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
.num_bits_resol = 11,
.pll_p_offset = 13,
.reg_values = reg_values,
+ .pll_fin_min = 6,
+ .pll_fin_max = 12,
.m_min = 41,
.m_max = 125,
.min_freq = 500,
@@ -457,6 +463,8 @@ static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
.num_bits_resol = 12,
.pll_p_offset = 13,
.reg_values = exynos5433_reg_values,
+ .pll_fin_min = 6,
+ .pll_fin_max = 12,
.m_min = 41,
.m_max = 125,
.min_freq = 500,
@@ -472,6 +480,8 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
.num_bits_resol = 12,
.pll_p_offset = 13,
.reg_values = exynos5422_reg_values,
+ .pll_fin_min = 6,
+ .pll_fin_max = 12,
.m_min = 41,
.m_max = 125,
.min_freq = 500,
@@ -491,6 +501,8 @@ static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = {
*/
.pll_p_offset = 14,
.reg_values = imx8mm_dsim_reg_values,
+ .pll_fin_min = 2,
+ .pll_fin_max = 30,
.m_min = 64,
.m_max = 1023,
.min_freq = 1050,
@@ -614,10 +626,21 @@ static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi,
u16 m;
u32 reg;
- if (dsi->pll_clk)
+ if (dsi->pll_clk) {
+ /*
+ * Ensure that the reference clock is generated with a power of
+ * two divider from its parent, but close to the PLLs upper
+ * limit.
+ */
+ fin = clk_get_rate(clk_get_parent(dsi->pll_clk));
+ while (fin > driver_data->pll_fin_max * MHZ)
+ fin /= 2;
+ clk_set_rate(dsi->pll_clk, fin);
+
fin = clk_get_rate(dsi->pll_clk);
- else
+ } else {
fin = dsi->pll_clk_rate;
+ }
dev_dbg(dsi->dev, "PLL ref clock freq %lu\n", fin);
fout = samsung_dsim_pll_find_pms(dsi, fin, freq, &p, &m, &s);
diff --git a/include/drm/bridge/samsung-dsim.h b/include/drm/bridge/samsung-dsim.h
index 757f87337fe5..e0c105051246 100644
--- a/include/drm/bridge/samsung-dsim.h
+++ b/include/drm/bridge/samsung-dsim.h
@@ -61,6 +61,8 @@ struct samsung_dsim_driver_data {
unsigned int num_bits_resol;
unsigned int pll_p_offset;
const unsigned int *reg_values;
+ unsigned int pll_fin_min;
+ unsigned int pll_fin_max;
u16 m_min;
u16 m_max;
};