disp: msm: sde: delay cwb done wait for last frame
Commit Ifa100424733 ("disp: msm: sde: delay encoder disable for clone mode") delays the CWB encoder disable but it is also skipping the CWB disable flush. That can cause the underrun on dp display if it uses the same 3d_merge HW block. This change reverts the portion of original code and only delays the last cwb frame done wait. It still keep the last CWB frame done wait as it is if crtc is also moving to inactive state. Change-Id: I3461188a35197f2925899ceea7ef705adf00a398 Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
This commit is contained in:
@@ -1074,7 +1074,8 @@ static void _sde_encoder_phys_wb_frame_done_helper(void *arg, bool frame_error)
|
||||
SDE_DEBUG("[wb:%d,%u]\n", hw_wb->idx - WB_0, wb_enc->frame_count);
|
||||
|
||||
/* don't notify upper layer for internal commit */
|
||||
if (phys_enc->enable_state == SDE_ENC_DISABLING)
|
||||
if (phys_enc->enable_state == SDE_ENC_DISABLING &&
|
||||
!phys_enc->in_clone_mode)
|
||||
goto complete;
|
||||
|
||||
if (phys_enc->parent_ops.handle_frame_done &&
|
||||
@@ -1272,6 +1273,31 @@ static bool _sde_encoder_phys_wb_is_idle(
|
||||
|
||||
return ret;
|
||||
}
|
||||
static void _sde_encoder_phys_wb_reset_state(
|
||||
struct sde_encoder_phys *phys_enc)
|
||||
{
|
||||
struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc);
|
||||
|
||||
/*
|
||||
* frame count and kickoff count are only used for debug purpose. Frame
|
||||
* count can be more than kickoff count at the end of disable call due
|
||||
* to extra frame_done wait. It does not cause any issue because
|
||||
* frame_done wait is based on retire_fence count. Leaving these
|
||||
* counters for debugging purpose.
|
||||
*/
|
||||
if (wb_enc->frame_count != wb_enc->kickoff_count) {
|
||||
SDE_EVT32(DRMID(phys_enc->parent), WBID(wb_enc),
|
||||
wb_enc->kickoff_count, wb_enc->frame_count,
|
||||
phys_enc->in_clone_mode);
|
||||
wb_enc->frame_count = wb_enc->kickoff_count;
|
||||
}
|
||||
|
||||
phys_enc->enable_state = SDE_ENC_DISABLED;
|
||||
wb_enc->crtc = NULL;
|
||||
phys_enc->hw_cdm = NULL;
|
||||
phys_enc->hw_ctl = NULL;
|
||||
phys_enc->in_clone_mode = false;
|
||||
}
|
||||
|
||||
static int _sde_encoder_phys_wb_wait_for_commit_done(
|
||||
struct sde_encoder_phys *phys_enc, bool is_disable)
|
||||
@@ -1358,7 +1384,17 @@ skip_wait:
|
||||
static int sde_encoder_phys_wb_wait_for_commit_done(
|
||||
struct sde_encoder_phys *phys_enc)
|
||||
{
|
||||
return _sde_encoder_phys_wb_wait_for_commit_done(phys_enc, false);
|
||||
int rc;
|
||||
|
||||
if (phys_enc->enable_state == SDE_ENC_DISABLING &&
|
||||
phys_enc->in_clone_mode) {
|
||||
rc = _sde_encoder_phys_wb_wait_for_commit_done(phys_enc, true);
|
||||
_sde_encoder_phys_wb_reset_state(phys_enc);
|
||||
} else {
|
||||
rc = _sde_encoder_phys_wb_wait_for_commit_done(phys_enc, false);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sde_encoder_phys_wb_wait_for_tx_complete(
|
||||
@@ -1625,7 +1661,9 @@ static void sde_encoder_phys_wb_disable(struct sde_encoder_phys *phys_enc)
|
||||
SDE_DEBUG("[wait_for_done: wb:%d, frame:%u, kickoff:%u]\n",
|
||||
hw_wb->idx - WB_0, wb_enc->frame_count,
|
||||
wb_enc->kickoff_count);
|
||||
_sde_encoder_phys_wb_wait_for_commit_done(phys_enc, true);
|
||||
|
||||
if (!phys_enc->in_clone_mode || !wb_enc->crtc->state->active)
|
||||
_sde_encoder_phys_wb_wait_for_commit_done(phys_enc, true);
|
||||
|
||||
if (!phys_enc->hw_ctl || !phys_enc->parent ||
|
||||
!phys_enc->sde_kms || !wb_enc->fb_disable) {
|
||||
@@ -1633,11 +1671,14 @@ static void sde_encoder_phys_wb_disable(struct sde_encoder_phys *phys_enc)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* avoid reset frame for CWB */
|
||||
if (phys_enc->in_clone_mode) {
|
||||
_sde_encoder_phys_wb_setup_cwb(phys_enc, false);
|
||||
_sde_encoder_phys_wb_update_cwb_flush(phys_enc, false);
|
||||
phys_enc->in_clone_mode = false;
|
||||
phys_enc->enable_state = SDE_ENC_DISABLING;
|
||||
|
||||
if (wb_enc->crtc->state->active)
|
||||
return;
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -1670,24 +1711,7 @@ static void sde_encoder_phys_wb_disable(struct sde_encoder_phys *phys_enc)
|
||||
sde_encoder_phys_wb_irq_ctrl(phys_enc, false);
|
||||
|
||||
exit:
|
||||
/*
|
||||
* frame count and kickoff count are only used for debug purpose. Frame
|
||||
* count can be more than kickoff count at the end of disable call due
|
||||
* to extra frame_done wait. It does not cause any issue because
|
||||
* frame_done wait is based on retire_fence count. Leaving these
|
||||
* counters for debugging purpose.
|
||||
*/
|
||||
if (wb_enc->frame_count != wb_enc->kickoff_count) {
|
||||
SDE_EVT32(DRMID(phys_enc->parent), WBID(wb_enc),
|
||||
wb_enc->kickoff_count, wb_enc->frame_count,
|
||||
phys_enc->in_clone_mode);
|
||||
wb_enc->frame_count = wb_enc->kickoff_count;
|
||||
}
|
||||
|
||||
phys_enc->enable_state = SDE_ENC_DISABLED;
|
||||
wb_enc->crtc = NULL;
|
||||
phys_enc->hw_cdm = NULL;
|
||||
phys_enc->hw_ctl = NULL;
|
||||
_sde_encoder_phys_wb_reset_state(phys_enc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user