drm/msm/sde: turn on clock before esd failure mitigation
Turn on mdp and rsc clocks before updating te
vsync source on MDSS hardware to mitigate the
esd failure.
Change-Id: Idf53f4231231b914d6e6472b06b68b9f745694ad
Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index e35a46b..1614c83 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -203,6 +203,7 @@
* clks and resources after IDLE_TIMEOUT time.
* @vsync_event_work: worker to handle vsync event for autorefresh
* @input_event_work: worker to handle input device touch events
+ * @esd_trigger_work: worker to handle esd trigger events
* @input_handler: handler for input device events
* @topology: topology of the display
* @vblank_enabled: boolean to track userspace vblank vote
@@ -249,6 +250,7 @@
struct kthread_delayed_work delayed_off_work;
struct kthread_work vsync_event_work;
struct kthread_work input_event_work;
+ struct kthread_work esd_trigger_work;
struct input_handler *input_handler;
struct msm_display_topology topology;
bool vblank_enabled;
@@ -3539,6 +3541,20 @@
&sde_enc->vsync_event_work);
}
+static void sde_encoder_esd_trigger_work_handler(struct kthread_work *work)
+{
+ struct sde_encoder_virt *sde_enc = container_of(work,
+ struct sde_encoder_virt, esd_trigger_work);
+
+ if (!sde_enc) {
+ SDE_ERROR("invalid sde encoder\n");
+ return;
+ }
+
+ sde_encoder_resource_control(&sde_enc->base,
+ SDE_ENC_RC_EVENT_KICKOFF);
+}
+
static void sde_encoder_input_event_work_handler(struct kthread_work *work)
{
struct sde_encoder_virt *sde_enc = container_of(work,
@@ -4528,6 +4544,9 @@
kthread_init_work(&sde_enc->input_event_work,
sde_encoder_input_event_work_handler);
+ kthread_init_work(&sde_enc->esd_trigger_work,
+ sde_encoder_esd_trigger_work_handler);
+
memcpy(&sde_enc->disp_info, disp_info, sizeof(*disp_info));
SDE_DEBUG_ENC(sde_enc, "created\n");
@@ -4789,6 +4808,33 @@
int sde_encoder_display_failure_notification(struct drm_encoder *enc)
{
+ struct msm_drm_thread *disp_thread = NULL;
+ struct msm_drm_private *priv = NULL;
+ struct sde_encoder_virt *sde_enc = NULL;
+
+ if (!enc || !enc->dev || !enc->dev->dev_private) {
+ SDE_ERROR("invalid parameters\n");
+ return -EINVAL;
+ }
+
+ priv = enc->dev->dev_private;
+ sde_enc = to_sde_encoder_virt(enc);
+ if (!sde_enc->crtc || (sde_enc->crtc->index
+ >= ARRAY_SIZE(priv->disp_thread))) {
+ SDE_DEBUG_ENC(sde_enc,
+ "invalid cached CRTC: %d or crtc index: %d\n",
+ sde_enc->crtc == NULL,
+ sde_enc->crtc ? sde_enc->crtc->index : -EINVAL);
+ return -EINVAL;
+ }
+
+ SDE_EVT32_VERBOSE(DRMID(enc));
+
+ disp_thread = &priv->disp_thread[sde_enc->crtc->index];
+
+ kthread_queue_work(&disp_thread->worker,
+ &sde_enc->esd_trigger_work);
+ kthread_flush_work(&sde_enc->esd_trigger_work);
/**
* panel may stop generating te signal (vsync) during esd failure. rsc
* hardware may hang without vsync. Avoid rsc hang by generating the