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 <veeras@codeaurora.org>
This commit is contained in:
Veera Sundaram Sankaran
2021-09-22 14:42:06 -07:00
parent cc23729c87
commit 88c9a184f9
3 changed files with 153 additions and 77 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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);