From 61dd13b44435166c5136bd1e5b76a265bd9cddaf Mon Sep 17 00:00:00 2001 From: Cihangir Akturk Date: Thu, 3 Aug 2017 14:58:38 +0300 Subject: drm/tilcdc: switch to drm_*{get,put} helpers drm_*_reference() and drm_*_unreference() functions are just compatibility alias for drm_*_get() and drm_*_put() adn should not be used by new code. So convert all users of compatibility functions to use the new APIs. Signed-off-by: Cihangir Akturk Signed-off-by: Jyri Sarha --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/tilcdc/tilcdc_crtc.c') diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 406fe4544b83..d2589f310437 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -75,7 +75,7 @@ static void unref_worker(struct drm_flip_work *work, void *val) struct drm_device *dev = tilcdc_crtc->base.dev; mutex_lock(&dev->mode_config.mutex); - drm_framebuffer_unreference(val); + drm_framebuffer_put(val); mutex_unlock(&dev->mode_config.mutex); } @@ -456,7 +456,7 @@ static void tilcdc_crtc_set_mode(struct drm_crtc *crtc) set_scanout(crtc, fb); - drm_framebuffer_reference(fb); + drm_framebuffer_get(fb); crtc->hwmode = crtc->state->adjusted_mode; } @@ -633,7 +633,7 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc, return -EBUSY; } - drm_framebuffer_reference(fb); + drm_framebuffer_get(fb); crtc->primary->fb = fb; tilcdc_crtc->event = event; -- cgit v1.2.3 From 46a956ab3c5be9141b75c0a6d8a754bdd4426577 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Fri, 26 May 2017 13:20:17 +0300 Subject: drm/tilcdc: Turn raster off in crtc reset, if it was on in the HW This forces the HW to be in sync with the empty state. This should help with the problem when LCDC is already enabled (e.g. by the bootloader) at the initialization phase and the enable fails when a new mode is applied. Signed-off-by: Jyri Sarha --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/tilcdc/tilcdc_crtc.c') diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index d2589f310437..0533fbeefafc 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -728,11 +728,39 @@ static void tilcdc_crtc_disable_vblank(struct drm_crtc *crtc) { } +static void tilcdc_crtc_reset(struct drm_crtc *crtc) +{ + struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); + struct drm_device *dev = crtc->dev; + int ret; + + drm_atomic_helper_crtc_reset(crtc); + + /* Turn the raster off if it for some reason is on. */ + pm_runtime_get_sync(dev->dev); + if (tilcdc_read(dev, LCDC_RASTER_CTRL_REG) & LCDC_RASTER_ENABLE) { + /* Enable DMA Frame Done Interrupt */ + tilcdc_write(dev, LCDC_INT_ENABLE_SET_REG, LCDC_FRAME_DONE); + tilcdc_clear_irqstatus(dev, 0xffffffff); + + tilcdc_crtc->frame_done = false; + tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); + + ret = wait_event_timeout(tilcdc_crtc->frame_done_wq, + tilcdc_crtc->frame_done, + msecs_to_jiffies(500)); + if (ret == 0) + dev_err(dev->dev, "%s: timeout waiting for framedone\n", + __func__); + } + pm_runtime_put_sync(dev->dev); +} + static const struct drm_crtc_funcs tilcdc_crtc_funcs = { .destroy = tilcdc_crtc_destroy, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, - .reset = drm_atomic_helper_crtc_reset, + .reset = tilcdc_crtc_reset, .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, .enable_vblank = tilcdc_crtc_enable_vblank, -- cgit v1.2.3 From 125fcc19dad5a0ac9d3f2e4ceb7827951d31ccc7 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 29 May 2017 22:06:26 +0300 Subject: drm/tilcdc: Remove WARN_ON(!drm_modeset_is_locked(&crtc->mutex)) checks Remove WARN_ON(!drm_modeset_is_locked(&crtc->mutex)) checks from tilcdc_crtc_enable(), tilcdc_crtc_disable(), and tilcdc_crtc_update_fb(). Signed-off-by: Jyri Sarha --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu/drm/tilcdc/tilcdc_crtc.c') diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 0533fbeefafc..4bc5d848cdd1 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -467,7 +467,6 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc) struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); unsigned long flags; - WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); mutex_lock(&tilcdc_crtc->enable_lock); if (tilcdc_crtc->enabled || tilcdc_crtc->shutdown) { mutex_unlock(&tilcdc_crtc->enable_lock); @@ -564,7 +563,6 @@ static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown) static void tilcdc_crtc_disable(struct drm_crtc *crtc) { - WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); tilcdc_crtc_off(crtc, false); } @@ -626,8 +624,6 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc, struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); struct drm_device *dev = crtc->dev; - WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); - if (tilcdc_crtc->event) { dev_err(dev->dev, "already pending page flip!\n"); return -EBUSY; -- cgit v1.2.3 From ba3fd954f0b4c2df1e0d7e243cb6735c6f4c5bdc Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 29 May 2017 22:09:44 +0300 Subject: drm/tilcdc: Use tilcdc_crtc_shutdown() in tilcdc_crtc_destroy() Use tilcdc_crtc_shutdown() instead of tilcdc_crtc_disable() in tilcdc_crtc_destroy() and remove the modeset locking. Signed-off-by: Jyri Sarha --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/gpu/drm/tilcdc/tilcdc_crtc.c') diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 4bc5d848cdd1..704db2443b5e 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -606,9 +606,7 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc) struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); struct tilcdc_drm_private *priv = crtc->dev->dev_private; - drm_modeset_lock(&crtc->mutex, NULL); - tilcdc_crtc_disable(crtc); - drm_modeset_unlock(&crtc->mutex); + tilcdc_crtc_shutdown(crtc); flush_workqueue(priv->wq); -- cgit v1.2.3 From ce99f7206c9105851d97202ed08c058af6f11ac4 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 12 Oct 2017 12:19:46 +0300 Subject: drm/tilcdc: Precalculate total frametime in tilcdc_crtc_set_mode() We need the total frame refresh time to check if we are too close to vertical sync when updating the two framebuffer DMA registers and risk a collision. This new method is more accurate that the previous that based on mode's vrefresh value, which itself is inaccurate or may not even be initialized. Reported-by: Kevin Hao Fixes: 11abbc9f39e0 ("drm/tilcdc: Set framebuffer DMA address to HW only if CRTC is enabled") Cc: # v4.11+ Signed-off-by: Jyri Sarha Reviewed-by: Tomi Valkeinen --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/tilcdc/tilcdc_crtc.c') diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 704db2443b5e..6ef4d1a1e3a9 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "tilcdc_drv.h" #include "tilcdc_regs.h" @@ -48,6 +49,7 @@ struct tilcdc_crtc { unsigned int lcd_fck_rate; ktime_t last_vblank; + unsigned int hvtotal_us; struct drm_framebuffer *curr_fb; struct drm_framebuffer *next_fb; @@ -292,6 +294,12 @@ static void tilcdc_crtc_set_clk(struct drm_crtc *crtc) LCDC_V2_CORE_CLK_EN); } +uint tilcdc_mode_hvtotal(const struct drm_display_mode *mode) +{ + return (uint) div_u64(1000llu * mode->htotal * mode->vtotal, + mode->clock); +} + static void tilcdc_crtc_set_mode(struct drm_crtc *crtc) { struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); @@ -459,6 +467,9 @@ static void tilcdc_crtc_set_mode(struct drm_crtc *crtc) drm_framebuffer_get(fb); crtc->hwmode = crtc->state->adjusted_mode; + + tilcdc_crtc->hvtotal_us = + tilcdc_mode_hvtotal(&crtc->hwmode); } static void tilcdc_crtc_enable(struct drm_crtc *crtc) @@ -642,7 +653,7 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc, spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags); next_vblank = ktime_add_us(tilcdc_crtc->last_vblank, - 1000000 / crtc->hwmode.vrefresh); + tilcdc_crtc->hvtotal_us); tdiff = ktime_to_us(ktime_sub(next_vblank, ktime_get())); if (tdiff < TILCDC_VBLANK_SAFETY_THRESHOLD_US) -- cgit v1.2.3