disp: msm: sde: reset ctl during wr_ptr_irq timeout
wr_ptr_irq timeout signifies that the MDP is stuck on either the current or previous frame. Handle ctl reset and fence signalling as part of this timeout handling. This logic would help to recover the HW faster in case of posted-start. Change-Id: I09b3d21772df431f9fc4a58b2fd9b4fcac4a7de7 Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
This commit is contained in:
parent
a8974603d1
commit
6da6eb6774
@ -4611,21 +4611,11 @@ static void _sde_encoder_helper_hdr_plus_mempool_update(
|
||||
}
|
||||
}
|
||||
|
||||
static void _sde_encoder_needs_hw_reset(struct drm_encoder *drm_enc,
|
||||
int ln_cnt1)
|
||||
void sde_encoder_helper_needs_hw_reset(struct drm_encoder *drm_enc)
|
||||
{
|
||||
struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
|
||||
struct sde_encoder_phys *phys;
|
||||
int ln_cnt2, i;
|
||||
|
||||
/* query line count before cur_master is updated */
|
||||
if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count)
|
||||
ln_cnt2 = sde_enc->cur_master->ops.get_wr_line_count(
|
||||
sde_enc->cur_master);
|
||||
else
|
||||
ln_cnt2 = -EINVAL;
|
||||
|
||||
SDE_EVT32(DRMID(drm_enc), ln_cnt1, ln_cnt2);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sde_enc->num_phys_encs; i++) {
|
||||
phys = sde_enc->phys_encs[i];
|
||||
@ -4643,7 +4633,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
|
||||
struct sde_crtc *sde_crtc;
|
||||
struct msm_drm_private *priv = NULL;
|
||||
bool needs_hw_reset = false, is_cmd_mode;
|
||||
int ln_cnt1 = -EINVAL, i, rc, ret = 0;
|
||||
int i, rc, ret = 0;
|
||||
struct msm_display_info *disp_info;
|
||||
|
||||
if (!drm_enc || !params || !drm_enc->dev ||
|
||||
@ -4660,11 +4650,6 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
|
||||
SDE_DEBUG_ENC(sde_enc, "\n");
|
||||
SDE_EVT32(DRMID(drm_enc));
|
||||
|
||||
/* save this for later, in case of errors */
|
||||
if (sde_enc->cur_master && sde_enc->cur_master->ops.get_wr_line_count)
|
||||
ln_cnt1 = sde_enc->cur_master->ops.get_wr_line_count(
|
||||
sde_enc->cur_master);
|
||||
|
||||
/* update the qsync parameters for the current frame */
|
||||
if (sde_enc->cur_master)
|
||||
sde_connector_set_qsync_params(
|
||||
@ -4715,7 +4700,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
|
||||
|
||||
/* if any phys needs reset, reset all phys, in-order */
|
||||
if (needs_hw_reset)
|
||||
_sde_encoder_needs_hw_reset(drm_enc, ln_cnt1);
|
||||
sde_encoder_helper_needs_hw_reset(drm_enc);
|
||||
|
||||
_sde_encoder_update_master(drm_enc, params);
|
||||
|
||||
|
@ -510,6 +510,12 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc,
|
||||
void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc,
|
||||
struct sde_hw_pp_vsync_info *info);
|
||||
|
||||
/**
|
||||
* sde_encoder_helper_needs_hw_reset - hw reset helper function
|
||||
* @drm_enc: Pointer to drm encoder structure
|
||||
*/
|
||||
void sde_encoder_helper_needs_hw_reset(struct drm_encoder *drm_enc);
|
||||
|
||||
/**
|
||||
* sde_encoder_helper_trigger_flush - control flush helper function
|
||||
* This helper function may be optionally specified by physical
|
||||
|
@ -1415,8 +1415,11 @@ static int sde_encoder_phys_cmd_wait_for_commit_done(
|
||||
cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
|
||||
|
||||
/* only required for master controller */
|
||||
if (sde_encoder_phys_cmd_is_master(phys_enc))
|
||||
if (sde_encoder_phys_cmd_is_master(phys_enc)) {
|
||||
rc = _sde_encoder_phys_cmd_wait_for_wr_ptr(phys_enc);
|
||||
if (rc == -ETIMEDOUT)
|
||||
goto wait_for_idle;
|
||||
}
|
||||
|
||||
if (!rc && sde_encoder_phys_cmd_is_master(phys_enc) &&
|
||||
cmd_enc->autorefresh.cfg.enable)
|
||||
@ -1424,15 +1427,24 @@ static int sde_encoder_phys_cmd_wait_for_commit_done(
|
||||
|
||||
/* wait for posted start or serialize trigger */
|
||||
if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) ||
|
||||
(!rc && phys_enc->frame_trigger_mode ==
|
||||
FRAME_DONE_WAIT_SERIALIZE)) {
|
||||
rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc);
|
||||
if (rc) {
|
||||
atomic_set(&phys_enc->pending_kickoff_cnt, 0);
|
||||
SDE_EVT32(DRMID(phys_enc->parent),
|
||||
phys_enc->hw_pp->idx - PINGPONG_0);
|
||||
SDE_ERROR("failed wait_for_idle: %d\n", rc);
|
||||
}
|
||||
(!rc && phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_SERIALIZE))
|
||||
goto wait_for_idle;
|
||||
|
||||
return rc;
|
||||
|
||||
wait_for_idle:
|
||||
rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc);
|
||||
if (rc) {
|
||||
SDE_EVT32(DRMID(phys_enc->parent),
|
||||
phys_enc->hw_pp->idx - PINGPONG_0,
|
||||
phys_enc->frame_trigger_mode,
|
||||
atomic_read(&phys_enc->pending_kickoff_cnt),
|
||||
phys_enc->enable_state, rc);
|
||||
atomic_set(&phys_enc->pending_kickoff_cnt, 0);
|
||||
SDE_ERROR("pp:%d failed wait_for_idle: %d\n",
|
||||
phys_enc->hw_pp->idx - PINGPONG_0, rc);
|
||||
if (phys_enc->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET)
|
||||
sde_encoder_helper_needs_hw_reset(phys_enc->parent);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
Loading…
Reference in New Issue
Block a user