diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index ac24500587bc..5f04f8e19188 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -2295,7 +2295,7 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, dev = crtc->dev; sde_crtc = to_sde_crtc(crtc); cstate = to_sde_crtc_state(crtc->state); - SDE_EVT32_VERBOSE(DRMID(crtc)); + SDE_EVT32_VERBOSE(DRMID(crtc), cstate->cwb_enc_mask); SDE_ATRACE_BEGIN("sde_crtc_prepare_commit"); @@ -2315,6 +2315,7 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, cstate->connectors[cstate->num_connectors++] = conn; sde_connector_prepare_fence(conn); + sde_encoder_set_clone_mode(encoder, crtc->state); } drm_connector_list_iter_end(&conn_iter); @@ -2377,7 +2378,7 @@ enum sde_intf_mode sde_crtc_get_intf_mode(struct drm_crtc *crtc, drm_for_each_encoder_mask(encoder, crtc->dev, cstate->encoder_mask) { /* continue if copy encoder is encountered */ - if (sde_encoder_in_clone_mode(encoder)) + if (sde_crtc_state_in_clone_mode(encoder, cstate)) continue; return sde_encoder_get_intf_mode(encoder); diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index 292e2a4cb49f..98ee9a46090c 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -423,6 +423,7 @@ enum sde_crtc_dirty_flags { * @property_values: Current crtc property values * @input_fence_timeout_ns : Cached input fence timeout, in ns * @num_dim_layers: Number of dim layers + * @cwb_enc_mask : encoder mask populated during atomic_check if CWB is enabled * @dim_layer: Dim layer configs * @num_ds: Number of destination scalers to be configured * @num_ds_enabled: Number of destination scalers enabled @@ -451,6 +452,7 @@ struct sde_crtc_state { DECLARE_BITMAP(dirty, SDE_CRTC_DIRTY_MAX); uint64_t input_fence_timeout_ns; uint32_t num_dim_layers; + uint32_t cwb_enc_mask; struct sde_hw_dim_layer dim_layer[SDE_MAX_DIM_LAYERS]; uint32_t num_ds; uint32_t num_ds_enabled; @@ -804,6 +806,22 @@ static inline bool sde_crtc_atomic_check_has_modeset( return (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state)); } +static inline bool sde_crtc_state_in_clone_mode(struct drm_encoder *encoder, + struct drm_crtc_state *state) +{ + struct sde_crtc_state *cstate; + + if (!state || !encoder) + return false; + + cstate = to_sde_crtc_state(state); + if (sde_encoder_in_clone_mode(encoder) || + (cstate->cwb_enc_mask & drm_encoder_mask(encoder))) + return true; + + return false; +} + /** * sde_crtc_get_secure_transition - determines the operations to be * performed before transitioning to secure state diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index e4cd09ba4d53..c4d7c021d311 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -783,6 +783,34 @@ bool sde_encoder_is_cwb_disabling(struct drm_encoder *drm_enc, return false; } +void sde_encoder_set_clone_mode(struct drm_encoder *drm_enc, + struct drm_crtc_state *crtc_state) +{ + struct sde_encoder_virt *sde_enc; + struct sde_crtc_state *sde_crtc_state; + int i = 0; + + if (!drm_enc || !crtc_state) { + SDE_DEBUG("invalid params\n"); + return; + } + sde_enc = to_sde_encoder_virt(drm_enc); + sde_crtc_state = to_sde_crtc_state(crtc_state); + + if ((sde_enc->disp_info.intf_type != DRM_MODE_CONNECTOR_VIRTUAL) || + (!(sde_crtc_state->cwb_enc_mask & drm_encoder_mask(drm_enc)))) + return; + + for (i = 0; i < sde_enc->num_phys_encs; i++) { + struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; + + if (phys) { + phys->in_clone_mode = true; + SDE_DEBUG("enc:%d phys state:%d\n", DRMID(drm_enc), phys->enable_state); + } + } +} + 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) diff --git a/msm/sde/sde_encoder.h b/msm/sde/sde_encoder.h index b5d791ae96ca..8e90c1408483 100644 --- a/msm/sde/sde_encoder.h +++ b/msm/sde/sde_encoder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -499,6 +499,14 @@ void sde_encoder_enable_recovery_event(struct drm_encoder *encoder); */ bool sde_encoder_in_clone_mode(struct drm_encoder *enc); +/** + * sde_encoder_set_clone_mode - cwb in wb phys enc is enabled. + * drm_enc: Pointer to drm encoder structure + * drm_crtc_state: Pointer to drm_crtc_state + */ +void sde_encoder_set_clone_mode(struct drm_encoder *drm_enc, + struct drm_crtc_state *crtc_state); + /* * sde_encoder_is_cwb_disabling - check if cwb encoder disable is pending * @drm_enc: Pointer to drm encoder structure diff --git a/msm/sde/sde_encoder_phys_wb.c b/msm/sde/sde_encoder_phys_wb.c index 944a2c7e9eed..58ba064f73ec 100644 --- a/msm/sde/sde_encoder_phys_wb.c +++ b/msm/sde/sde_encoder_phys_wb.c @@ -604,6 +604,7 @@ static void _sde_enc_phys_wb_detect_cwb(struct sde_encoder_phys *phys_enc, struct drm_crtc_state *crtc_state) { struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); + struct sde_crtc_state *cstate = to_sde_crtc_state(crtc_state); const struct sde_wb_cfg *wb_cfg = wb_enc->hw_wb->caps; u32 encoder_mask = 0; @@ -612,9 +613,11 @@ static void _sde_enc_phys_wb_detect_cwb(struct sde_encoder_phys *phys_enc, encoder_mask = crtc_state->encoder_mask; encoder_mask &= ~drm_encoder_mask(phys_enc->parent); } - phys_enc->in_clone_mode = encoder_mask ? true : false; - SDE_DEBUG("detect CWB - status:%d\n", phys_enc->in_clone_mode); + cstate->cwb_enc_mask = encoder_mask ? drm_encoder_mask(phys_enc->parent) : 0; + + SDE_DEBUG("detect CWB - status:%d, phys state:%d in_clone_mode:%d\n", + cstate->cwb_enc_mask, phys_enc->enable_state, phys_enc->in_clone_mode); } static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, @@ -755,6 +758,7 @@ static int sde_encoder_phys_wb_atomic_check( struct drm_connector_state *conn_state) { struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); + struct sde_crtc_state *cstate = to_sde_crtc_state(crtc_state); struct sde_hw_wb *hw_wb = wb_enc->hw_wb; const struct sde_wb_cfg *wb_cfg = hw_wb->caps; struct drm_framebuffer *fb; @@ -782,7 +786,7 @@ static int sde_encoder_phys_wb_atomic_check( _sde_enc_phys_wb_detect_cwb(phys_enc, crtc_state); - if (clone_mode_curr && !phys_enc->in_clone_mode) { + if (clone_mode_curr && !cstate->cwb_enc_mask) { SDE_ERROR("WB commit before CWB disable\n"); return -EINVAL; } @@ -841,7 +845,7 @@ static int sde_encoder_phys_wb_atomic_check( crtc_state->mode_changed = true; /* if in clone mode, return after cwb validation */ - if (phys_enc->in_clone_mode) { + if (cstate->cwb_enc_mask) { rc = _sde_enc_phys_wb_validate_cwb(phys_enc, crtc_state, conn_state); if (rc) diff --git a/msm/sde/sde_rm.c b/msm/sde/sde_rm.c index ed35add22d82..f5221aae3f26 100644 --- a/msm/sde/sde_rm.c +++ b/msm/sde/sde_rm.c @@ -2040,7 +2040,7 @@ static int _sde_rm_populate_requirements( * Set the requirement for LM which has CWB support if CWB is * found enabled. */ - if (!RM_RQ_CWB(reqs) && sde_encoder_in_clone_mode(enc)) { + if (!RM_RQ_CWB(reqs) && sde_crtc_state_in_clone_mode(enc, crtc_state)) { reqs->top_ctrl |= BIT(SDE_RM_TOPCTL_CWB); /*