diff options
author | Jyri Sarha <jsarha@ti.com> | 2016-09-06 09:19:54 -0400 |
---|---|---|
committer | Jyri Sarha <jsarha@ti.com> | 2016-09-07 08:54:40 -0400 |
commit | 642e51677d29c9f21891b571be4473ec482acaf0 (patch) | |
tree | c5ffe3c2821e677d1a8e24d446a8b9d9d97e37de /drivers/gpu/drm/tilcdc | |
parent | a6b7ebaadb5c8d869908e803e5616922a5096253 (diff) |
drm/tilcdc: Clean up LCDC functional clock rate setting code
Clean up LCDC functional clock rate setting code.
The LCDC functional clock is set by two functions: mode_set_nofb() and
cpufreq_transition().
When tilcdc_crtc_mode_set_nofb() is called in atomic commit phase the
drm atomic helpers have taken all the necessary drm locks and turned
off the crtc, while tilcdc_commit() is keeping LCDC powered on. For
mode_set_nofb() just a simple clock setting function without any
locking or power management code is enough. The new tilcdc_crtc_set_clk()
is implemented for that purpose.
cpufreq_transition() on the other hand is called from outside DRM and
it needs to take the necessary locks and turn off the CRTC while
keeping the LCDC powered. The reimplemented tilcdc_crtc_update_clk()
is for that purpose and it uses the new tilcdc_crtc_set_clk() to
actually set the clock.
Signed-off-by: Jyri Sarha <jsarha@ti.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/tilcdc')
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 77 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_drv.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_drv.h | 1 |
3 files changed, 47 insertions, 42 deletions
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 208768922030..5579d97b08e6 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c | |||
@@ -35,6 +35,8 @@ struct tilcdc_crtc { | |||
35 | bool frame_done; | 35 | bool frame_done; |
36 | spinlock_t irq_lock; | 36 | spinlock_t irq_lock; |
37 | 37 | ||
38 | unsigned int lcd_fck_rate; | ||
39 | |||
38 | ktime_t last_vblank; | 40 | ktime_t last_vblank; |
39 | 41 | ||
40 | struct drm_framebuffer *curr_fb; | 42 | struct drm_framebuffer *curr_fb; |
@@ -304,6 +306,37 @@ static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc, | |||
304 | return true; | 306 | return true; |
305 | } | 307 | } |
306 | 308 | ||
309 | static void tilcdc_crtc_set_clk(struct drm_crtc *crtc) | ||
310 | { | ||
311 | struct drm_device *dev = crtc->dev; | ||
312 | struct tilcdc_drm_private *priv = dev->dev_private; | ||
313 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); | ||
314 | const unsigned clkdiv = 2; /* using a fixed divider of 2 */ | ||
315 | int ret; | ||
316 | |||
317 | /* mode.clock is in KHz, set_rate wants parameter in Hz */ | ||
318 | ret = clk_set_rate(priv->clk, crtc->mode.clock * 1000 * clkdiv); | ||
319 | if (ret < 0) { | ||
320 | dev_err(dev->dev, "failed to set display clock rate to: %d\n", | ||
321 | crtc->mode.clock); | ||
322 | return; | ||
323 | } | ||
324 | |||
325 | tilcdc_crtc->lcd_fck_rate = clk_get_rate(priv->clk); | ||
326 | |||
327 | DBG("lcd_clk=%u, mode clock=%d, div=%u", | ||
328 | tilcdc_crtc->lcd_fck_rate, crtc->mode.clock, clkdiv); | ||
329 | |||
330 | /* Configure the LCD clock divisor. */ | ||
331 | tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(clkdiv) | | ||
332 | LCDC_RASTER_MODE); | ||
333 | |||
334 | if (priv->rev == 2) | ||
335 | tilcdc_set(dev, LCDC_CLK_ENABLE_REG, | ||
336 | LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN | | ||
337 | LCDC_V2_CORE_CLK_EN); | ||
338 | } | ||
339 | |||
307 | static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc) | 340 | static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc) |
308 | { | 341 | { |
309 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); | 342 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
@@ -466,7 +499,7 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc) | |||
466 | 499 | ||
467 | set_scanout(crtc, fb); | 500 | set_scanout(crtc, fb); |
468 | 501 | ||
469 | tilcdc_crtc_update_clk(crtc); | 502 | tilcdc_crtc_set_clk(crtc); |
470 | 503 | ||
471 | crtc->hwmode = crtc->state->adjusted_mode; | 504 | crtc->hwmode = crtc->state->adjusted_mode; |
472 | } | 505 | } |
@@ -635,41 +668,21 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc) | |||
635 | { | 668 | { |
636 | struct drm_device *dev = crtc->dev; | 669 | struct drm_device *dev = crtc->dev; |
637 | struct tilcdc_drm_private *priv = dev->dev_private; | 670 | struct tilcdc_drm_private *priv = dev->dev_private; |
638 | unsigned long lcd_clk; | 671 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
639 | const unsigned clkdiv = 2; /* using a fixed divider of 2 */ | ||
640 | int ret; | ||
641 | 672 | ||
642 | pm_runtime_get_sync(dev->dev); | 673 | drm_modeset_lock_crtc(crtc, NULL); |
674 | if (tilcdc_crtc->lcd_fck_rate != clk_get_rate(priv->clk)) { | ||
675 | if (tilcdc_crtc_is_on(crtc)) { | ||
676 | pm_runtime_get_sync(dev->dev); | ||
677 | tilcdc_crtc_disable(crtc); | ||
643 | 678 | ||
644 | tilcdc_crtc_disable(crtc); | 679 | tilcdc_crtc_set_clk(crtc); |
645 | 680 | ||
646 | /* mode.clock is in KHz, set_rate wants parameter in Hz */ | 681 | tilcdc_crtc_enable(crtc); |
647 | ret = clk_set_rate(priv->clk, crtc->mode.clock * 1000 * clkdiv); | 682 | pm_runtime_put_sync(dev->dev); |
648 | if (ret < 0) { | 683 | } |
649 | dev_err(dev->dev, "failed to set display clock rate to: %d\n", | ||
650 | crtc->mode.clock); | ||
651 | goto out; | ||
652 | } | 684 | } |
653 | 685 | drm_modeset_unlock_crtc(crtc); | |
654 | lcd_clk = clk_get_rate(priv->clk); | ||
655 | |||
656 | DBG("lcd_clk=%lu, mode clock=%d, div=%u", | ||
657 | lcd_clk, crtc->mode.clock, clkdiv); | ||
658 | |||
659 | /* Configure the LCD clock divisor. */ | ||
660 | tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(clkdiv) | | ||
661 | LCDC_RASTER_MODE); | ||
662 | |||
663 | if (priv->rev == 2) | ||
664 | tilcdc_set(dev, LCDC_CLK_ENABLE_REG, | ||
665 | LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN | | ||
666 | LCDC_V2_CORE_CLK_EN); | ||
667 | |||
668 | if (tilcdc_crtc_is_on(crtc)) | ||
669 | tilcdc_crtc_enable(crtc); | ||
670 | |||
671 | out: | ||
672 | pm_runtime_put_sync(dev->dev); | ||
673 | } | 686 | } |
674 | 687 | ||
675 | #define SYNC_LOST_COUNT_LIMIT 50 | 688 | #define SYNC_LOST_COUNT_LIMIT 50 |
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index b1ac61eac056..52ff3e120bb9 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c | |||
@@ -185,14 +185,8 @@ static int cpufreq_transition(struct notifier_block *nb, | |||
185 | struct tilcdc_drm_private *priv = container_of(nb, | 185 | struct tilcdc_drm_private *priv = container_of(nb, |
186 | struct tilcdc_drm_private, freq_transition); | 186 | struct tilcdc_drm_private, freq_transition); |
187 | 187 | ||
188 | if (val == CPUFREQ_POSTCHANGE) { | 188 | if (val == CPUFREQ_POSTCHANGE) |
189 | if (priv->lcd_fck_rate != clk_get_rate(priv->clk)) { | 189 | tilcdc_crtc_update_clk(priv->crtc); |
190 | drm_modeset_lock_crtc(priv->crtc, NULL); | ||
191 | priv->lcd_fck_rate = clk_get_rate(priv->clk); | ||
192 | tilcdc_crtc_update_clk(priv->crtc); | ||
193 | drm_modeset_unlock_crtc(priv->crtc); | ||
194 | } | ||
195 | } | ||
196 | 190 | ||
197 | return 0; | 191 | return 0; |
198 | } | 192 | } |
@@ -286,7 +280,6 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) | |||
286 | } | 280 | } |
287 | 281 | ||
288 | #ifdef CONFIG_CPU_FREQ | 282 | #ifdef CONFIG_CPU_FREQ |
289 | priv->lcd_fck_rate = clk_get_rate(priv->clk); | ||
290 | priv->freq_transition.notifier_call = cpufreq_transition; | 283 | priv->freq_transition.notifier_call = cpufreq_transition; |
291 | ret = cpufreq_register_notifier(&priv->freq_transition, | 284 | ret = cpufreq_register_notifier(&priv->freq_transition, |
292 | CPUFREQ_TRANSITION_NOTIFIER); | 285 | CPUFREQ_TRANSITION_NOTIFIER); |
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index a6e5e6d4970c..9780c37ec4cd 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h | |||
@@ -74,7 +74,6 @@ struct tilcdc_drm_private { | |||
74 | 74 | ||
75 | #ifdef CONFIG_CPU_FREQ | 75 | #ifdef CONFIG_CPU_FREQ |
76 | struct notifier_block freq_transition; | 76 | struct notifier_block freq_transition; |
77 | unsigned int lcd_fck_rate; | ||
78 | #endif | 77 | #endif |
79 | 78 | ||
80 | struct workqueue_struct *wq; | 79 | struct workqueue_struct *wq; |