Well, that was a lot stickier than I thought it would be! This patch removes dpu_rect and its helpers in favor of drm_rect and its helpers. Signed-off-by: Sean Paul <seanpaul@xxxxxxxxxxxx> --- Based on my tracepoints set. drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 86 ++++---- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 7 - drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 10 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 4 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 54 ----- drivers/gpu/drm/msm/disp/dpu1/dpu_kms_utils.c | 25 --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 185 ++++++++++-------- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 10 +- 9 files changed, 160 insertions(+), 223 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index eefc1892ad47..86ed8cb45cee 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -24,6 +24,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_flip_work.h> +#include <drm/drm_rect.h> #include "dpu_kms.h" #include "dpu_hw_lm.h" @@ -607,15 +608,15 @@ static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc) lm_horiz_position = 0; for (lm_idx = 0; lm_idx < dpu_crtc->num_mixers; lm_idx++) { - const struct dpu_rect *lm_roi = &crtc_state->lm_bounds[lm_idx]; + const struct drm_rect *lm_roi = &crtc_state->lm_bounds[lm_idx]; struct dpu_hw_mixer *hw_lm = dpu_crtc->mixers[lm_idx].hw_lm; struct dpu_hw_mixer_cfg cfg; - if (dpu_kms_rect_is_null(lm_roi)) + if (!lm_roi || !drm_rect_visible(lm_roi)) continue; - cfg.out_width = lm_roi->w; - cfg.out_height = lm_roi->h; + cfg.out_width = drm_rect_width(lm_roi); + cfg.out_height = drm_rect_height(lm_roi); cfg.right_mixer = lm_horiz_position++; cfg.flags = 0; hw_lm->ops.setup_mixer_out(hw_lm, &cfg); @@ -634,7 +635,6 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct dpu_hw_ctl *ctl; struct dpu_hw_mixer *lm; struct dpu_hw_stage_cfg *stage_cfg; - struct dpu_rect plane_crtc_roi; u32 flush_mask; uint32_t stage_idx, lm_idx; @@ -656,11 +656,6 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, if (!state) continue; - plane_crtc_roi.x = state->crtc_x; - plane_crtc_roi.y = state->crtc_y; - plane_crtc_roi.w = state->crtc_w; - plane_crtc_roi.h = state->crtc_h; - pstate = to_dpu_plane_state(state); fb = state->fb; @@ -1119,13 +1114,13 @@ static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc, crtc_split_width = dpu_crtc_get_mixer_width(dpu_crtc, cstate, adj_mode); for (i = 0; i < dpu_crtc->num_mixers; i++) { - cstate->lm_bounds[i].x = crtc_split_width * i; - cstate->lm_bounds[i].y = 0; - cstate->lm_bounds[i].w = crtc_split_width; - cstate->lm_bounds[i].h = - dpu_crtc_get_mixer_height(dpu_crtc, cstate, adj_mode); - trace_dpu_crtc_setup_lm_bounds(DRMID(crtc), i, - &cstate->lm_bounds[i]); + struct drm_rect *r = &cstate->lm_bounds[i]; + r->x1 = crtc_split_width * i; + r->y1 = 0; + r->x2 = r->x1 + crtc_split_width; + r->y2 = dpu_crtc_get_mixer_height(dpu_crtc, cstate, adj_mode); + + trace_dpu_crtc_setup_lm_bounds(DRMID(crtc), i, r); } drm_mode_debug_printmodeline(adj_mode); @@ -1822,6 +1817,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, int multirect_count = 0; const struct drm_plane_state *pipe_staged[SSPP_MAX]; int left_zpos_cnt = 0, right_zpos_cnt = 0; + struct drm_rect crtc_rect = { 0 }; if (!crtc) { DPU_ERROR("invalid crtc\n"); @@ -1850,8 +1846,13 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, _dpu_crtc_setup_lm_bounds(crtc, state); + crtc_rect.x2 = mode->hdisplay; + crtc_rect.y2 = mode->vdisplay; + /* get plane state for all drm planes associated with crtc state */ drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { + struct drm_rect dst, clip = crtc_rect; + if (IS_ERR_OR_NULL(pstate)) { rc = PTR_ERR(pstate); DPU_ERROR("%s: failed to get plane%d state, %d\n", @@ -1879,14 +1880,13 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, cnt++; - if (CHECK_LAYER_BOUNDS(pstate->crtc_y, pstate->crtc_h, - mode->vdisplay) || - CHECK_LAYER_BOUNDS(pstate->crtc_x, pstate->crtc_w, - mode->hdisplay)) { + dst = drm_plane_state_dest(pstate); + if (!drm_rect_intersect(&clip, &dst) || + !drm_rect_equals(&clip, &dst)) { DPU_ERROR("invalid vertical/horizontal destination\n"); - DPU_ERROR("y:%d h:%d vdisp:%d x:%d w:%d hdisp:%d\n", - pstate->crtc_y, pstate->crtc_h, mode->vdisplay, - pstate->crtc_x, pstate->crtc_w, mode->hdisplay); + DPU_ERROR("display: " DRM_RECT_FMT " plane: " + DRM_RECT_FMT "\n", DRM_RECT_ARG(&crtc_rect), + DRM_RECT_ARG(&dst)); rc = -E2BIG; goto end; } @@ -1969,7 +1969,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, */ for (i = 1; i < cnt; i++) { struct plane_state *prv_pstate, *cur_pstate; - struct dpu_rect left_rect, right_rect; + struct drm_rect left_rect, right_rect; int32_t left_pid, right_pid; int32_t stage; @@ -1981,18 +1981,12 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, stage = cur_pstate->stage; left_pid = prv_pstate->dpu_pstate->base.plane->base.id; - POPULATE_RECT(&left_rect, prv_pstate->drm_pstate->crtc_x, - prv_pstate->drm_pstate->crtc_y, - prv_pstate->drm_pstate->crtc_w, - prv_pstate->drm_pstate->crtc_h, false); + left_rect = drm_plane_state_dest(prv_pstate->drm_pstate); right_pid = cur_pstate->dpu_pstate->base.plane->base.id; - POPULATE_RECT(&right_rect, cur_pstate->drm_pstate->crtc_x, - cur_pstate->drm_pstate->crtc_y, - cur_pstate->drm_pstate->crtc_w, - cur_pstate->drm_pstate->crtc_h, false); + right_rect = drm_plane_state_dest(cur_pstate->drm_pstate); - if (right_rect.x < left_rect.x) { + if (right_rect.x1 < left_rect.x1) { swap(left_pid, right_pid); swap(left_rect, right_rect); } @@ -2010,19 +2004,21 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, stage, left_pid, right_pid); rc = -EINVAL; goto end; - } else if (right_rect.x != (left_rect.x + left_rect.w)) { - DPU_ERROR( - "non-contiguous coordinates for src split. stage: %d left: %d - %d right: %d - %d\n", - stage, left_rect.x, left_rect.w, - right_rect.x, right_rect.w); + } else if (right_rect.x1 != drm_rect_width(&left_rect)) { + DPU_ERROR("non-contiguous coordinates for src split. " + "stage: %d left: " DRM_RECT_FMT " right: " + DRM_RECT_FMT "\n", stage, + DRM_RECT_ARG(&left_rect), + DRM_RECT_ARG(&right_rect)); rc = -EINVAL; goto end; - } else if ((left_rect.y != right_rect.y) || - (left_rect.h != right_rect.h)) { - DPU_ERROR( - "source split at stage: %d. invalid yoff/height: l_y: %d r_y: %d l_h: %d r_h: %d\n", - stage, left_rect.y, right_rect.y, - left_rect.h, right_rect.h); + } else if (left_rect.y1 != right_rect.y1 || + drm_rect_height(&left_rect) != drm_rect_height(&right_rect)) { + DPU_ERROR("source split at stage: %d. invalid " + "yoff/height: left: " DRM_RECT_FMT " right: " + DRM_RECT_FMT "\n", stage, + DRM_RECT_ARG(&left_rect), + DRM_RECT_ARG(&right_rect)); rc = -EINVAL; goto end; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index 39def93df641..7147dcb2be16 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -318,7 +318,7 @@ struct dpu_crtc_state { bool bw_split_vote; bool is_ppsplit; - struct dpu_rect lm_bounds[CRTC_DUAL_MIXERS]; + struct drm_rect lm_bounds[CRTC_DUAL_MIXERS]; uint64_t input_fence_timeout_ns; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h index 836ff9e87b2e..35e6bf930924 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h @@ -424,13 +424,6 @@ struct dpu_hw_fmt_layout { uint32_t plane_pitch[DPU_MAX_PLANES]; }; -struct dpu_rect { - u16 x; - u16 y; - u16 w; - u16 h; -}; - struct dpu_csc_cfg { /* matrix coefficients in S15.16 format */ uint32_t csc_mv[DPU_CSC_MATRIX_COEFF_SIZE]; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c index 2b3f5e88af98..c25b52a6b219 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -462,10 +462,12 @@ static void dpu_hw_sspp_setup_rects(struct dpu_hw_pipe *ctx, /* src and dest rect programming */ - src_xy = (cfg->src_rect.y << 16) | (cfg->src_rect.x); - src_size = (cfg->src_rect.h << 16) | (cfg->src_rect.w); - dst_xy = (cfg->dst_rect.y << 16) | (cfg->dst_rect.x); - dst_size = (cfg->dst_rect.h << 16) | (cfg->dst_rect.w); + src_xy = (cfg->src_rect.y1 << 16) | cfg->src_rect.x1; + src_size = (drm_rect_height(&cfg->src_rect) << 16) | + drm_rect_width(&cfg->src_rect); + dst_xy = (cfg->dst_rect.y1 << 16) | cfg->dst_rect.x1; + dst_size = (drm_rect_height(&cfg->dst_rect) << 16) | + drm_rect_width(&cfg->dst_rect); if (rect_index == DPU_SSPP_RECT_SOLO) { ystride0 = (cfg->layout.plane_pitch[0]) | diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h index 0bb5ecb2f1b8..4d81e5f5ce1b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h @@ -164,8 +164,8 @@ struct dpu_hw_pixel_ext { */ struct dpu_hw_pipe_cfg { struct dpu_hw_fmt_layout layout; - struct dpu_rect src_rect; - struct dpu_rect dst_rect; + struct drm_rect src_rect; + struct drm_rect dst_rect; enum dpu_sspp_multirect_index index; enum dpu_sspp_multirect_mode mode; }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 046e6f770560..fb4ae84a388a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -65,17 +65,6 @@ #define DPU_ERROR(fmt, ...) pr_err("[dpu error]" fmt, ##__VA_ARGS__) -#define POPULATE_RECT(rect, a, b, c, d, Q16_flag) \ - do { \ - (rect)->x = (Q16_flag) ? (a) >> 16 : (a); \ - (rect)->y = (Q16_flag) ? (b) >> 16 : (b); \ - (rect)->w = (Q16_flag) ? (c) >> 16 : (c); \ - (rect)->h = (Q16_flag) ? (d) >> 16 : (d); \ - } while (0) - -#define CHECK_LAYER_BOUNDS(offset, size, max_size) \ - (((size) > (max_size)) || ((offset) > ((max_size) - (size)))) - /** * ktime_compare_safe - compare two ktime structures * This macro is similar to the standard ktime_compare() function, but @@ -430,49 +419,6 @@ void dpu_kms_info_append_format(struct dpu_kms_info *info, */ void dpu_kms_info_stop(struct dpu_kms_info *info); -/** - * dpu_kms_rect_intersect - intersect two rectangles - * @r1: first rectangle - * @r2: scissor rectangle - * @result: result rectangle, all 0's on no intersection found - */ -void dpu_kms_rect_intersect(const struct dpu_rect *r1, - const struct dpu_rect *r2, - struct dpu_rect *result); - -/** - * dpu_kms_rect_is_equal - compares two rects - * @r1: rect value to compare - * @r2: rect value to compare - * - * Returns 1 if the rects are same, 0 otherwise. - */ -static inline bool dpu_kms_rect_is_equal(struct dpu_rect *r1, - struct dpu_rect *r2) -{ - if ((!r1 && r2) || (r1 && !r2)) - return false; - - if (!r1 && !r2) - return true; - - return r1->x == r2->x && r1->y == r2->y && r1->w == r2->w && - r1->h == r2->h; -} - -/** - * dpu_kms_rect_is_null - returns true if the width or height of a rect is 0 - * @rect: rectangle to check for zero size - * @Return: True if width or height of rectangle is 0 - */ -static inline bool dpu_kms_rect_is_null(const struct dpu_rect *r) -{ - if (!r) - return true; - - return (!r->w || !r->h); -} - /** * Vblank enable/disable functions */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms_utils.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms_utils.c index 40e016254227..a80b3da5a9fe 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms_utils.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms_utils.c @@ -151,28 +151,3 @@ void dpu_kms_info_stop(struct dpu_kms_info *info) info->len = info->staged_len + len; } } - -void dpu_kms_rect_intersect(const struct dpu_rect *r1, - const struct dpu_rect *r2, - struct dpu_rect *result) -{ - int l, t, r, b; - - if (!r1 || !r2 || !result) - return; - - l = max(r1->x, r2->x); - t = max(r1->y, r2->y); - r = min((r1->x + r1->w), (r2->x + r2->w)); - b = min((r1->y + r1->h), (r2->y + r2->h)); - - if (r <= l || b <= t) { - memset(result, 0, sizeof(*result)); - } else { - result->x = l; - result->y = t; - result->w = r - l; - result->h = b - t; - } -} - diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 2c3dc00477b3..c2088a3bfba7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -180,8 +180,10 @@ static inline int _dpu_plane_calc_fill_level(struct drm_plane *plane, continue; DPU_DEBUG("plane%d/%d src_width:%d/%d\n", pdpu->base.base.id, tmp->base.base.id, - src_width, tmp->pipe_cfg.src_rect.w); - src_width = max_t(u32, src_width, tmp->pipe_cfg.src_rect.w); + src_width, + drm_rect_width(&tmp->pipe_cfg.src_rect)); + src_width = max_t(u32, src_width, + drm_rect_width(&tmp->pipe_cfg.src_rect)); } if (fmt->fetch_planes == DPU_PLANE_PSEUDO_PLANAR) { @@ -272,7 +274,7 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane, fb->format->format, fb->modifier); total_fl = _dpu_plane_calc_fill_level(plane, fmt, - pdpu->pipe_cfg.src_rect.w); + drm_rect_width(&pdpu->pipe_cfg.src_rect)); if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) lut_usage = DPU_QOS_LUT_USAGE_LINEAR; @@ -493,8 +495,8 @@ static void _dpu_plane_set_ot_limit(struct drm_plane *plane, memset(&ot_params, 0, sizeof(ot_params)); ot_params.xin_id = pdpu->pipe_hw->cap->xin_id; ot_params.num = pdpu->pipe_hw->idx - SSPP_NONE; - ot_params.width = pdpu->pipe_cfg.src_rect.w; - ot_params.height = pdpu->pipe_cfg.src_rect.h; + ot_params.width = drm_rect_width(&pdpu->pipe_cfg.src_rect); + ot_params.height = drm_rect_height(&pdpu->pipe_cfg.src_rect); ot_params.is_wfd = !pdpu->is_rt_pipe; ot_params.frame_rate = crtc->mode.vrefresh; ot_params.vbif_idx = VBIF_RT; @@ -757,10 +759,10 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu, /* update scaler. calculate default config for QSEED3 */ _dpu_plane_setup_scaler3(pdpu, pstate, - pdpu->pipe_cfg.src_rect.w, - pdpu->pipe_cfg.src_rect.h, - pdpu->pipe_cfg.dst_rect.w, - pdpu->pipe_cfg.dst_rect.h, + drm_rect_width(&pdpu->pipe_cfg.src_rect), + drm_rect_height(&pdpu->pipe_cfg.src_rect), + drm_rect_width(&pdpu->pipe_cfg.dst_rect), + drm_rect_height(&pdpu->pipe_cfg.dst_rect), &pstate->scaler3_cfg, fmt, chroma_subsmpl_h, chroma_subsmpl_v); } @@ -807,10 +809,12 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu, pstate->multirect_index); /* override scaler/decimation if solid fill */ - pdpu->pipe_cfg.src_rect.x = 0; - pdpu->pipe_cfg.src_rect.y = 0; - pdpu->pipe_cfg.src_rect.w = pdpu->pipe_cfg.dst_rect.w; - pdpu->pipe_cfg.src_rect.h = pdpu->pipe_cfg.dst_rect.h; + pdpu->pipe_cfg.src_rect.x1 = 0; + pdpu->pipe_cfg.src_rect.y1 = 0; + pdpu->pipe_cfg.src_rect.x2 = + drm_rect_width(&pdpu->pipe_cfg.dst_rect); + pdpu->pipe_cfg.src_rect.y2 = + drm_rect_height(&pdpu->pipe_cfg.dst_rect); _dpu_plane_setup_scaler(pdpu, pstate, fmt, true); if (pdpu->pipe_hw->ops.setup_format) @@ -854,10 +858,9 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane) { struct dpu_plane_state *pstate[R_MAX]; const struct drm_plane_state *drm_state[R_MAX]; - struct dpu_rect src[R_MAX], dst[R_MAX]; + struct drm_rect src[R_MAX], dst[R_MAX]; struct dpu_plane *dpu_plane[R_MAX]; const struct dpu_format *fmt[R_MAX]; - bool q16_data = true; int i, buffer_lines; unsigned int max_tile_height = 1; bool parallel_fetch_qualified = true; @@ -889,13 +892,15 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane) return -EINVAL; } - POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y, - drm_state[i]->src_w, drm_state[i]->src_h, q16_data); - POPULATE_RECT(&dst[i], drm_state[i]->crtc_x, - drm_state[i]->crtc_y, drm_state[i]->crtc_w, - drm_state[i]->crtc_h, !q16_data); + src[i].x1 = drm_state[i]->src_x >> 16; + src[i].y1 = drm_state[i]->src_y >> 16; + src[i].x2 = src[i].x1 + (drm_state[i]->src_w >> 16); + src[i].y2 = src[i].y1 + (drm_state[i]->src_h >> 16); - if (src[i].w != dst[i].w || src[i].h != dst[i].h) { + dst[i] = drm_plane_state_dest(drm_state[i]); + + if (drm_rect_calc_hscale(&src[i], &dst[i], 1, 1) != 1 || + drm_rect_calc_vscale(&src[i], &dst[i], 1, 1) != 1) { DPU_ERROR_PLANE(dpu_plane[i], "scaling is not supported in multirect mode\n"); return -EINVAL; @@ -918,7 +923,8 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane) if (has_tiled_rect) width_threshold /= 2; - if (parallel_fetch_qualified && src[i].w > width_threshold) + if (parallel_fetch_qualified && + drm_rect_width(&src[i]) > width_threshold) parallel_fetch_qualified = false; } @@ -936,8 +942,8 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane) /* TIME_MX Mode */ buffer_lines = 2 * max_tile_height; - if ((dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) || - (dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines)) { + if (dst[R1].y1 >= dst[R0].y2 + buffer_lines || + dst[R0].y1 >= dst[R1].y2 + buffer_lines) { pstate[R0]->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX; pstate[R1]->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX; } else { @@ -1059,6 +1065,25 @@ static void dpu_plane_cleanup_fb(struct drm_plane *plane, msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace); } +static bool dpu_plane_validate_src(struct drm_rect *src, + struct drm_rect *fb_rect, + uint32_t min_src_size) +{ + /* Ensure fb size is supported */ + if (drm_rect_width(fb_rect) > MAX_IMG_WIDTH || + drm_rect_height(fb_rect) > MAX_IMG_HEIGHT) + return false; + + /* Ensure src rect is above the minimum size */ + if (drm_rect_width(src) < min_src_size || + drm_rect_height(src) < min_src_size) + return false; + + /* Ensure src is fully encapsulated in fb */ + return drm_rect_intersect(fb_rect, src) && + drm_rect_equals(fb_rect, src); +} + static int dpu_plane_sspp_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { @@ -1066,9 +1091,10 @@ static int dpu_plane_sspp_atomic_check(struct drm_plane *plane, struct dpu_plane *pdpu; struct dpu_plane_state *pstate; const struct dpu_format *fmt; - struct dpu_rect src, dst; - uint32_t max_upscale, max_downscale, min_src_size, max_linewidth; - bool q16_data = true; + struct drm_rect src, dst, fb_rect = { 0 }; + uint32_t max_upscale = 1, max_downscale = 1; + uint32_t min_src_size, max_linewidth; + int hscale = 1, vscale = 1; if (!plane || !state) { DPU_ERROR("invalid arg(s), plane %d state %d\n", @@ -1086,16 +1112,31 @@ static int dpu_plane_sspp_atomic_check(struct drm_plane *plane, goto exit; } - /* src values are in Q16 fixed point, convert to integer */ - POPULATE_RECT(&src, state->src_x, state->src_y, state->src_w, - state->src_h, q16_data); - POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, state->crtc_w, - state->crtc_h, !q16_data); + src.x1 = state->src_x >> 16; + src.y1 = state->src_y >> 16; + src.x2 = src.x1 + (state->src_w >> 16); + src.y2 = src.y1 + (state->src_h >> 16); + + dst = drm_plane_state_dest(state); + + fb_rect.x2 = state->fb->width; + fb_rect.y2 = state->fb->height; - max_upscale = pdpu->pipe_sblk->maxupscale; - max_downscale = pdpu->pipe_sblk->maxdwnscale; max_linewidth = pdpu->pipe_sblk->common->maxlinewidth; + if (pdpu->features & DPU_SSPP_SCALER) { + max_downscale = pdpu->pipe_sblk->maxdwnscale; + max_upscale = pdpu->pipe_sblk->maxupscale; + } + if (drm_rect_width(&src) < drm_rect_width(&dst)) + hscale = drm_rect_calc_hscale(&src, &dst, 1, max_upscale); + else + hscale = drm_rect_calc_hscale(&dst, &src, 1, max_downscale); + if (drm_rect_height(&src) < drm_rect_height(&dst)) + vscale = drm_rect_calc_vscale(&src, &dst, 1, max_upscale); + else + vscale = drm_rect_calc_vscale(&dst, &src, 1, max_downscale); + DPU_DEBUG_PLANE(pdpu, "check %d -> %d\n", dpu_plane_enabled(plane->state), dpu_plane_enabled(state)); @@ -1115,51 +1156,37 @@ static int dpu_plane_sspp_atomic_check(struct drm_plane *plane, ret = -EINVAL; /* check src bounds */ - } else if (state->fb->width > MAX_IMG_WIDTH || - state->fb->height > MAX_IMG_HEIGHT || - src.w < min_src_size || src.h < min_src_size || - CHECK_LAYER_BOUNDS(src.x, src.w, state->fb->width) || - CHECK_LAYER_BOUNDS(src.y, src.h, state->fb->height)) { - DPU_ERROR_PLANE(pdpu, "invalid source %u, %u, %ux%u\n", - src.x, src.y, src.w, src.h); + } else if (!dpu_plane_validate_src(&src, &fb_rect, min_src_size)) { + DPU_ERROR_PLANE(pdpu, "invalid source " DRM_RECT_FMT "\n", + DRM_RECT_ARG(&src)); ret = -E2BIG; /* valid yuv image */ - } else if (DPU_FORMAT_IS_YUV(fmt) && ((src.x & 0x1) || (src.y & 0x1) || - (src.w & 0x1) || (src.h & 0x1))) { - DPU_ERROR_PLANE(pdpu, "invalid yuv source %u, %u, %ux%u\n", - src.x, src.y, src.w, src.h); + } else if (DPU_FORMAT_IS_YUV(fmt) && + (src.x1 & 0x1 || src.y1 & 0x1 || + drm_rect_width(&src) & 0x1 || + drm_rect_height(&src) & 0x1)) { + DPU_ERROR_PLANE(pdpu, "invalid yuv source " DRM_RECT_FMT "\n", + DRM_RECT_ARG(&src)); ret = -EINVAL; /* min dst support */ - } else if (dst.w < 0x1 || dst.h < 0x1) { - DPU_ERROR_PLANE(pdpu, "invalid dest rect %u, %u, %ux%u\n", - dst.x, dst.y, dst.w, dst.h); - ret = -EINVAL; - - /* decimation validation */ - } else if (!(pdpu->features & DPU_SSPP_SCALER) && - ((src.w != dst.w) || (src.h != dst.h))) { - DPU_ERROR_PLANE(pdpu, - "pipe doesn't support scaling %ux%u->%ux%u\n", - src.w, src.h, dst.w, dst.h); + } else if (drm_rect_width(&dst) < 0x1 || drm_rect_height(&dst) < 0x1) { + DPU_ERROR_PLANE(pdpu, "invalid dest rect " DRM_RECT_FMT "\n", + DRM_RECT_ARG(&dst)); ret = -EINVAL; /* check decimated source width */ - } else if (src.w > max_linewidth) { - DPU_ERROR_PLANE(pdpu, - "invalid src w:%u, line w:%u\n", - src.w, max_linewidth); + } else if (drm_rect_width(&src) > max_linewidth) { + DPU_ERROR_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n", + DRM_RECT_ARG(&src), max_linewidth); ret = -E2BIG; - /* check max scaler capability */ - } else if (((src.w * max_upscale) < dst.w) || - ((src.h * max_upscale) < dst.h) || - ((dst.w * max_downscale) < src.w) || - ((dst.h * max_downscale) < src.h)) { - DPU_ERROR_PLANE(pdpu, - "too much scaling requested %ux%u->%ux%u\n", - src.w, src.h, dst.w, dst.h); + /* check scaler capability */ + } else if (hscale < 0 || vscale < 0) { + DPU_ERROR_PLANE(pdpu, "invalid scaling requested src=" + DRM_RECT_FMT " dst=" DRM_RECT_FMT "\n", + DRM_RECT_ARG(&src), DRM_RECT_ARG(&dst)); ret = -E2BIG; } @@ -1253,8 +1280,7 @@ static int dpu_plane_sspp_atomic_update(struct drm_plane *plane, const struct dpu_format *fmt; struct drm_crtc *crtc; struct drm_framebuffer *fb; - struct dpu_rect src, dst; - bool q16_data = true; + struct drm_rect src, dst; if (!plane) { DPU_ERROR("invalid plane\n"); @@ -1293,20 +1319,19 @@ static int dpu_plane_sspp_atomic_update(struct drm_plane *plane, pdpu->is_rt_pipe = (dpu_crtc_get_client_type(crtc) != NRT_CLIENT); _dpu_plane_set_qos_ctrl(plane, false, DPU_PLANE_QOS_PANIC_CTRL); - /* update roi config */ - POPULATE_RECT(&src, state->src_x, state->src_y, - state->src_w, state->src_h, q16_data); - POPULATE_RECT(&dst, state->crtc_x, state->crtc_y, - state->crtc_w, state->crtc_h, !q16_data); + src.x1 = state->src_x >> 16; + src.y1 = state->src_y >> 16; + src.x2 = src.x1 + (state->src_w >> 16); + src.y2 = src.y1 + (state->src_h >> 16); - DPU_DEBUG_PLANE(pdpu, - "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n", - fb->base.id, src.x, src.y, src.w, src.h, - crtc->base.id, dst.x, dst.y, dst.w, dst.h, + dst = drm_plane_state_dest(state); + + DPU_DEBUG_PLANE(pdpu, "FB[%u] " DRM_RECT_FMT "->crtc%u " DRM_RECT_FMT + ", %4.4s ubwc %d\n", fb->base.id, DRM_RECT_ARG(&src), + crtc->base.id, DRM_RECT_ARG(&dst), (char *)&fmt->base.pixel_format, DPU_FORMAT_IS_UBWC(fmt)); - pdpu->pipe_cfg.src_rect = src; pdpu->pipe_cfg.dst_rect = dst; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h index 41fd6a227d8b..1924c6662362 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h @@ -17,6 +17,7 @@ #include <linux/types.h> #include <linux/tracepoint.h> +#include <drm/drm_rect.h> #include "dpu_crtc.h" #include "dpu_encoder_phys.h" #include "dpu_hw_mdss.h" @@ -719,21 +720,20 @@ TRACE_EVENT(dpu_crtc_setup_mixer, ); TRACE_EVENT(dpu_crtc_setup_lm_bounds, - TP_PROTO(uint32_t drm_id, int mixer, struct dpu_rect *bounds), + TP_PROTO(uint32_t drm_id, int mixer, struct drm_rect *bounds), TP_ARGS(drm_id, mixer, bounds), TP_STRUCT__entry( __field( uint32_t, drm_id ) __field( int, mixer ) - __field( struct dpu_rect *, bounds ) + __field( struct drm_rect *, bounds ) ), TP_fast_assign( __entry->drm_id = drm_id; __entry->mixer = mixer; __entry->bounds = bounds; ), - TP_printk("id:%u mixer:%d bounds:{%ux%u/%ux%u}", __entry->drm_id, - __entry->mixer, __entry->bounds->x, __entry->bounds->y, - __entry->bounds->w, __entry->bounds->h) + TP_printk("id:%u mixer:%d bounds:" DRM_RECT_FMT, __entry->drm_id, + __entry->mixer, DRM_RECT_ARG(__entry->bounds)) ); TRACE_EVENT(dpu_crtc_vblank_enable, -- Sean Paul, Software Engineer, Google / Chromium OS -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html