diff --git a/msm/msm_atomic.c b/msm/msm_atomic.c index db5f072e78..0a2f95e48b 100644 --- a/msm/msm_atomic.c +++ b/msm/msm_atomic.c @@ -87,19 +87,19 @@ static inline bool _msm_seamless_for_conn(struct drm_connector *connector, old_conn_state->crtc->state->connectors_changed) return false; - if (msm_is_mode_seamless(&connector->encoder->crtc->state->mode)) + if (msm_is_mode_seamless(&old_conn_state->crtc->state->mode)) return true; if (msm_is_mode_seamless_vrr( - &connector->encoder->crtc->state->adjusted_mode)) + &old_conn_state->crtc->state->adjusted_mode)) return true; if (msm_is_mode_seamless_dyn_clk( - &connector->encoder->crtc->state->adjusted_mode)) + &old_conn_state->crtc->state->adjusted_mode)) return true; if (msm_is_mode_seamless_dms( - &connector->encoder->crtc->state->adjusted_mode)) + &old_conn_state->crtc->state->adjusted_mode)) return true; return false; @@ -142,17 +142,51 @@ static void msm_atomic_wait_for_commit_done( } } -static void -msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) +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 *crtc; 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) +{ + struct drm_connector *connector; + struct drm_connector_state *old_conn_state; struct drm_panel_notifier notifier_data; int i, blank; - 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; @@ -222,6 +256,18 @@ msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) ¬ifier_data); } } +} + +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; @@ -564,6 +610,9 @@ 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); diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 117f452805..27cf378a76 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -1264,8 +1264,13 @@ static int _sde_encoder_update_rsc_client( qsync_mode = sde_connector_get_qsync_mode( sde_enc->cur_master->connector); - if (sde_encoder_in_clone_mode(drm_enc) || - (disp_info->display_type != SDE_CONNECTOR_PRIMARY) || + /* left primary encoder keep vote */ + if (sde_encoder_in_clone_mode(drm_enc)) { + SDE_EVT32(rsc_state, SDE_EVTLOG_FUNC_CASE1); + return 0; + } + + if ((disp_info->display_type != SDE_CONNECTOR_PRIMARY) || (disp_info->display_type && qsync_mode)) rsc_state = enable ? SDE_RSC_CLK_STATE : SDE_RSC_IDLE_STATE; else if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE))