Some features like ctm can be enabled dynamically. Release and reserve the dpu resources whenever a topology change occurs such that required hw blocks are allocated appropriately. Changes in v1: - Avoid mode_set call directly instead change the mode_changed (Dmitry) Signed-off-by: Kalyan Thota <quic_kalyant@xxxxxxxxxxx> --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 2 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 42 ++++++++++++++++++----------- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 4 ++- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index 539b68b..58e8c72 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -204,6 +204,7 @@ struct dpu_crtc { * @hw_ctls : List of active ctl paths * @crc_source : CRC source * @crc_frame_skip_count: Number of frames skipped before getting CRC + * @ctm_enabled : Cached ctm reservation state */ struct dpu_crtc_state { struct drm_crtc_state base; @@ -225,6 +226,7 @@ struct dpu_crtc_state { enum dpu_crtc_crc_source crc_source; int crc_frame_skip_count; + bool ctm_enabled; }; #define to_dpu_crtc_state(x) \ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 3bd46b4..0ddf2c9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -217,6 +217,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = { 15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10 }; +static bool _dpu_enc_is_dspps_changed(struct drm_crtc_state *crtc_state, + struct msm_display_topology topology) +{ + struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state); + + if (drm_atomic_crtc_needs_modeset(crtc_state)) + return true; + + if ((cstate->ctm_enabled && !topology.num_dspp) || + (!cstate->ctm_enabled && topology.num_dspp)) { + crtc_state->mode_changed = true; + return true; + } + + return false; +} bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc) { @@ -638,25 +654,21 @@ static int dpu_encoder_virt_atomic_check( if (ret) { DPU_ERROR_ENC(dpu_enc, "mode unsupported, phys idx %d\n", i); - break; + return ret; } } topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state); + _dpu_enc_is_dspps_changed(crtc_state, topology); + /* Reserve dynamic resources now. */ - if (!ret) { - /* - * Release and Allocate resources on every modeset - * Dont allocate when active is false. - */ - if (drm_atomic_crtc_needs_modeset(crtc_state)) { - dpu_rm_release(global_state, drm_enc); + if (drm_atomic_crtc_needs_modeset(crtc_state)) { + dpu_rm_release(global_state, drm_enc); - if (!crtc_state->active_changed || crtc_state->active) - ret = dpu_rm_reserve(&dpu_kms->rm, global_state, - drm_enc, crtc_state, topology); - } + if (crtc_state->enable) + ret = dpu_rm_reserve(&dpu_kms->rm, global_state, + drm_enc, crtc_state, topology); } trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags); @@ -1027,7 +1039,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC]; struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL }; struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC]; - int num_lm, num_ctl, num_pp, num_dsc; + int num_lm, num_ctl, num_pp, num_dsc, num_dspp; unsigned int dsc_mask = 0; int i; @@ -1058,7 +1070,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl)); num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm)); - dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, + num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp, ARRAY_SIZE(hw_dspp)); @@ -1089,7 +1101,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, } cstate->num_mixers = num_lm; - + cstate->ctm_enabled = !!num_dspp; dpu_enc->connector = conn_state->connector; for (i = 0; i < dpu_enc->num_phys_encs; i++) { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index 9e7236e..4cbe20c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -150,8 +150,10 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, * dpu_encoder_prepare_commit - prepare encoder at the very beginning of an * atomic commit, before any registers are written * @drm_enc: Pointer to previously created drm encoder structure + * @crtc_state: Pointer to drm crtc state */ -void dpu_encoder_prepare_commit(struct drm_encoder *drm_enc); +void dpu_encoder_prepare_commit(struct drm_encoder *drm_enc, + struct drm_crtc_state *crtc_state); /** * dpu_encoder_set_idle_timeout - set the idle timeout for video -- 2.7.4