From patchwork Tue Jul 10 10:32:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Russell King (Oracle)" X-Patchwork-Id: 10518917 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 20FF56028E for ; Wed, 11 Jul 2018 07:19:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0985F2621E for ; Wed, 11 Jul 2018 07:19:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F232028E9D; Wed, 11 Jul 2018 07:19:57 +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 97A992621E for ; Wed, 11 Jul 2018 07:19:57 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 369956EBC4; Wed, 11 Jul 2018 07:17:20 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from pandora.armlinux.org.uk (pandora.armlinux.org.uk [IPv6:2001:4d48:ad52:3201:214:fdff:fe10:1be6]) by gabe.freedesktop.org (Postfix) with ESMTPS id 185AF6E904 for ; Tue, 10 Jul 2018 10:32:54 +0000 (UTC) Received: from e0022681537dd.dyn.armlinux.org.uk ([fd8f:7570:feb6:1:222:68ff:fe15:37dd]:48110 helo=rmk-PC.armlinux.org.uk) by pandora.armlinux.org.uk with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.90_1) (envelope-from ) id 1fcpww-0002lg-8w; Tue, 10 Jul 2018 11:32:50 +0100 Received: from rmk by rmk-PC.armlinux.org.uk with local (Exim 4.82_1-5b7a7c0-XX) (envelope-from ) id 1fcpwv-00041F-HQ; Tue, 10 Jul 2018 11:32:49 +0100 In-Reply-To: <20180710103106.GI17271@n2100.armlinux.org.uk> References: <20180710103106.GI17271@n2100.armlinux.org.uk> From: Russell King To: dri-devel@lists.freedesktop.org Subject: [PATCH 08/17] drm/armada: convert page_flip to use primary plane atomic_update() MIME-Version: 1.0 Content-Disposition: inline Message-Id: Date: Tue, 10 Jul 2018 11:32:49 +0100 X-Mailman-Approved-At: Wed, 11 Jul 2018 07:16:21 +0000 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: David Airlie Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP page_flip requests happen asynchronously, so we can't wait on the vblank event before returning to userspace, as the transitional plane update helper would do. Craft our own implementation that keeps the asynchronous behaviour of this request, while making use of the atomic infrastructure for the primary plane update. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 81 ++++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 523e0e8c6962..50b34f5fc97b 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -939,53 +940,81 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc) * and a mode_set. */ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t page_flip_flags, - struct drm_modeset_acquire_ctx *ctx) + struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, + uint32_t page_flip_flags, struct drm_modeset_acquire_ctx *ctx) { struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); + struct drm_plane *plane = crtc->primary; + const struct drm_plane_helper_funcs *plane_funcs; + struct drm_plane_state *state; struct armada_plane_work *work; - unsigned i; int ret; - work = armada_drm_crtc_alloc_plane_work(dcrtc->crtc.primary); - if (!work) + /* Construct new state for the primary plane */ + state = drm_atomic_helper_plane_duplicate_state(plane); + if (!state) return -ENOMEM; - work->event = event; - work->old_fb = dcrtc->crtc.primary->fb; + drm_atomic_set_fb_for_plane(state, fb); - i = armada_drm_crtc_calc_fb(fb, crtc->x, crtc->y, work->regs, - dcrtc->interlaced); - armada_reg_queue_end(work->regs, i); + work = armada_drm_crtc_alloc_plane_work(plane); + if (!work) { + ret = -ENOMEM; + goto put_state; + } + + /* Make sure we can get vblank interrupts */ + ret = drm_crtc_vblank_get(crtc); + if (ret) + goto put_work; /* - * Ensure that we hold a reference on the new framebuffer. - * This has to match the behaviour in mode_set. + * If we have another work pending, we can't process this flip. + * The modeset locks protect us from another user queuing a work + * while we're setting up. */ - drm_framebuffer_get(fb); - - ret = armada_drm_plane_work_queue(dcrtc, work); - if (ret) { - /* Undo our reference above */ - drm_framebuffer_put(fb); - kfree(work); - return ret; + if (drm_to_armada_plane(plane)->work) { + ret = -EBUSY; + goto put_vblank; } + work->event = event; + work->old_fb = plane->state->fb; + /* - * We are in transition to atomic modeset: update the atomic modeset - * state with the new framebuffer to keep the state consistent. + * Hold a ref on the new fb while it's being displayed by the + * hardware. The old fb refcount will be released in the worker. */ - drm_framebuffer_assign(&dcrtc->crtc.primary->state->fb, fb); + drm_framebuffer_get(state->fb); + + /* Point of no return */ + swap(plane->state, state); + + dcrtc->regs_idx = 0; + dcrtc->regs = work->regs; + + plane_funcs = plane->helper_private; + plane_funcs->atomic_update(plane, state); + armada_reg_queue_end(dcrtc->regs, dcrtc->regs_idx); + + /* Queue the work - this should never fail */ + WARN_ON(armada_drm_plane_work_queue(dcrtc, work)); + work = NULL; /* * Finally, if the display is blanked, we won't receive an * interrupt, so complete it now. */ if (dpms_blanked(dcrtc->dpms)) - armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary); - - return 0; + armada_drm_plane_work_run(dcrtc, plane); + +put_vblank: + drm_crtc_vblank_put(crtc); +put_work: + kfree(work); +put_state: + drm_atomic_helper_plane_destroy_state(plane, state); + return ret; } static int