Applying an underscan setup is just a matter of scaling all planes appropriately and adjusting the CRTC X/Y offset to account for the horizontal and vertical border. Create an vc4_plane_underscan_adj() function doing that and call it from vc4_plane_setup_clipping_and_scaling() so that we are ready to attach underscan properties to the HDMI connector. Signed-off-by: Boris Brezillon <boris.brezillon@xxxxxxxxxxx> --- Changes in v3: - Rebase on top of the "cursor rescaling" changes Changes in v2: - Take changes on hborder/vborder meaning into account --- drivers/gpu/drm/vc4/vc4_crtc.c | 47 +++++++++++++++++++++++++++++++ drivers/gpu/drm/vc4/vc4_drv.h | 3 ++ drivers/gpu/drm/vc4/vc4_plane.c | 50 +++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 3ce136ba8791..3ace68186f07 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -49,6 +49,11 @@ struct vc4_crtc_state { struct drm_mm_node mm; bool feed_txp; bool txp_armed; + + struct { + unsigned int vborder; + unsigned int hborder; + } underscan; }; static inline struct vc4_crtc_state * @@ -624,6 +629,39 @@ static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc, return MODE_OK; } +void vc4_crtc_get_underscan_borders(struct drm_crtc_state *state, + unsigned int *vborder, + unsigned int *hborder) +{ + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state); + struct drm_connector_state *conn_state; + struct drm_connector *conn; + int i; + + *vborder = vc4_state->underscan.vborder; + *hborder = vc4_state->underscan.hborder; + + /* We have to interate over all new connector states because + * vc4_crtc_get_underscan_borders() might be called before + * vc4_crtc_atomic_check() which means underscan 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; + + if (conn_state->underscan.mode == DRM_UNDERSCAN_ON) { + *vborder = conn_state->underscan.vborder; + *hborder = conn_state->underscan.hborder; + } else { + *vborder = 0; + *hborder = 0; + } + + break; + } +} + static int vc4_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -657,6 +695,7 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc, return ret; for_each_new_connector_in_state(state->state, conn, conn_state, i) { + unsigned int vborder = 0, hborder = 0; if (conn_state->crtc != crtc) continue; @@ -671,6 +710,13 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc, vc4_state->feed_txp = false; } + if (conn_state->underscan.mode == DRM_UNDERSCAN_ON) { + vborder = conn_state->underscan.vborder; + hborder = conn_state->underscan.hborder; + } + + vc4_state->underscan.vborder = vborder; + vc4_state->underscan.hborder = hborder; break; } @@ -972,6 +1018,7 @@ static struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc) old_vc4_state = to_vc4_crtc_state(crtc->state); vc4_state->feed_txp = old_vc4_state->feed_txp; + vc4_state->underscan = old_vc4_state->underscan; __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base); return &vc4_state->base; diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index d1000c4805c2..ce08c5dc199d 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -707,6 +707,9 @@ bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, 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_underscan_borders(struct drm_crtc_state *state, + unsigned int *vborder, + unsigned int *hborder); /* vc4_debugfs.c */ int vc4_debugfs_init(struct drm_minor *minor); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 8cda0d460a6d..78705d9ae25d 100644 --- 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_plane_state *state, int plane) } } +static int vc4_plane_underscan_adj(struct drm_plane_state *pstate) +{ + struct vc4_plane_state *vc4_pstate = to_vc4_plane_state(pstate); + unsigned int vborder, hborder, adjhdisplay, adjvdisplay; + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_new_crtc_state(pstate->state, + pstate->crtc); + + vc4_crtc_get_underscan_borders(crtc_state, &vborder, &hborder); + if (!vborder && !hborder) + return 0; + + if (hborder * 2 >= crtc_state->mode.hdisplay || + vborder * 2 >= crtc_state->mode.vdisplay) + return -EINVAL; + + adjhdisplay = crtc_state->mode.hdisplay - (2 * hborder); + vc4_pstate->crtc_x = DIV_ROUND_CLOSEST(vc4_pstate->crtc_x * + adjhdisplay, + crtc_state->mode.hdisplay); + vc4_pstate->crtc_x += hborder; + if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - hborder) + vc4_pstate->crtc_x = crtc_state->mode.hdisplay - hborder; + + adjvdisplay = crtc_state->mode.vdisplay - (2 * vborder); + vc4_pstate->crtc_y = DIV_ROUND_CLOSEST(vc4_pstate->crtc_y * + adjvdisplay, + crtc_state->mode.vdisplay); + vc4_pstate->crtc_y += vborder; + if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - vborder) + vc4_pstate->crtc_y = crtc_state->mode.vdisplay - vborder; + + 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 vc4_plane_state *vc4_state = to_vc4_plane_state(state); @@ -306,6 +352,10 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) vc4_state->crtc_w = state->dst.x2 - state->dst.x1; vc4_state->crtc_h = state->dst.y2 - state->dst.y1; + ret = vc4_plane_underscan_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], -- 2.17.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel