aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJyri Sarha <jsarha@ti.com>2016-04-06 07:02:38 -0400
committerJyri Sarha <jsarha@ti.com>2016-11-30 07:14:40 -0500
commit13b3d72705817cdcf003226dd9f22f3ecee64ba4 (patch)
tree6ea4f220a76be5661e7d485c97736c93aecacbea
parent2d53a18098e5a03a30b1b1419ab4103357b69f0d (diff)
drm/tilcdc: Recover from sync lost error flood by resetting the LCDC
Recover from sync lost error flood by resetting the LCDC instead of turning off the SYNC_LOST error IRQ. When LCDC starves on limited memory bandwidth it may sometimes result an error situation when the picture may have shifted couple of pixels to right and SYNC_LOST interrupt is generated on every frame. LCDC main reset recovers from this situation and causes a brief blanking on the screen. Signed-off-by: Jyri Sarha <jsarha@ti.com> Tested-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_crtc.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index 0d09acce4916..c7873493f506 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -55,6 +55,7 @@ struct tilcdc_crtc {
55 55
56 int sync_lost_count; 56 int sync_lost_count;
57 bool frame_intact; 57 bool frame_intact;
58 struct work_struct recover_work;
58}; 59};
59#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base) 60#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)
60 61
@@ -252,6 +253,25 @@ static bool tilcdc_crtc_is_on(struct drm_crtc *crtc)
252 return crtc->state && crtc->state->enable && crtc->state->active; 253 return crtc->state && crtc->state->enable && crtc->state->active;
253} 254}
254 255
256static void tilcdc_crtc_recover_work(struct work_struct *work)
257{
258 struct tilcdc_crtc *tilcdc_crtc =
259 container_of(work, struct tilcdc_crtc, recover_work);
260 struct drm_crtc *crtc = &tilcdc_crtc->base;
261
262 dev_info(crtc->dev->dev, "%s: Reset CRTC", __func__);
263
264 drm_modeset_lock_crtc(crtc, NULL);
265
266 if (!tilcdc_crtc_is_on(crtc))
267 goto out;
268
269 tilcdc_crtc_disable(crtc);
270 tilcdc_crtc_enable(crtc);
271out:
272 drm_modeset_unlock_crtc(crtc);
273}
274
255static void tilcdc_crtc_destroy(struct drm_crtc *crtc) 275static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
256{ 276{
257 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 277 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
@@ -838,9 +858,12 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
838 tilcdc_crtc->frame_intact = false; 858 tilcdc_crtc->frame_intact = false;
839 if (tilcdc_crtc->sync_lost_count++ > 859 if (tilcdc_crtc->sync_lost_count++ >
840 SYNC_LOST_COUNT_LIMIT) { 860 SYNC_LOST_COUNT_LIMIT) {
841 dev_err(dev->dev, "%s(0x%08x): Sync lost flood detected, disabling the interrupt", __func__, stat); 861 dev_err(dev->dev, "%s(0x%08x): Sync lost flood detected, recovering", __func__, stat);
862 queue_work(system_wq,
863 &tilcdc_crtc->recover_work);
842 tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG, 864 tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG,
843 LCDC_SYNC_LOST); 865 LCDC_SYNC_LOST);
866 tilcdc_crtc->sync_lost_count = 0;
844 } 867 }
845 } 868 }
846 869
@@ -880,6 +903,7 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
880 "unref", unref_worker); 903 "unref", unref_worker);
881 904
882 spin_lock_init(&tilcdc_crtc->irq_lock); 905 spin_lock_init(&tilcdc_crtc->irq_lock);
906 INIT_WORK(&tilcdc_crtc->recover_work, tilcdc_crtc_recover_work);
883 907
884 ret = drm_crtc_init_with_planes(dev, crtc, 908 ret = drm_crtc_init_with_planes(dev, crtc,
885 &tilcdc_crtc->primary, 909 &tilcdc_crtc->primary,