|
@@ -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);
|
|
|
}
|
|
|
|
|
|
/**
|