Merge "disp: msm: sde: delay cwb done wait for last frame"

This commit is contained in:
qctecmdr
2020-10-01 00:36:12 -07:00
committed by Gerrit - the friendly Code Review server
6 changed files with 105 additions and 77 deletions

View File

@@ -142,50 +142,16 @@ static void msm_atomic_wait_for_commit_done(
}
}
static bool
msm_disable_outputs_for_clone_conn(struct drm_device *dev,
struct drm_atomic_state *old_state)
{
struct drm_connector *connector;
struct drm_connector_state *old_conn_state;
struct drm_crtc_state *old_crtc_state;
struct drm_crtc *crtc = NULL;
int i;
bool clone_state = false;
for_each_old_connector_in_state(old_state, connector,
old_conn_state, i) {
if (!old_conn_state->crtc)
continue;
old_crtc_state = drm_atomic_get_old_crtc_state(old_state,
old_conn_state->crtc);
if (!old_crtc_state->active ||
!old_conn_state->crtc->state->connectors_changed ||
(!_msm_seamless_for_conn(connector, old_conn_state,
false) && (connector->connector_type !=
DRM_MODE_CONNECTOR_VIRTUAL)))
return false;
if (crtc)
clone_state = (crtc == old_conn_state->crtc)
? true : false;
crtc = old_conn_state->crtc;
}
return clone_state;
}
static void
msm_disable_connector_outputs(struct drm_device *dev,
struct drm_atomic_state *old_state)
msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
{
struct drm_connector *connector;
struct drm_connector_state *old_conn_state;
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
int i;
SDE_ATRACE_BEGIN("msm_disable");
for_each_old_connector_in_state(old_state, connector,
old_conn_state, i) {
const struct drm_encoder_helper_funcs *funcs;
@@ -238,18 +204,6 @@ msm_disable_connector_outputs(struct drm_device *dev,
drm_bridge_post_disable(encoder->bridge);
}
}
static void
msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
{
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
int i;
SDE_ATRACE_BEGIN("msm_disable");
if (!msm_disable_outputs_for_clone_conn(dev, old_state))
msm_disable_connector_outputs(dev, old_state);
for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
const struct drm_crtc_helper_funcs *funcs;
@@ -568,9 +522,6 @@ static void complete_commit(struct msm_commit *c)
kms->funcs->complete_commit(kms, state);
if (msm_disable_outputs_for_clone_conn(dev, state))
msm_disable_connector_outputs(dev, state);
drm_atomic_state_put(state);
commit_destroy(c);

View File

@@ -756,6 +756,29 @@ bool sde_encoder_in_clone_mode(struct drm_encoder *drm_enc)
return false;
}
bool sde_encoder_is_cwb_disabling(struct drm_encoder *drm_enc,
struct drm_crtc *crtc)
{
struct sde_encoder_virt *sde_enc;
int i;
if (!drm_enc)
return false;
sde_enc = to_sde_encoder_virt(drm_enc);
if (sde_enc->disp_info.intf_type != DRM_MODE_CONNECTOR_VIRTUAL)
return false;
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
if (sde_encoder_phys_is_cwb_disabling(phys, crtc))
return true;
}
return false;
}
static int _sde_encoder_atomic_check_phys_enc(struct sde_encoder_virt *sde_enc,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)

View File

@@ -495,6 +495,15 @@ void sde_encoder_recovery_events_handler(struct drm_encoder *encoder,
*/
bool sde_encoder_in_clone_mode(struct drm_encoder *enc);
/*
* sde_encoder_is_cwb_disabling - check if cwb encoder disable is pending
* @drm_enc: Pointer to drm encoder structure
* @drm_crtc: Pointer to drm crtc structure
* @Return: true if cwb encoder disable is pending
*/
bool sde_encoder_is_cwb_disabling(struct drm_encoder *drm_enc,
struct drm_crtc *drm_crtc);
/**
* sde_encoder_is_primary_display - checks if underlying display is primary
* display or not.

View File

@@ -641,6 +641,26 @@ static inline enum sde_3d_blend_mode sde_encoder_helper_get_3d_blend_mode(
return BLEND_3D_NONE;
}
/**
* sde_encoder_phys_is_cwb_disabling - Check if CWB encoder attached to this
* CRTC and it is in SDE_ENC_DISABLING state.
* @phys_enc: Pointer to physical encoder structure
* @crtc: drm crtc
* @Return: true if cwb encoder is in disabling state
*/
static inline bool sde_encoder_phys_is_cwb_disabling(
struct sde_encoder_phys *phys, struct drm_crtc *crtc)
{
struct sde_encoder_phys_wb *wb_enc;
if (!phys || !phys->in_clone_mode ||
phys->enable_state != SDE_ENC_DISABLING)
return false;
wb_enc = container_of(phys, struct sde_encoder_phys_wb, base);
return (wb_enc->crtc == crtc) ? true : false;
}
/**
* sde_encoder_helper_split_config - split display configuration helper function
* This helper function may be used by physical encoders to configure

View File

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

View File

@@ -1557,7 +1557,8 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms,
SDE_ATRACE_BEGIN("sde_kms_wait_for_commit_done");
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->crtc != crtc)
if (encoder->crtc != crtc &&
!sde_encoder_is_cwb_disabling(encoder, crtc))
continue;
/*
* Wait for post-flush if necessary to delay before