[U-Boot] [PATCH v4 4/5] sunxi: video: split out PLL configuration code

Vasily Khoruzhick anarsoul at gmail.com
Fri Oct 27 04:51:51 UTC 2017


It will be reused in new DM LCD driver.

Signed-off-by: Vasily Khoruzhick <anarsoul at gmail.com>
---
v2-v3: no changes
v4: - fix compilation for boards that use sunxi_display.c
    - rebased and fixed checkpatch errors

 arch/arm/include/asm/arch-sunxi/lcdc.h |   3 +
 drivers/video/sunxi/lcdc.c             | 122 +++++++++++++++++++++++++++++++-
 drivers/video/sunxi/sunxi_display.c    | 123 +++------------------------------
 3 files changed, 132 insertions(+), 116 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/lcdc.h b/arch/arm/include/asm/arch-sunxi/lcdc.h
index a751698b4f..132c480106 100644
--- a/arch/arm/include/asm/arch-sunxi/lcdc.h
+++ b/arch/arm/include/asm/arch-sunxi/lcdc.h
@@ -124,5 +124,8 @@ void lcdc_tcon0_mode_set(struct sunxi_lcdc_reg * const lcdc,
 void lcdc_tcon1_mode_set(struct sunxi_lcdc_reg * const lcdc,
 			 const struct display_timing *mode,
 			 bool ext_hvsync, bool is_composite);
+void lcdc_pll_set(struct sunxi_ccm_reg * const ccm, int tcon,
+		  int dotclock, int *clk_div, int *clk_double,
+		  bool is_composite);
 
 #endif /* _LCDC_H */
diff --git a/drivers/video/sunxi/lcdc.c b/drivers/video/sunxi/lcdc.c
index 7d215b713e..4cb86fb7ff 100644
--- a/drivers/video/sunxi/lcdc.c
+++ b/drivers/video/sunxi/lcdc.c
@@ -10,6 +10,7 @@
 
 #include <common.h>
 
+#include <asm/arch/clock.h>
 #include <asm/arch/lcdc.h>
 #include <asm/io.h>
 
@@ -100,7 +101,7 @@ void lcdc_tcon0_mode_set(struct sunxi_lcdc_reg * const lcdc,
 	writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) |
 	       SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v);
 
-#ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
+#if defined(CONFIG_VIDEO_LCD_IF_PARALLEL) || defined(CONFIG_VIDEO_DE2)
 	writel(SUNXI_LCDC_X(mode->hsync_len.typ) |
 	       SUNXI_LCDC_Y(mode->vsync_len.typ), &lcdc->tcon0_timing_sync);
 
@@ -207,3 +208,122 @@ void lcdc_tcon1_mode_set(struct sunxi_lcdc_reg * const lcdc,
 				SUNXI_LCDC_MUX_CTRL_SRC0(1));
 #endif
 }
+
+void lcdc_pll_set(struct sunxi_ccm_reg *ccm, int tcon, int dotclock,
+		  int *clk_div, int *clk_double, bool is_composite)
+{
+	int value, n, m, min_m, max_m, diff;
+	int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
+	int best_double = 0;
+	bool use_mipi_pll = false;
+
+	if (tcon == 0) {
+#if defined(CONFIG_VIDEO_LCD_IF_PARALLEL) || defined(CONFIG_SUNXI_DE2)
+		min_m = 6;
+		max_m = 127;
+#endif
+#ifdef CONFIG_VIDEO_LCD_IF_LVDS
+		min_m = 7;
+		max_m = 7;
+#endif
+	} else {
+		min_m = 1;
+		max_m = 15;
+	}
+
+	/*
+	 * Find the lowest divider resulting in a matching clock, if there
+	 * is no match, pick the closest lower clock, as monitors tend to
+	 * not sync to higher frequencies.
+	 */
+	for (m = min_m; m <= max_m; m++) {
+#ifndef CONFIG_SUNXI_DE2
+		n = (m * dotclock) / 3000;
+
+		if ((n >= 9) && (n <= 127)) {
+			value = (3000 * n) / m;
+			diff = dotclock - value;
+			if (diff < best_diff) {
+				best_diff = diff;
+				best_m = m;
+				best_n = n;
+				best_double = 0;
+			}
+		}
+
+		/* These are just duplicates */
+		if (!(m & 1))
+			continue;
+#endif
+
+		/* No double clock on DE2 */
+		n = (m * dotclock) / 6000;
+		if ((n >= 9) && (n <= 127)) {
+			value = (6000 * n) / m;
+			diff = dotclock - value;
+			if (diff < best_diff) {
+				best_diff = diff;
+				best_m = m;
+				best_n = n;
+				best_double = 1;
+			}
+		}
+	}
+
+#ifdef CONFIG_MACH_SUN6I
+	/*
+	 * Use the MIPI pll if we've been unable to find any matching setting
+	 * for PLL3, this happens with high dotclocks because of min_m = 6.
+	 */
+	if (tcon == 0 && best_n == 0) {
+		use_mipi_pll = true;
+		best_m = 6;  /* Minimum m for tcon0 */
+	}
+
+	if (use_mipi_pll) {
+		clock_set_pll3(297000000); /* Fix the video pll at 297 MHz */
+		clock_set_mipi_pll(best_m * dotclock * 1000);
+		debug("dotclock: %dkHz = %dkHz via mipi pll\n",
+		      dotclock, clock_get_mipi_pll() / best_m / 1000);
+	} else
+#endif
+	{
+		clock_set_pll3(best_n * 3000000);
+		debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
+		      dotclock,
+		      (best_double + 1) * clock_get_pll3() / best_m / 1000,
+		      best_double + 1, best_n, best_m);
+	}
+
+	if (tcon == 0) {
+		u32 pll;
+
+		if (use_mipi_pll)
+			pll = CCM_LCD_CH0_CTRL_MIPI_PLL;
+		else if (best_double)
+			pll = CCM_LCD_CH0_CTRL_PLL3_2X;
+		else
+			pll = CCM_LCD_CH0_CTRL_PLL3;
+#ifndef CONFIG_SUNXI_DE2
+		writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll,
+		       &ccm->lcd0_ch0_clk_cfg);
+#else
+		writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll,
+		       &ccm->lcd0_clk_cfg);
+#endif
+	}
+#ifndef CONFIG_SUNXI_DE2
+	else {
+		writel(CCM_LCD_CH1_CTRL_GATE |
+		       (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X :
+				      CCM_LCD_CH1_CTRL_PLL3) |
+		       CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg);
+		if (is_composite)
+			setbits_le32(&ccm->lcd0_ch1_clk_cfg,
+				     CCM_LCD_CH1_CTRL_HALF_SCLK1);
+	}
+#endif
+
+	*clk_div = best_m;
+	*clk_double = best_double;
+}
diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c
index de768ba94a..87a1a4496d 100644
--- a/drivers/video/sunxi/sunxi_display.c
+++ b/drivers/video/sunxi/sunxi_display.c
@@ -515,119 +515,6 @@ static void sunxi_composer_enable(void)
 	setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START);
 }
 
-/*
- * LCDC, what allwinner calls a CRTC, so timing controller and serializer.
- */
-static void sunxi_lcdc_pll_set(int tcon, int dotclock,
-			       int *clk_div, int *clk_double)
-{
-	struct sunxi_ccm_reg * const ccm =
-		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
-	int value, n, m, min_m, max_m, diff;
-	int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
-	int best_double = 0;
-	bool use_mipi_pll = false;
-
-	if (tcon == 0) {
-#ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
-		min_m = 6;
-		max_m = 127;
-#endif
-#ifdef CONFIG_VIDEO_LCD_IF_LVDS
-		min_m = max_m = 7;
-#endif
-	} else {
-		min_m = 1;
-		max_m = 15;
-	}
-
-	/*
-	 * Find the lowest divider resulting in a matching clock, if there
-	 * is no match, pick the closest lower clock, as monitors tend to
-	 * not sync to higher frequencies.
-	 */
-	for (m = min_m; m <= max_m; m++) {
-		n = (m * dotclock) / 3000;
-
-		if ((n >= 9) && (n <= 127)) {
-			value = (3000 * n) / m;
-			diff = dotclock - value;
-			if (diff < best_diff) {
-				best_diff = diff;
-				best_m = m;
-				best_n = n;
-				best_double = 0;
-			}
-		}
-
-		/* These are just duplicates */
-		if (!(m & 1))
-			continue;
-
-		n = (m * dotclock) / 6000;
-		if ((n >= 9) && (n <= 127)) {
-			value = (6000 * n) / m;
-			diff = dotclock - value;
-			if (diff < best_diff) {
-				best_diff = diff;
-				best_m = m;
-				best_n = n;
-				best_double = 1;
-			}
-		}
-	}
-
-#ifdef CONFIG_MACH_SUN6I
-	/*
-	 * Use the MIPI pll if we've been unable to find any matching setting
-	 * for PLL3, this happens with high dotclocks because of min_m = 6.
-	 */
-	if (tcon == 0 && best_n == 0) {
-		use_mipi_pll = true;
-		best_m = 6;  /* Minimum m for tcon0 */
-	}
-
-	if (use_mipi_pll) {
-		clock_set_pll3(297000000); /* Fix the video pll at 297 MHz */
-		clock_set_mipi_pll(best_m * dotclock * 1000);
-		debug("dotclock: %dkHz = %dkHz via mipi pll\n",
-		      dotclock, clock_get_mipi_pll() / best_m / 1000);
-	} else
-#endif
-	{
-		clock_set_pll3(best_n * 3000000);
-		debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
-		      dotclock,
-		      (best_double + 1) * clock_get_pll3() / best_m / 1000,
-		      best_double + 1, best_n, best_m);
-	}
-
-	if (tcon == 0) {
-		u32 pll;
-
-		if (use_mipi_pll)
-			pll = CCM_LCD_CH0_CTRL_MIPI_PLL;
-		else if (best_double)
-			pll = CCM_LCD_CH0_CTRL_PLL3_2X;
-		else
-			pll = CCM_LCD_CH0_CTRL_PLL3;
-
-		writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll,
-		       &ccm->lcd0_ch0_clk_cfg);
-	} else {
-		writel(CCM_LCD_CH1_CTRL_GATE |
-		       (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X :
-				      CCM_LCD_CH1_CTRL_PLL3) |
-		       CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg);
-		if (sunxi_is_composite())
-			setbits_le32(&ccm->lcd0_ch1_clk_cfg,
-				     CCM_LCD_CH1_CTRL_HALF_SCLK1);
-	}
-
-	*clk_div = best_m;
-	*clk_double = best_double;
-}
-
 static void sunxi_lcdc_init(void)
 {
 	struct sunxi_ccm_reg * const ccm =
@@ -754,6 +641,8 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
 {
 	struct sunxi_lcdc_reg * const lcdc =
 		(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+	struct sunxi_ccm_reg * const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	int clk_div, clk_double, pin;
 	struct display_timing timing;
 
@@ -773,7 +662,8 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
 #endif
 	}
 
-	sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
+	lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double,
+		     sunxi_is_composite());
 
 	sunxi_ctfb_mode_to_display_timing(mode, &timing);
 	lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac,
@@ -787,6 +677,8 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
 {
 	struct sunxi_lcdc_reg * const lcdc =
 		(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+	struct sunxi_ccm_reg * const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	struct display_timing timing;
 
 	sunxi_ctfb_mode_to_display_timing(mode, &timing);
@@ -798,7 +690,8 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
 		sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0);
 	}
 
-	sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
+	lcdc_pll_set(ccm, 1, mode->pixclock_khz, clk_div, clk_double,
+		     sunxi_is_composite());
 }
 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
 
-- 
2.14.3



More information about the U-Boot mailing list