Commit 3d19306a authored by Darren Etheridge's avatar Darren Etheridge Committed by Jyri Sarha

drm/tilcdc: rewrite pixel clock calculation

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: default avatarDarren Etheridge <detheridge@ti.com>
[Rewrapped description]
Signed-off-by: default avatarJyri Sarha <jsarha@ti.com>
Reviewed-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
parent 0041ee4d
...@@ -573,7 +573,8 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc) ...@@ -573,7 +573,8 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct tilcdc_drm_private *priv = dev->dev_private; struct tilcdc_drm_private *priv = dev->dev_private;
int dpms = tilcdc_crtc->dpms; 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; int ret;
pm_runtime_get_sync(dev->dev); pm_runtime_get_sync(dev->dev);
...@@ -581,22 +582,21 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc) ...@@ -581,22 +582,21 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
if (dpms == DRM_MODE_DPMS_ON) if (dpms == DRM_MODE_DPMS_ON)
tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
/* in raster mode, minimum divisor is 2: */ /* mode.clock is in KHz, set_rate wants parameter in Hz */
ret = clk_set_rate(priv->disp_clk, crtc->mode.clock * 1000 * 2); ret = clk_set_rate(priv->clk, crtc->mode.clock * 1000 * clkdiv);
if (ret) { if (ret < 0) {
dev_err(dev->dev, "failed to set display clock rate to: %d\n", dev_err(dev->dev, "failed to set display clock rate to: %d\n",
crtc->mode.clock); crtc->mode.clock);
goto out; goto out;
} }
lcd_clk = clk_get_rate(priv->clk); 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("lcd_clk=%lu, mode clock=%d, div=%u",
DBG("fck=%lu, dpll_disp_ck=%lu", clk_get_rate(priv->clk), clk_get_rate(priv->disp_clk)); lcd_clk, crtc->mode.clock, clkdiv);
/* Configure the LCD clock divisor. */ /* 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); LCDC_RASTER_MODE);
if (priv->rev == 2) if (priv->rev == 2)
......
...@@ -192,13 +192,6 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) ...@@ -192,13 +192,6 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
goto fail_iounmap; 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 #ifdef CONFIG_CPU_FREQ
priv->lcd_fck_rate = clk_get_rate(priv->clk); priv->lcd_fck_rate = clk_get_rate(priv->clk);
priv->freq_transition.notifier_call = cpufreq_transition; priv->freq_transition.notifier_call = cpufreq_transition;
...@@ -206,7 +199,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) ...@@ -206,7 +199,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
CPUFREQ_TRANSITION_NOTIFIER); CPUFREQ_TRANSITION_NOTIFIER);
if (ret) { if (ret) {
dev_err(dev->dev, "failed to register cpufreq notifier\n"); dev_err(dev->dev, "failed to register cpufreq notifier\n");
goto fail_put_disp_clk; goto fail_put_clk;
} }
#endif #endif
...@@ -330,8 +323,6 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) ...@@ -330,8 +323,6 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
cpufreq_unregister_notifier(&priv->freq_transition, cpufreq_unregister_notifier(&priv->freq_transition,
CPUFREQ_TRANSITION_NOTIFIER); CPUFREQ_TRANSITION_NOTIFIER);
fail_put_disp_clk:
clk_put(priv->disp_clk);
#endif #endif
fail_put_clk: fail_put_clk:
......
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
struct tilcdc_drm_private { struct tilcdc_drm_private {
void __iomem *mmio; void __iomem *mmio;
struct clk *disp_clk; /* display dpll */
struct clk *clk; /* functional clock */ struct clk *clk; /* functional clock */
int rev; /* IP revision */ int rev; /* IP revision */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment