drm/tilcdc: rewrite pixel clock calculation
authorDarren Etheridge <detheridge@ti.com>
Wed, 15 Jan 2014 21:52:36 +0000 (15:52 -0600)
committerJyri Sarha <jsarha@ti.com>
Thu, 25 Feb 2016 14:39:28 +0000 (16:39 +0200)
Updating the tilcdc DRM driver code to calculate the LCD controller
pixel clock more accurately. Based on a suggested implementation by
Tomi Valkeinen.

The current code does not work correctly and produces wrong results
with many requested clock rates. It also oddly uses two different
clocks, a display pll clock and a divider clock (child of display
pll), instead of just using the clock coming to the lcdc.

This patch removes the use of the display pll clock, and rewrites the
code to calculate the clock rates. The idea is simply to request a
clock rate of pixelclock*2, as the LCD controller has an internal
divider which we set to 2.

Signed-off-by: Darren Etheridge <detheridge@ti.com>
[Rewrapped description]
Signed-off-by: Jyri Sarha <jsarha@ti.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
drivers/gpu/drm/tilcdc/tilcdc_drv.c
drivers/gpu/drm/tilcdc/tilcdc_drv.h

index 4802da8e6d6f989cd796b98eb4e32f2012f29bcc..aaf8989810b1827713a728f20af2820b5ca6f4d3 100644 (file)
@@ -573,7 +573,8 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        struct tilcdc_drm_private *priv = dev->dev_private;
        int dpms = tilcdc_crtc->dpms;
-       unsigned int lcd_clk, div;
+       unsigned long lcd_clk;
+       const unsigned clkdiv = 2; /* using a fixed divider of 2 */
        int ret;
 
        pm_runtime_get_sync(dev->dev);
@@ -581,22 +582,21 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
        if (dpms == DRM_MODE_DPMS_ON)
                tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 
-       /* in raster mode, minimum divisor is 2: */
-       ret = clk_set_rate(priv->disp_clk, crtc->mode.clock * 1000 * 2);
-       if (ret) {
+       /* mode.clock is in KHz, set_rate wants parameter in Hz */
+       ret = clk_set_rate(priv->clk, crtc->mode.clock * 1000 * clkdiv);
+       if (ret < 0) {
                dev_err(dev->dev, "failed to set display clock rate to: %d\n",
                                crtc->mode.clock);
                goto out;
        }
 
        lcd_clk = clk_get_rate(priv->clk);
-       div = lcd_clk / (crtc->mode.clock * 1000);
 
-       DBG("lcd_clk=%u, mode clock=%d, div=%u", lcd_clk, crtc->mode.clock, div);
-       DBG("fck=%lu, dpll_disp_ck=%lu", clk_get_rate(priv->clk), clk_get_rate(priv->disp_clk));
+       DBG("lcd_clk=%lu, mode clock=%d, div=%u",
+               lcd_clk, crtc->mode.clock, clkdiv);
 
        /* Configure the LCD clock divisor. */
-       tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(div) |
+       tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(clkdiv) |
                        LCDC_RASTER_MODE);
 
        if (priv->rev == 2)
index 8190ac3b1b3225dcffb1fd2944cec9dd5104f36a..b3dbbe9d652eba3242749fab3db3e5838dcccffe 100644 (file)
@@ -192,13 +192,6 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
                goto fail_iounmap;
        }
 
-       priv->disp_clk = clk_get(dev->dev, "dpll_disp_ck");
-       if (IS_ERR(priv->clk)) {
-               dev_err(dev->dev, "failed to get display clock\n");
-               ret = -ENODEV;
-               goto fail_put_clk;
-       }
-
 #ifdef CONFIG_CPU_FREQ
        priv->lcd_fck_rate = clk_get_rate(priv->clk);
        priv->freq_transition.notifier_call = cpufreq_transition;
@@ -206,7 +199,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
                        CPUFREQ_TRANSITION_NOTIFIER);
        if (ret) {
                dev_err(dev->dev, "failed to register cpufreq notifier\n");
-               goto fail_put_disp_clk;
+               goto fail_put_clk;
        }
 #endif
 
@@ -330,8 +323,6 @@ fail_cpufreq_unregister:
 #ifdef CONFIG_CPU_FREQ
        cpufreq_unregister_notifier(&priv->freq_transition,
                        CPUFREQ_TRANSITION_NOTIFIER);
-fail_put_disp_clk:
-       clk_put(priv->disp_clk);
 #endif
 
 fail_put_clk:
index 66105d8dc62062a426b7d44849b2a781c31d81be..62a1d688e6b36e7bb1a71ea3ff5f007953f05bc1 100644 (file)
@@ -49,7 +49,6 @@
 struct tilcdc_drm_private {
        void __iomem *mmio;
 
-       struct clk *disp_clk;    /* display dpll */
        struct clk *clk;         /* functional clock */
        int rev;                 /* IP revision */