diff options
-rw-r--r-- | arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 | ||||
-rw-r--r-- | drivers/video/sunxi_display.c | 31 |
2 files changed, 26 insertions, 7 deletions
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h index 1beeff3..653f63c 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h @@ -255,6 +255,8 @@ struct sunxi_ccm_reg { #define CCM_LCD_CH0_CTRL_PLL3_2X (2 << 24) #define CCM_LCD_CH0_CTRL_PLL7_2X (3 << 24) #define CCM_LCD_CH0_CTRL_MIPI_PLL (4 << 24) +/* No reset bit in ch0_clk_cfg (reset is controlled through ahb_reset1) */ +#define CCM_LCD_CH0_CTRL_RST 0 #define CCM_LCD_CH0_CTRL_GATE (0x1 << 31) #define CCM_LCD_CH1_CTRL_M(n) ((((n) - 1) & 0xf) << 0) diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index f990ab9..e4f95d4 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -323,20 +323,29 @@ static void sunxi_composer_enable(void) /* * LCDC, what allwinner calls a CRTC, so timing controller and serializer. */ -static void sunxi_lcdc_pll_set(int dotclock, int *clk_div, int *clk_double) +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, diff; + int value, n, m, min_m, max_m, diff; int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF; int best_double = 0; + if (tcon == 0) { + min_m = 6; + max_m = 127; + } 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 = 15; m > 0; m--) { + for (m = min_m; m <= max_m; m++) { n = (m * dotclock) / 3000; if ((n >= 9) && (n <= 127)) { @@ -373,9 +382,17 @@ static void sunxi_lcdc_pll_set(int dotclock, int *clk_div, int *clk_double) clock_set_pll3(best_n * 3000000); - 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 (tcon == 0) { + writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | + (best_double ? CCM_LCD_CH0_CTRL_PLL3_2X : + CCM_LCD_CH0_CTRL_PLL3), + &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); + } *clk_div = best_m; *clk_double = best_double; @@ -453,7 +470,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len), &lcdc->tcon1_timing_sync); - sunxi_lcdc_pll_set(mode->pixclock_khz, clk_div, clk_double); + sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double); } #ifdef CONFIG_MACH_SUN6I |