From patchwork Tue Sep 29 18:11:02 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Russell King X-Patchwork-Id: 7289401 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 94624BEEA4 for ; Tue, 29 Sep 2015 18:17:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7007720687 for ; Tue, 29 Sep 2015 18:17:46 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id D18AE206DC for ; Tue, 29 Sep 2015 18:17:44 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1097D6E76A; Tue, 29 Sep 2015 11:17:44 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from pandora.arm.linux.org.uk (pandora.arm.linux.org.uk [78.32.30.218]) by gabe.freedesktop.org (Postfix) with ESMTPS id D49246E7AF for ; Tue, 29 Sep 2015 11:17:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=arm.linux.org.uk; s=pandora-2014; h=Date:Sender:Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Subject:To:From:References:In-Reply-To; bh=YJ62IO0Vz0R/ipZZww7iJr/vOWjzDTEEEA77/HysebE=; b=cLl4LVSJHC8KFqN8gM42Q/+zql58AY/A7cDXglChcuNECWulptcWp6fKyhNrpcLcayPpit7ZUBpAl2sYQF4tOVWNWktpCRj2RCEzTcfvUIifiwIFAZCPiSu7rkzP4PqCNbv0PFDgn+1WPxwoUx5JRBgB9w8fF7ru4qBRAUJENZY=; Received: from e0022681537dd.dyn.arm.linux.org.uk ([2001:4d48:ad52:3201:222:68ff:fe15:37dd]:55809 helo=rmk-PC.arm.linux.org.uk) by pandora.arm.linux.org.uk with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.82_1-5b7a7c0-XX) (envelope-from ) id 1ZgzMl-0004LD-W9 for dri-devel@lists.freedesktop.org; Tue, 29 Sep 2015 19:11:04 +0100 Received: from rmk by rmk-PC.arm.linux.org.uk with local (Exim 4.82_1-5b7a7c0-XX) (envelope-from ) id 1ZgzMk-0003mL-AK for dri-devel@lists.freedesktop.org; Tue, 29 Sep 2015 19:11:02 +0100 In-Reply-To: <20150929180843.GP21513@n2100.arm.linux.org.uk> References: <20150929180843.GP21513@n2100.arm.linux.org.uk> From: Russell King To: dri-devel@lists.freedesktop.org Subject: [PATCH 18/20] drm/armada: move CRTC flip work to primary plane work MIME-Version: 1.0 Content-Disposition: inline Message-Id: Date: Tue, 29 Sep 2015 19:11:02 +0100 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add a plane work implementation, and move the CRTC framebuffer flip work to it for the primary plane. The idea is to have a common plane work implementation for both the primary and overlay planes. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 102 ++++++++++++++++++++--------------- drivers/gpu/drm/armada/armada_crtc.h | 15 ++++-- 2 files changed, 70 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 46d932bc7678..0c1a1524f5d5 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -20,6 +20,7 @@ #include "armada_hw.h" struct armada_frame_work { + struct armada_plane_work work; struct drm_pending_vblank_event *event; struct armada_regs regs[4]; struct drm_framebuffer *old_fb; @@ -190,6 +191,41 @@ static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb, return i; } +static void armada_drm_plane_work_run(struct armada_crtc *dcrtc, + struct armada_plane *plane) +{ + struct armada_plane_work *work = xchg(&plane->work, NULL); + + /* Handle any pending frame work. */ + if (work) { + work->fn(dcrtc, plane, work); + drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); + } +} + +int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, + struct armada_plane *plane, struct armada_plane_work *work) +{ + int ret; + + ret = drm_vblank_get(dcrtc->crtc.dev, dcrtc->num); + if (ret) { + DRM_ERROR("failed to acquire vblank counter\n"); + return ret; + } + + ret = cmpxchg(&plane->work, NULL, work) ? -EBUSY : 0; + if (ret) + drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); + + return ret; +} + +int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout) +{ + return wait_event_timeout(plane->frame_wait, !plane->work, timeout); +} + void armada_drm_vbl_event_add(struct armada_crtc *dcrtc, struct armada_vbl_event *evt) { @@ -233,44 +269,31 @@ static void armada_drm_vbl_event_run(struct armada_crtc *dcrtc) static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, struct armada_frame_work *work) { - struct drm_device *dev = dcrtc->crtc.dev; - int ret; + struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary); - ret = drm_vblank_get(dev, dcrtc->num); - if (ret) { - DRM_ERROR("failed to acquire vblank counter\n"); - return ret; - } - - if (cmpxchg(&dcrtc->frame_work, NULL, work)) { - drm_vblank_put(dev, dcrtc->num); - ret = -EBUSY; - } - - return ret; + return armada_drm_plane_work_queue(dcrtc, plane, &work->work); } static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc, - struct armada_frame_work *work) + struct armada_plane *plane, struct armada_plane_work *work) { + struct armada_frame_work *fwork = container_of(work, struct armada_frame_work, work); struct drm_device *dev = dcrtc->crtc.dev; unsigned long flags; spin_lock_irqsave(&dcrtc->irq_lock, flags); - armada_drm_crtc_update_regs(dcrtc, work->regs); + armada_drm_crtc_update_regs(dcrtc, fwork->regs); spin_unlock_irqrestore(&dcrtc->irq_lock, flags); - if (work->event) { + if (fwork->event) { spin_lock_irqsave(&dev->event_lock, flags); - drm_send_vblank_event(dev, dcrtc->num, work->event); + drm_send_vblank_event(dev, dcrtc->num, fwork->event); spin_unlock_irqrestore(&dev->event_lock, flags); } - drm_vblank_put(dev, dcrtc->num); - /* Finally, queue the process-half of the cleanup. */ - __armada_drm_queue_unref_work(dcrtc->crtc.dev, work->old_fb); - kfree(work); + __armada_drm_queue_unref_work(dcrtc->crtc.dev, fwork->old_fb); + kfree(fwork); } static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc, @@ -290,6 +313,7 @@ static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc, work = kmalloc(sizeof(*work), GFP_KERNEL); if (work) { int i = 0; + work->work.fn = armada_drm_crtc_complete_frame_work; work->event = NULL; work->old_fb = fb; armada_reg_queue_end(work->regs, i); @@ -310,18 +334,14 @@ static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc, static void armada_drm_vblank_off(struct armada_crtc *dcrtc) { - struct armada_frame_work *work; + struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary); /* * Tell the DRM core that vblank IRQs aren't going to happen for * a while. This cleans up any pending vblank events for us. */ drm_crtc_vblank_off(&dcrtc->crtc); - - /* Handle any pending flip event. */ - work = xchg(&dcrtc->frame_work, NULL); - if (work) - armada_drm_crtc_complete_frame_work(dcrtc, work); + armada_drm_plane_work_run(dcrtc, plane); } void armada_drm_crtc_gamma_set(struct drm_crtc *crtc, u16 r, u16 g, u16 b, @@ -450,12 +470,9 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) spin_unlock(&dcrtc->irq_lock); if (stat & GRA_FRAME_IRQ) { - struct armada_frame_work *work = xchg(&dcrtc->frame_work, NULL); - - if (work) - armada_drm_crtc_complete_frame_work(dcrtc, work); - - wake_up(&drm_to_armada_plane(dcrtc->crtc.primary)->frame_wait); + struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary); + armada_drm_plane_work_run(dcrtc, plane); + wake_up(&plane->frame_wait); } } @@ -571,8 +588,8 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, adj->crtc_vtotal, tm, bm); /* Wait for pending flips to complete */ - wait_event(drm_to_armada_plane(dcrtc->crtc.primary)->frame_wait, - !dcrtc->frame_work); + armada_drm_plane_work_wait(drm_to_armada_plane(dcrtc->crtc.primary), + MAX_SCHEDULE_TIMEOUT); drm_crtc_vblank_off(crtc); @@ -689,8 +706,8 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, armada_reg_queue_end(regs, i); /* Wait for pending flips to complete */ - wait_event(drm_to_armada_plane(dcrtc->crtc.primary)->frame_wait, - !dcrtc->frame_work); + armada_drm_plane_work_wait(drm_to_armada_plane(dcrtc->crtc.primary), + MAX_SCHEDULE_TIMEOUT); /* Take a reference to the new fb as we're using it */ drm_framebuffer_reference(crtc->primary->fb); @@ -1013,6 +1030,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, if (!work) return -ENOMEM; + work->work.fn = armada_drm_crtc_complete_frame_work; work->event = event; work->old_fb = dcrtc->crtc.primary->fb; @@ -1046,12 +1064,8 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, * Finally, if the display is blanked, we won't receive an * interrupt, so complete it now. */ - if (dpms_blanked(dcrtc->dpms)) { - struct armada_frame_work *work = xchg(&dcrtc->frame_work, NULL); - - if (work) - armada_drm_crtc_complete_frame_work(dcrtc, work); - } + if (dpms_blanked(dcrtc->dpms)) + armada_drm_plane_work_run(dcrtc, drm_to_armada_plane(dcrtc->crtc.primary)); return 0; } diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index 3ec5101e13f7..aaad5ab78673 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -31,16 +31,27 @@ struct armada_regs { #define armada_reg_queue_end(_r, _i) \ armada_reg_queue_mod(_r, _i, 0, 0, ~0) -struct armada_frame_work; +struct armada_crtc; +struct armada_plane; struct armada_variant; +struct armada_plane_work { + void (*fn)(struct armada_crtc *, + struct armada_plane *, + struct armada_plane_work *); +}; + struct armada_plane { struct drm_plane base; wait_queue_head_t frame_wait; + struct armada_plane_work *work; }; #define drm_to_armada_plane(p) container_of(p, struct armada_plane, base) int armada_drm_plane_init(struct armada_plane *plane); +int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, + struct armada_plane *plane, struct armada_plane_work *work); +int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout); struct armada_crtc { struct drm_crtc crtc; @@ -74,8 +85,6 @@ struct armada_crtc { uint32_t dumb_ctrl; uint32_t spu_iopad_ctrl; - struct armada_frame_work *frame_work; - spinlock_t irq_lock; uint32_t irq_ena; struct list_head vbl_list;