diff options
author | Bartosz Golaszewski <bgolaszewski@baylibre.com> | 2016-12-19 09:47:14 -0500 |
---|---|---|
committer | Jyri Sarha <jsarha@ti.com> | 2017-01-04 03:22:16 -0500 |
commit | f97fd383d9a10fd125bcdafba03240685aed5608 (patch) | |
tree | 563453aa96a8ee6c1f3a68b0be6583a5525709c1 | |
parent | 0186fcce896d3cb6fb690ed8b4405c9c1b76977a (diff) |
drm: tilcdc: simplify the recovery from sync lost error on rev1
Revision 2 of LCDC suffers from an issue where a SYNC_LOST error
caused by limited memory bandwidth may leave the picture shifted a
couple pixels to the right.
This issue has not been observed on revision 1, while the recovery
mechanism introduces a different issue, where the END_OF_FRAME
interrupt doesn't fire while drm is waiting for vblanks.
On rev1: recover from sync lost errors by simply clearing the
RASTER_ENABLE bit in the RASTER_CTRL register and re-enabling it
again as is suggested by the datasheet.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Reviewed-by: Jyri Sarha <jsarha@ti.com>
Signed-off-by: Jyri Sarha <jsarha@ti.com>
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 9942b0577d6e..20041073e46d 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c | |||
@@ -856,7 +856,7 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc) | |||
856 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); | 856 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
857 | struct drm_device *dev = crtc->dev; | 857 | struct drm_device *dev = crtc->dev; |
858 | struct tilcdc_drm_private *priv = dev->dev_private; | 858 | struct tilcdc_drm_private *priv = dev->dev_private; |
859 | uint32_t stat; | 859 | uint32_t stat, reg; |
860 | 860 | ||
861 | stat = tilcdc_read_irqstatus(dev); | 861 | stat = tilcdc_read_irqstatus(dev); |
862 | tilcdc_clear_irqstatus(dev, stat); | 862 | tilcdc_clear_irqstatus(dev, stat); |
@@ -921,17 +921,26 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc) | |||
921 | dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost", | 921 | dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost", |
922 | __func__, stat); | 922 | __func__, stat); |
923 | tilcdc_crtc->frame_intact = false; | 923 | tilcdc_crtc->frame_intact = false; |
924 | if (tilcdc_crtc->sync_lost_count++ > | 924 | if (priv->rev == 1) { |
925 | SYNC_LOST_COUNT_LIMIT) { | 925 | reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG); |
926 | dev_err(dev->dev, "%s(0x%08x): Sync lost flood detected, recovering", __func__, stat); | 926 | if (reg & LCDC_RASTER_ENABLE) { |
927 | queue_work(system_wq, &tilcdc_crtc->recover_work); | ||
928 | if (priv->rev == 1) | ||
929 | tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, | 927 | tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, |
930 | LCDC_V1_SYNC_LOST_INT_ENA); | 928 | LCDC_RASTER_ENABLE); |
931 | else | 929 | tilcdc_set(dev, LCDC_RASTER_CTRL_REG, |
930 | LCDC_RASTER_ENABLE); | ||
931 | } | ||
932 | } else { | ||
933 | if (tilcdc_crtc->sync_lost_count++ > | ||
934 | SYNC_LOST_COUNT_LIMIT) { | ||
935 | dev_err(dev->dev, | ||
936 | "%s(0x%08x): Sync lost flood detected, recovering", | ||
937 | __func__, stat); | ||
938 | queue_work(system_wq, | ||
939 | &tilcdc_crtc->recover_work); | ||
932 | tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG, | 940 | tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG, |
933 | LCDC_SYNC_LOST); | 941 | LCDC_SYNC_LOST); |
934 | tilcdc_crtc->sync_lost_count = 0; | 942 | tilcdc_crtc->sync_lost_count = 0; |
943 | } | ||
935 | } | 944 | } |
936 | } | 945 | } |
937 | 946 | ||