From: Mans Rullgard Date: Fri, 29 Aug 2008 01:34:39 +0000 (+0100) Subject: OMAP: Improve pixel clock configuration X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=01c2d720e59c291de9eb21eb65225f2f215fef84 OMAP: Improve pixel clock configuration This sets the DSS1_ALWON_FCLK clock as close as possible to a multiple of the requested pixel clock, while keeping it below the 173MHz limit. Due to of the structure of the clock tree, dss1_alwon_fck cannot be set directly, and we must use dpll4_m4_ck instead. Signed-off-by: Mans Rullgard --- diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c index 64bf333..888d2c2 100644 --- a/drivers/video/omap/dispc.c +++ b/drivers/video/omap/dispc.c @@ -177,6 +177,7 @@ static struct { struct clk *dss_ick, *dss1_fck; struct clk *dss_54m_fck; + struct clk *dpll4_m4_ck; enum omapfb_update_mode update_mode; struct omapfb_device *fbdev; @@ -736,19 +737,34 @@ static void setup_color_conv_coef(void) MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range); } +#define MAX_FCK 173000000 + static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div) { + unsigned long prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); + unsigned long pcd_min = is_tft? 2: 3; + unsigned long fck_div; unsigned long fck, lck; - *lck_div = 1; pck = max(1, pck); + + if (pck * pcd_min > MAX_FCK) { + dev_warn(dispc.fbdev->dev, "pixclock %d kHz too high.\n", + pck / 1000); + pck = MAX_FCK / pcd_min; + } + + fck = pck * 2; + fck_div = (prate + pck) / fck; + if (fck_div > 16) + fck_div /= (fck_div + 15) / 16; + if (fck_div < 1) + fck_div = 1; + clk_set_rate(dispc.dpll4_m4_ck, prate / fck_div); fck = clk_get_rate(dispc.dss1_fck); - lck = fck; - *pck_div = (lck + pck - 1) / pck; - if (is_tft) - *pck_div = max(2, *pck_div); - else - *pck_div = max(3, *pck_div); + + *lck_div = 1; + *pck_div = (fck + pck - 1) / pck; if (*pck_div > 255) { *pck_div = 255; lck = pck * *pck_div; @@ -909,11 +925,21 @@ static int get_dss_clocks(void) return PTR_ERR(dispc.dss_54m_fck); } + if (IS_ERR((dispc.dpll4_m4_ck = + clk_get(dispc.fbdev->dev, "dpll4_m4_ck")))) { + dev_err(dispc.fbdev->dev, "can't get dpll4_m4_ck"); + clk_put(dispc.dss_ick); + clk_put(dispc.dss1_fck); + clk_put(dispc.dss_54m_fck); + return PTR_ERR(dispc.dss_54m_fck); + } + return 0; } static void put_dss_clocks(void) { + clk_put(dispc.dpll4_m4_ck); clk_put(dispc.dss_54m_fck); clk_put(dispc.dss1_fck); clk_put(dispc.dss_ick);