Commit f97fd383 authored by Bartosz Golaszewski's avatar Bartosz Golaszewski Committed by Jyri Sarha

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: default avatarBartosz Golaszewski <bgolaszewski@baylibre.com>
Reviewed-by: default avatarJyri Sarha <jsarha@ti.com>
Signed-off-by: default avatarJyri Sarha <jsarha@ti.com>
parent 0186fcce
...@@ -856,7 +856,7 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc) ...@@ -856,7 +856,7 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_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;
uint32_t stat; uint32_t stat, reg;
stat = tilcdc_read_irqstatus(dev); stat = tilcdc_read_irqstatus(dev);
tilcdc_clear_irqstatus(dev, stat); tilcdc_clear_irqstatus(dev, stat);
...@@ -921,19 +921,28 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc) ...@@ -921,19 +921,28 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost", dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost",
__func__, stat); __func__, stat);
tilcdc_crtc->frame_intact = false; tilcdc_crtc->frame_intact = false;
if (priv->rev == 1) {
reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG);
if (reg & LCDC_RASTER_ENABLE) {
tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
LCDC_RASTER_ENABLE);
tilcdc_set(dev, LCDC_RASTER_CTRL_REG,
LCDC_RASTER_ENABLE);
}
} else {
if (tilcdc_crtc->sync_lost_count++ > if (tilcdc_crtc->sync_lost_count++ >
SYNC_LOST_COUNT_LIMIT) { SYNC_LOST_COUNT_LIMIT) {
dev_err(dev->dev, "%s(0x%08x): Sync lost flood detected, recovering", __func__, stat); dev_err(dev->dev,
queue_work(system_wq, &tilcdc_crtc->recover_work); "%s(0x%08x): Sync lost flood detected, recovering",
if (priv->rev == 1) __func__, stat);
tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, queue_work(system_wq,
LCDC_V1_SYNC_LOST_INT_ENA); &tilcdc_crtc->recover_work);
else
tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG, tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG,
LCDC_SYNC_LOST); LCDC_SYNC_LOST);
tilcdc_crtc->sync_lost_count = 0; tilcdc_crtc->sync_lost_count = 0;
} }
} }
}
if (stat & LCDC_FRAME_DONE) { if (stat & LCDC_FRAME_DONE) {
tilcdc_crtc->frame_done = true; tilcdc_crtc->frame_done = true;
......
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