Merge "disp: msm: sde: delay cwb done wait for last frame"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
5e96441e58
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user