diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.19/950-0716-drm-vc4-Take-margin-setup-into-account-when-updating.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.19/950-0716-drm-vc4-Take-margin-setup-into-account-when-updating.patch | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.19/950-0716-drm-vc4-Take-margin-setup-into-account-when-updating.patch b/target/linux/brcm2708/patches-4.19/950-0716-drm-vc4-Take-margin-setup-into-account-when-updating.patch new file mode 100644 index 0000000000..dadd23f6d1 --- /dev/null +++ b/target/linux/brcm2708/patches-4.19/950-0716-drm-vc4-Take-margin-setup-into-account-when-updating.patch @@ -0,0 +1,185 @@ +From 461711465ee64817a2c3bfc47d3f670c20a5a972 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon <boris.brezillon@bootlin.com> +Date: Thu, 6 Dec 2018 15:24:38 +0100 +Subject: [PATCH 716/782] drm/vc4: Take margin setup into account when updating + planes + +Commit 666e73587f90f42d90385c1bea1009a650bf73f4 upstream. + +Applyin margins is just a matter of scaling all planes appropriately +and adjusting the CRTC X/Y offset to account for the +left/right/top/bottom borders. + +Create a vc4_plane_margins_adj() function doing that and call it from +vc4_plane_setup_clipping_and_scaling() so that we are ready to attach +margins properties to the HDMI connector. + +Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> +Reviewed-by: Eric Anholt <eric@anholt.net> +Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> +Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-5-boris.brezillon@bootlin.com +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 43 +++++++++++++++++++++++++++ + drivers/gpu/drm/vc4/vc4_drv.h | 3 ++ + drivers/gpu/drm/vc4/vc4_plane.c | 51 +++++++++++++++++++++++++++++++++ + 3 files changed, 97 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -48,6 +48,13 @@ struct vc4_crtc_state { + struct drm_mm_node mm; + bool feed_txp; + bool txp_armed; ++ ++ struct { ++ unsigned int left; ++ unsigned int right; ++ unsigned int top; ++ unsigned int bottom; ++ } margins; + }; + + static inline struct vc4_crtc_state * +@@ -623,6 +630,37 @@ static enum drm_mode_status vc4_crtc_mod + return MODE_OK; + } + ++void vc4_crtc_get_margins(struct drm_crtc_state *state, ++ unsigned int *left, unsigned int *right, ++ unsigned int *top, unsigned int *bottom) ++{ ++ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state); ++ struct drm_connector_state *conn_state; ++ struct drm_connector *conn; ++ int i; ++ ++ *left = vc4_state->margins.left; ++ *right = vc4_state->margins.right; ++ *top = vc4_state->margins.top; ++ *bottom = vc4_state->margins.bottom; ++ ++ /* We have to interate over all new connector states because ++ * vc4_crtc_get_margins() might be called before ++ * vc4_crtc_atomic_check() which means margins info in vc4_crtc_state ++ * might be outdated. ++ */ ++ for_each_new_connector_in_state(state->state, conn, conn_state, i) { ++ if (conn_state->crtc != state->crtc) ++ continue; ++ ++ *left = conn_state->tv.margins.left; ++ *right = conn_state->tv.margins.right; ++ *top = conn_state->tv.margins.top; ++ *bottom = conn_state->tv.margins.bottom; ++ break; ++ } ++} ++ + static int vc4_crtc_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) + { +@@ -670,6 +708,10 @@ static int vc4_crtc_atomic_check(struct + vc4_state->feed_txp = false; + } + ++ vc4_state->margins.left = conn_state->tv.margins.left; ++ vc4_state->margins.right = conn_state->tv.margins.right; ++ vc4_state->margins.top = conn_state->tv.margins.top; ++ vc4_state->margins.bottom = conn_state->tv.margins.bottom; + break; + } + +@@ -971,6 +1013,7 @@ static struct drm_crtc_state *vc4_crtc_d + + old_vc4_state = to_vc4_crtc_state(crtc->state); + vc4_state->feed_txp = old_vc4_state->feed_txp; ++ vc4_state->margins = old_vc4_state->margins; + + __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base); + return &vc4_state->base; +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -705,6 +705,9 @@ bool vc4_crtc_get_scanoutpos(struct drm_ + const struct drm_display_mode *mode); + void vc4_crtc_handle_vblank(struct vc4_crtc *crtc); + void vc4_crtc_txp_armed(struct drm_crtc_state *state); ++void vc4_crtc_get_margins(struct drm_crtc_state *state, ++ unsigned int *right, unsigned int *left, ++ unsigned int *top, unsigned int *bottom); + + /* vc4_debugfs.c */ + int vc4_debugfs_init(struct drm_minor *minor); +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -258,6 +258,52 @@ static u32 vc4_get_scl_field(struct drm_ + } + } + ++static int vc4_plane_margins_adj(struct drm_plane_state *pstate) ++{ ++ struct vc4_plane_state *vc4_pstate = to_vc4_plane_state(pstate); ++ unsigned int left, right, top, bottom, adjhdisplay, adjvdisplay; ++ struct drm_crtc_state *crtc_state; ++ ++ crtc_state = drm_atomic_get_new_crtc_state(pstate->state, ++ pstate->crtc); ++ ++ vc4_crtc_get_margins(crtc_state, &left, &right, &top, &bottom); ++ if (!left && !right && !top && !bottom) ++ return 0; ++ ++ if (left + right >= crtc_state->mode.hdisplay || ++ top + bottom >= crtc_state->mode.vdisplay) ++ return -EINVAL; ++ ++ adjhdisplay = crtc_state->mode.hdisplay - (left + right); ++ vc4_pstate->crtc_x = DIV_ROUND_CLOSEST(vc4_pstate->crtc_x * ++ adjhdisplay, ++ crtc_state->mode.hdisplay); ++ vc4_pstate->crtc_x += left; ++ if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - left) ++ vc4_pstate->crtc_x = crtc_state->mode.hdisplay - left; ++ ++ adjvdisplay = crtc_state->mode.vdisplay - (top + bottom); ++ vc4_pstate->crtc_y = DIV_ROUND_CLOSEST(vc4_pstate->crtc_y * ++ adjvdisplay, ++ crtc_state->mode.vdisplay); ++ vc4_pstate->crtc_y += top; ++ if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - top) ++ vc4_pstate->crtc_y = crtc_state->mode.vdisplay - top; ++ ++ vc4_pstate->crtc_w = DIV_ROUND_CLOSEST(vc4_pstate->crtc_w * ++ adjhdisplay, ++ crtc_state->mode.hdisplay); ++ vc4_pstate->crtc_h = DIV_ROUND_CLOSEST(vc4_pstate->crtc_h * ++ adjvdisplay, ++ crtc_state->mode.vdisplay); ++ ++ if (!vc4_pstate->crtc_w || !vc4_pstate->crtc_h) ++ return -EINVAL; ++ ++ return 0; ++} ++ + static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) + { + struct drm_plane *plane = state->plane; +@@ -269,6 +315,7 @@ static int vc4_plane_setup_clipping_and_ + int num_planes = fb->format->num_planes; + u32 h_subsample = 1; + u32 v_subsample = 1; ++ int ret; + int i; + + for (i = 0; i < num_planes; i++) +@@ -292,6 +339,10 @@ static int vc4_plane_setup_clipping_and_ + vc4_state->crtc_w = state->crtc_w; + vc4_state->crtc_h = state->crtc_h; + ++ ret = vc4_plane_margins_adj(state); ++ if (ret) ++ return ret; ++ + vc4_state->x_scaling[0] = vc4_get_scaling_mode(vc4_state->src_w[0], + vc4_state->crtc_w); + vc4_state->y_scaling[0] = vc4_get_scaling_mode(vc4_state->src_h[0], |