From 88c9a184f939a274833439a5d98b44f4fb16bde3 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Wed, 22 Sep 2021 14:42:06 -0700 Subject: [PATCH] disp: msm: sde: use dnsc_blur src w/h for calculating crtc/lm w/h When downscale blur feature is enabled, calculate the mixex and crtc width and height using the dnsc_blur's src width & height. Update the sde_crtc_get_mixer width/height functions to return the correct size based on the features enabled. Change-Id: I52dd88cc52e1ca5cb37e381e92e0e3032e7b090f Signed-off-by: Veera Sundaram Sankaran --- msm/sde/sde_crtc.c | 142 ++++++++++++++++++++++++++++++++++++------ msm/sde/sde_crtc.h | 81 ++++++++---------------- msm/sde/sde_encoder.c | 7 ++- 3 files changed, 153 insertions(+), 77 deletions(-) diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 24d992940b..fa601a3eef 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -135,6 +135,100 @@ static inline struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc) return to_sde_kms(priv->kms); } +static inline struct drm_connector_state *_sde_crtc_get_virt_conn_state( + struct drm_crtc *crtc, struct drm_crtc_state *crtc_state) +{ + struct drm_connector *conn; + struct drm_connector_state *conn_state, *virt_conn_state = NULL; + struct drm_connector_list_iter conn_iter; + int i; + + if (crtc_state->state) { + for_each_new_connector_in_state(crtc_state->state, conn, conn_state, i) { + if (conn_state && (conn_state->crtc == crtc) + && (conn->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)) { + virt_conn_state = conn_state; + break; + } + } + } else { + drm_connector_list_iter_begin(crtc->dev, &conn_iter); + drm_for_each_connector_iter(conn, &conn_iter) { + if (conn->state && (conn->state->crtc == crtc) + && (conn->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)) { + virt_conn_state = conn->state; + break; + } + } + drm_connector_list_iter_end(&conn_iter); + } + + return virt_conn_state; +} + +void sde_crtc_get_mixer_resolution(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state, + struct drm_display_mode *mode, u32 *width, u32 *height) +{ + struct sde_crtc *sde_crtc; + struct sde_crtc_state *cstate; + struct drm_connector_state *virt_conn_state; + struct sde_connector_state *virt_cstate; + + *width = 0; + *height = 0; + + if (!crtc || !crtc_state || !mode) + return; + + sde_crtc = to_sde_crtc(crtc); + cstate = to_sde_crtc_state(crtc_state); + virt_conn_state = _sde_crtc_get_virt_conn_state(crtc, crtc_state); + virt_cstate = virt_conn_state ? to_sde_connector_state(virt_conn_state) : NULL; + + if (cstate->num_ds_enabled) { + *width = cstate->ds_cfg[0].lm_width; + *height = cstate->ds_cfg[0].lm_height; + } else if (virt_cstate && virt_cstate->dnsc_blur_count) { + *width = (virt_cstate->dnsc_blur_cfg[0].src_width + * virt_cstate->dnsc_blur_count) / sde_crtc->num_mixers; + *height = virt_cstate->dnsc_blur_cfg[0].src_height; + } else { + *width = mode->hdisplay / sde_crtc->num_mixers; + *height = mode->vdisplay; + } +} + +void sde_crtc_get_resolution(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state, + struct drm_display_mode *mode, u32 *width, u32 *height) +{ + struct sde_crtc *sde_crtc; + struct sde_crtc_state *cstate; + struct drm_connector_state *virt_conn_state; + struct sde_connector_state *virt_cstate; + + *width = 0; + *height = 0; + + if (!crtc || !crtc_state || !mode) + return; + + sde_crtc = to_sde_crtc(crtc); + cstate = to_sde_crtc_state(crtc_state); + virt_conn_state = _sde_crtc_get_virt_conn_state(crtc, crtc_state); + virt_cstate = virt_conn_state ? to_sde_connector_state(virt_conn_state) : NULL; + + if (cstate->num_ds_enabled) { + *width = cstate->ds_cfg[0].lm_width * cstate->num_ds_enabled; + *height = cstate->ds_cfg[0].lm_height; + } else if (virt_cstate && virt_cstate->dnsc_blur_count) { + *width = virt_cstate->dnsc_blur_cfg[0].src_width * virt_cstate->dnsc_blur_count; + *height = virt_cstate->dnsc_blur_cfg[0].src_height; + } else { + *width = mode->hdisplay; + *height = mode->vdisplay; + } +} + /** * sde_crtc_calc_fps() - Calculates fps value. * @sde_crtc : CRTC structure @@ -503,6 +597,23 @@ static void sde_crtc_destroy(struct drm_crtc *crtc) kfree(sde_crtc); } +struct sde_connector_state *_sde_crtc_get_sde_connector_state(struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + struct drm_connector *conn; + struct drm_connector_state *conn_state; + int i; + + for_each_new_connector_in_state(state, conn, conn_state, i) { + if (!conn_state || conn_state->crtc != crtc) + continue; + + return to_sde_connector_state(conn_state); + } + + return NULL; +} + struct msm_display_mode *sde_crtc_get_msm_mode(struct drm_crtc_state *c_state) { struct drm_connector *connector; @@ -906,8 +1017,7 @@ static int _sde_crtc_set_crtc_roi(struct drm_crtc *crtc, /* clear the ROI to null if it matches full screen anyways */ adj_mode = &state->adjusted_mode; - crtc_width = sde_crtc_get_width(sde_crtc, crtc_state, adj_mode); - crtc_height = sde_crtc_get_mixer_height(sde_crtc, crtc_state, adj_mode); + sde_crtc_get_resolution(crtc, state, adj_mode, &crtc_width, &crtc_height); if (crtc_roi->x == 0 && crtc_roi->y == 0 && crtc_roi->w == crtc_width && crtc_roi->h == crtc_height) memset(crtc_roi, 0, sizeof(*crtc_roi)); @@ -3489,10 +3599,9 @@ static void _sde_crtc_setup_lm_bounds(struct drm_crtc *crtc, struct drm_crtc_sta sde_crtc = to_sde_crtc(crtc); cstate = to_sde_crtc_state(state); - adj_mode = &state->adjusted_mode; - mixer_width = sde_crtc_get_mixer_width(sde_crtc, cstate, adj_mode); - mixer_height = sde_crtc_get_mixer_height(sde_crtc, cstate, adj_mode); + + sde_crtc_get_mixer_resolution(crtc, state, adj_mode, &mixer_width, &mixer_height); for (i = 0; i < sde_crtc->num_mixers; i++) { cstate->lm_bounds[i].x = mixer_width * i; @@ -4733,11 +4842,10 @@ static void sde_crtc_enable(struct drm_crtc *crtc, } /* no input validation - caller API has all the checks */ -static int _sde_crtc_excl_dim_layer_check(struct drm_crtc_state *state, +static int _sde_crtc_excl_dim_layer_check(struct drm_crtc *crtc, struct drm_crtc_state *state, struct plane_state pstates[], int cnt) { struct sde_crtc_state *cstate = to_sde_crtc_state(state); - struct sde_crtc *sde_crtc = to_sde_crtc(state->crtc); struct drm_display_mode *mode = &state->adjusted_mode; const struct drm_plane_state *pstate; struct sde_plane_state *sde_pstate; @@ -4745,8 +4853,7 @@ static int _sde_crtc_excl_dim_layer_check(struct drm_crtc_state *state, struct sde_rect *rect; u32 crtc_width, crtc_height; - crtc_width = sde_crtc_get_width(sde_crtc, cstate, mode); - crtc_height = sde_crtc_get_mixer_height(sde_crtc, cstate, mode); + sde_crtc_get_resolution(crtc, state, mode, &crtc_width, &crtc_height); /* Check dim layer rect bounds and stage */ for (i = 0; i < cstate->num_dim_layers; i++) { @@ -5065,8 +5172,7 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc, memset(pipe_staged, 0, sizeof(pipe_staged)); - crtc_width = sde_crtc_get_width(sde_crtc, cstate, mode); - crtc_height = sde_crtc_get_mixer_height(sde_crtc, cstate, mode); + sde_crtc_get_resolution(crtc, state, mode, &crtc_width, &crtc_height); drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { if (IS_ERR_OR_NULL(pstate)) { @@ -5200,7 +5306,7 @@ static int _sde_crtc_check_zpos(struct drm_crtc_state *state, sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL); - rc = _sde_crtc_excl_dim_layer_check(state, pstates, cnt); + rc = _sde_crtc_excl_dim_layer_check(crtc, state, pstates, cnt); if (rc) return rc; @@ -5311,9 +5417,8 @@ static int _sde_crtc_check_plane_layout(struct drm_crtc *crtc, struct drm_plane_state *plane_state; struct sde_plane_state *pstate; struct drm_display_mode *mode; - struct sde_crtc *sde_crtc; - struct sde_crtc_state *cstate; int layout_split; + u32 crtc_width, crtc_height; kms = _sde_crtc_get_kms(crtc); @@ -5327,8 +5432,8 @@ static int _sde_crtc_check_plane_layout(struct drm_crtc *crtc, return 0; mode = &crtc->state->adjusted_mode; - sde_crtc = to_sde_crtc(crtc); - cstate = to_sde_crtc_state(crtc->state); + sde_crtc_get_resolution(crtc, crtc_state, mode, &crtc_width, &crtc_height); + drm_atomic_crtc_state_for_each_plane(plane, crtc_state) { plane_state = drm_atomic_get_existing_plane_state( crtc_state->state, plane); @@ -5336,7 +5441,7 @@ static int _sde_crtc_check_plane_layout(struct drm_crtc *crtc, continue; pstate = to_sde_plane_state(plane_state); - layout_split = sde_crtc_get_width(sde_crtc, cstate, mode) >> 1; + layout_split = crtc_width >> 1; if (plane_state->crtc_x >= layout_split) { plane_state->crtc_x -= layout_split; @@ -6362,8 +6467,7 @@ static int _sde_debugfs_status_show(struct seq_file *s, void *data) mutex_lock(&sde_crtc->crtc_lock); mode = &crtc->state->adjusted_mode; - mixer_width = sde_crtc_get_mixer_width(sde_crtc, cstate, mode); - mixer_height = sde_crtc_get_mixer_height(sde_crtc, cstate, mode); + sde_crtc_get_mixer_resolution(crtc, crtc->state, mode, &mixer_width, &mixer_height); seq_printf(s, "crtc:%d width:%d height:%d\n", DRMID(crtc), mixer_width * sde_crtc->num_mixers, mixer_height); diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index 729510836e..8aafac6de2 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -545,61 +545,6 @@ struct sde_crtc_irq_info { #define sde_crtc_get_property(S, X) \ ((S) && ((X) < CRTC_PROP_COUNT) ? ((S)->property_values[(X)].value) : 0) -/** - * sde_crtc_get_mixer_width - get the mixer width - * Mixer width will be same as panel width(/2 for split) - * unless destination scaler feature is enabled - */ -static inline int sde_crtc_get_mixer_width(struct sde_crtc *sde_crtc, - struct sde_crtc_state *cstate, struct drm_display_mode *mode) -{ - u32 mixer_width; - - if (!sde_crtc || !cstate || !mode) - return 0; - - if (cstate->num_ds_enabled) - mixer_width = cstate->ds_cfg[0].lm_width; - else - mixer_width = mode->hdisplay / sde_crtc->num_mixers; - - return mixer_width; -} - -/** - * sde_crtc_get_mixer_height - get the mixer height - * Mixer height will be same as panel height unless - * destination scaler feature is enabled - */ -static inline int sde_crtc_get_mixer_height(struct sde_crtc *sde_crtc, - struct sde_crtc_state *cstate, struct drm_display_mode *mode) -{ - if (!sde_crtc || !cstate || !mode) - return 0; - - return (cstate->num_ds_enabled ? - cstate->ds_cfg[0].lm_height : mode->vdisplay); -} - -/** - * sde_crtc_get_width - get the correct crtc width based on the features enabled - */ -static inline int sde_crtc_get_width(struct sde_crtc *sde_crtc, - struct sde_crtc_state *cstate, struct drm_display_mode *mode) -{ - u32 width; - - if (!sde_crtc || !cstate || !mode) - return 0; - - if (cstate->num_ds_enabled) - width = cstate->ds_cfg[0].lm_width * cstate->num_ds_enabled; - else - width = mode->hdisplay; - - return width; -} - /** * sde_crtc_frame_pending - retun the number of pending frames * @crtc: Pointer to drm crtc object @@ -658,6 +603,32 @@ static inline int sde_crtc_request_frame_reset(struct drm_crtc *crtc, return 0; } +/** + * sde_crtc_get_mixer_resolution - Get the mixer resolution based on the features enabled. + * Mixer width will be same as panel width(/2 for split) or src_width of + * destination scaler or downscale-blur. + * @drm_crtc: Pointer to drm crtc object + * @crtc_state: Pointer to drm crtc state object + * @mode: Pointer to drm display mode object + * @width: Pointer to width object populated with mixer width by this function + * @height: Pointer to height object populated with mixer height by this function + */ +void sde_crtc_get_mixer_resolution(struct drm_crtc *sde_crtc, struct drm_crtc_state *crtc_state, + struct drm_display_mode *mode, u32 *width, u32 *height); + +/** + * sde_crtc_get_resolution - Get the crtc resolution based on the features enabled. + * Crtc width will be same as panel width or (src_width of + * destination scaler or downscale-blur) * num_blocks. + * @drm_crtc: Pointer to drm crtc object + * @crtc_state: Pointer to drm crtc state object + * @mode: Pointer to drm display mode object + * @width: Pointer to width object populated with crtc width by this function + * @height: Pointer to height object populated with crtc height by this function + */ +void sde_crtc_get_resolution(struct drm_crtc *sde_crtc, struct drm_crtc_state *crtc_state, + struct drm_display_mode *mode, u32 *width, u32 *height); + /** * sde_crtc_vblank - enable or disable vblanks for this crtc * @crtc: Pointer to drm crtc object diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 90d7eb32f6..b726dde1a1 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -926,17 +926,18 @@ static int _sde_encoder_atomic_check_pu_roi(struct sde_encoder_virt *sde_enc, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state, struct sde_connector_state *sde_conn_state, struct sde_crtc_state *sde_crtc_state) { - struct sde_crtc *sde_crtc = to_sde_crtc(crtc_state->crtc); struct drm_display_mode *mode = &crtc_state->adjusted_mode; int ret = 0; if (crtc_state->mode_changed || crtc_state->active_changed) { struct sde_rect mode_roi, roi; + u32 width, height; + sde_crtc_get_resolution(crtc_state->crtc, crtc_state, mode, &width, &height); mode_roi.x = 0; mode_roi.y = 0; - mode_roi.w = sde_crtc_get_width(sde_crtc, sde_crtc_state, mode); - mode_roi.h = sde_crtc_get_mixer_height(sde_crtc, sde_crtc_state, mode); + mode_roi.w = width; + mode_roi.h = height; if (sde_conn_state->rois.num_rects) { sde_kms_rect_merge_rectangles(&sde_conn_state->rois, &roi);