From patchwork Thu Nov 22 11:23:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 10693935 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D822013BF for ; Thu, 22 Nov 2018 11:23:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C7B8D2858D for ; Thu, 22 Nov 2018 11:23:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BC523285A6; Thu, 22 Nov 2018 11:23:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4C60B2858D for ; Thu, 22 Nov 2018 11:23:47 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DEF2C6E488; Thu, 22 Nov 2018 11:23:38 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail.bootlin.com (mail.bootlin.com [62.4.15.54]) by gabe.freedesktop.org (Postfix) with ESMTP id 876F36E436; Thu, 22 Nov 2018 11:23:34 +0000 (UTC) Received: by mail.bootlin.com (Postfix, from userid 110) id 91F3620DA7; Thu, 22 Nov 2018 12:23:33 +0100 (CET) Received: from localhost.localdomain (aaubervilliers-681-1-94-205.w90-88.abo.wanadoo.fr [90.88.35.205]) by mail.bootlin.com (Postfix) with ESMTPSA id 41B8F2037D; Thu, 22 Nov 2018 12:23:33 +0100 (CET) From: Boris Brezillon To: Eric Anholt Subject: [PATCH v3 2/3] drm/vc4: Take underscan setup into account when updating planes Date: Thu, 22 Nov 2018 12:23:30 +0100 Message-Id: <20181122112331.17735-3-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181122112331.17735-1-boris.brezillon@bootlin.com> References: <20181122112331.17735-1-boris.brezillon@bootlin.com> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nouveau@lists.freedesktop.org, dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org, Boris Brezillon , Ben Skeggs , Alex Deucher , =?utf-8?q?Christian_K=C3=B6nig?= MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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],