Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 13b3d727 authored by Jyri Sarha's avatar Jyri Sarha
Browse files

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: default avatarJyri Sarha <jsarha@ti.com>
Tested-by: default avatarBartosz Golaszewski <bgolaszewski@baylibre.com>
parent 2d53a180
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ struct tilcdc_crtc {

	int sync_lost_count;
	bool frame_intact;
	struct work_struct recover_work;
};
#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)

@@ -252,6 +253,25 @@ static bool tilcdc_crtc_is_on(struct drm_crtc *crtc)
	return crtc->state && crtc->state->enable && crtc->state->active;
}

static void tilcdc_crtc_recover_work(struct work_struct *work)
{
	struct tilcdc_crtc *tilcdc_crtc =
		container_of(work, struct tilcdc_crtc, recover_work);
	struct drm_crtc *crtc = &tilcdc_crtc->base;

	dev_info(crtc->dev->dev, "%s: Reset CRTC", __func__);

	drm_modeset_lock_crtc(crtc, NULL);

	if (!tilcdc_crtc_is_on(crtc))
		goto out;

	tilcdc_crtc_disable(crtc);
	tilcdc_crtc_enable(crtc);
out:
	drm_modeset_unlock_crtc(crtc);
}

static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
{
	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
@@ -838,9 +858,12 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
			tilcdc_crtc->frame_intact = false;
			if (tilcdc_crtc->sync_lost_count++ >
			    SYNC_LOST_COUNT_LIMIT) {
				dev_err(dev->dev, "%s(0x%08x): Sync lost flood detected, disabling the interrupt", __func__, stat);
				dev_err(dev->dev, "%s(0x%08x): Sync lost flood detected, recovering", __func__, stat);
				queue_work(system_wq,
					   &tilcdc_crtc->recover_work);
				tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG,
					     LCDC_SYNC_LOST);
				tilcdc_crtc->sync_lost_count = 0;
			}
		}

@@ -880,6 +903,7 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
			"unref", unref_worker);

	spin_lock_init(&tilcdc_crtc->irq_lock);
	INIT_WORK(&tilcdc_crtc->recover_work, tilcdc_crtc_recover_work);

	ret = drm_crtc_init_with_planes(dev, crtc,
					&tilcdc_crtc->primary,