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

Commit d1ba18d5 authored by Dhaval Patel's avatar Dhaval Patel Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm/sde: handle esd recovery in sde encoder



Panel may stop sending TE signal when esd check
fail. That leads to pp timeout and rsc in hang
state. RSC hang state can be avoid by changing
the vsync source to watchdog timer. Vsync source
reset to panel TE when DRM client reset the
display after receiving the panel dead event.
PingPong timeout should also trigger the retire
fence during esd failure because ctl_start IRQ
might be missed.

Change-Id: I22f5cffcb1f3e71839a9cb3ca8e62f3a4489003b
Signed-off-by: default avatarChandan Uddaraju <chandanu@codeaurora.org>
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent 11822d11
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1726,6 +1726,7 @@ static void sde_connector_check_status_work(struct work_struct *work)
	event.length = sizeof(bool);
	msm_mode_object_event_notify(&conn->base.base,
		conn->base.dev, &event, (u8 *)&panel_dead);
	sde_encoder_display_failure_notification(conn->encoder);
}

static const struct drm_connector_helper_funcs sde_connector_helper_ops = {
+43 −1
Original line number Diff line number Diff line
@@ -1681,6 +1681,29 @@ static int _sde_encoder_dsc_disable(struct sde_encoder_virt *sde_enc)
	return ret;
}

static int _sde_encoder_switch_to_watchdog_vsync(struct drm_encoder *drm_enc)
{
	struct sde_encoder_virt *sde_enc;
	struct msm_display_info disp_info;

	if (!drm_enc) {
		pr_err("invalid drm encoder\n");
		return -EINVAL;
	}

	sde_enc = to_sde_encoder_virt(drm_enc);

	sde_encoder_control_te(drm_enc, false);

	memcpy(&disp_info, &sde_enc->disp_info, sizeof(disp_info));
	disp_info.is_te_using_watchdog_timer = true;
	_sde_encoder_update_vsync_source(sde_enc, &disp_info, false);

	sde_encoder_control_te(drm_enc, true);

	return 0;
}

static int _sde_encoder_update_rsc_client(
		struct drm_encoder *drm_enc,
		struct sde_encoder_rsc_config *config, bool enable)
@@ -1820,7 +1843,12 @@ static int _sde_encoder_update_rsc_client(
		if (ret) {
			SDE_ERROR_ENC(sde_enc,
					"wait for vblank failed ret:%d\n", ret);
			break;
			/**
			 * rsc hardware may hang without vsync. avoid rsc hang
			 * by generating the vsync from watchdog timer.
			 */
			if (crtc->base.id == wait_vblank_crtc_id)
				_sde_encoder_switch_to_watchdog_vsync(drm_enc);
		}
	}

@@ -4936,3 +4964,17 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder)

	return ret;
}

int sde_encoder_display_failure_notification(struct drm_encoder *enc)
{
	/**
	 * panel may stop generating te signal (vsync) during esd failure. rsc
	 * hardware may hang without vsync. Avoid rsc hang by generating the
	 * vsync from watchdog timer instead of panel.
	 */
	_sde_encoder_switch_to_watchdog_vsync(enc);

	sde_encoder_wait_for_event(enc, MSM_ENC_TX_COMPLETE);

	return 0;
}
+10 −0
Original line number Diff line number Diff line
@@ -237,4 +237,14 @@ void sde_encoder_prepare_commit(struct drm_encoder *drm_enc);
 */
int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder);

/**
 * sde_encoder_display_failure_notification - update sde encoder state for
 * esd timeout or other display failure notification. This event flows from
 * dsi, sde_connector to sde_encoder.
 *      TODO: manage the event at sde_kms level for forward processing.
 * @drm_enc:    Pointer to drm encoder structure
 * @Return:     true if successful in updating the encoder structure
 */
int sde_encoder_display_failure_notification(struct drm_encoder *enc);

#endif /* __SDE_ENCODER_H__ */
+11 −0
Original line number Diff line number Diff line
@@ -485,6 +485,17 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(

	cmd_enc->pp_timeout_report_cnt++;

	if (sde_encoder_phys_cmd_is_master(phys_enc)) {
		 /* trigger the retire fence if it was missed */
		if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt,
				-1, 0))
			phys_enc->parent_ops.handle_frame_done(
				phys_enc->parent,
				phys_enc,
				SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE);
		atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0);
	}

	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
			cmd_enc->pp_timeout_report_cnt,
			atomic_read(&phys_enc->pending_kickoff_cnt),