sunxi: video: split out PLL configuration code
authorVasily Khoruzhick <anarsoul@gmail.com>
Fri, 27 Oct 2017 04:51:51 +0000 (21:51 -0700)
committerAnatolij Gustschin <agust@denx.de>
Fri, 27 Oct 2017 07:39:19 +0000 (09:39 +0200)
It will be reused in new DM LCD driver.

Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
arch/arm/include/asm/arch-sunxi/lcdc.h
drivers/video/sunxi/lcdc.c
drivers/video/sunxi/sunxi_display.c

index a751698b4fe3ede0d49190464ed5e489b774a4a7..132c4801067052f3b30e88055b193b94255f50a7 100644 (file)
@@ -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 */
index 7d215b713efad892d26d2c8a3712d4a0b905d1a0..4cb86fb7ffafa865cf759215110cb58d20b7ffd9 100644 (file)
@@ -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;
+}
index 7f25ed5f26e9d7e90e8be43d076295c6047c3de3..0630289c0a194f925dd8ad18f698a03599e66820 100644 (file)
@@ -516,119 +516,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 =
@@ -755,6 +642,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;
 
@@ -774,7 +663,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,
@@ -788,6 +678,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);
@@ -799,7 +691,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 */