Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Bartosz Golaszewski and committed by
Jyri Sarha
f97fd383 0186fcce

+18 -9
+18 -9
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
··· 856 856 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 857 857 struct drm_device *dev = crtc->dev; 858 858 struct tilcdc_drm_private *priv = dev->dev_private; 859 - uint32_t stat; 859 + uint32_t stat, reg; 860 860 861 861 stat = tilcdc_read_irqstatus(dev); 862 862 tilcdc_clear_irqstatus(dev, stat); ··· 921 921 dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost", 922 922 __func__, stat); 923 923 tilcdc_crtc->frame_intact = false; 924 - if (tilcdc_crtc->sync_lost_count++ > 925 - SYNC_LOST_COUNT_LIMIT) { 926 - dev_err(dev->dev, "%s(0x%08x): Sync lost flood detected, recovering", __func__, stat); 927 - queue_work(system_wq, &tilcdc_crtc->recover_work); 928 - if (priv->rev == 1) 924 + if (priv->rev == 1) { 925 + reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG); 926 + if (reg & LCDC_RASTER_ENABLE) { 929 927 tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, 930 - LCDC_V1_SYNC_LOST_INT_ENA); 931 - else 928 + LCDC_RASTER_ENABLE); 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 940 tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG, 933 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