From patchwork Tue May 31 09:24:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ying Liu X-Patchwork-Id: 9144039 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 7605960761 for ; Tue, 31 May 2016 09:25:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 67B4825D97 for ; Tue, 31 May 2016 09:25:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5C6172796F; Tue, 31 May 2016 09:25:14 +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=-4.2 required=2.0 tests=BAD_ENC_HEADER,BAYES_00, DKIM_ADSP_CUSTOM_MED,FREEMAIL_FROM,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A7AAC25D97 for ; Tue, 31 May 2016 09:25:13 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6C8786E372; Tue, 31 May 2016 09:25:09 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from na01-by2-obe.outbound.protection.outlook.com (mail-by2on0067.outbound.protection.outlook.com [207.46.100.67]) by gabe.freedesktop.org (Postfix) with ESMTPS id ACE826E374 for ; Tue, 31 May 2016 09:25:07 +0000 (UTC) Received: from BN3PR0301CA0068.namprd03.prod.outlook.com (10.160.152.164) by BLUPR0301MB1588.namprd03.prod.outlook.com (10.162.214.22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.511.6; Tue, 31 May 2016 09:25:06 +0000 Received: from BN1BFFO11FD016.protection.gbl (2a01:111:f400:7c10::1:100) by BN3PR0301CA0068.outlook.office365.com (2a01:111:e400:401e::36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.506.9 via Frontend Transport; Tue, 31 May 2016 09:25:06 +0000 Authentication-Results: spf=softfail (sender IP is 192.88.158.2) smtp.mailfrom=gmail.com; ffwll.ch; dkim=none (message not signed) header.d=none; ffwll.ch; dmarc=fail action=none header.from=gmail.com; Received-SPF: SoftFail (protection.outlook.com: domain of transitioning gmail.com discourages use of 192.88.158.2 as permitted sender) Received: from az84smr01.freescale.net (192.88.158.2) by BN1BFFO11FD016.mail.protection.outlook.com (10.58.144.79) with Microsoft SMTP Server (TLS) id 15.1.497.8 via Frontend Transport; Tue, 31 May 2016 09:25:04 +0000 Received: from victor.ap.freescale.net (victor.ap.freescale.net [10.192.241.62]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id u4V9OfRT013844; Tue, 31 May 2016 02:25:02 -0700 From: Liu Ying To: Subject: [PATCH v2 09/10] drm/imx: atomic phase 3 step 4: Use generic atomic page flip Date: Tue, 31 May 2016 17:24:30 +0800 Message-ID: <1464686671-20299-10-git-send-email-gnuiyl@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1464686671-20299-1-git-send-email-gnuiyl@gmail.com> References: <1464686671-20299-1-git-send-email-gnuiyl@gmail.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131091603051494839; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.158.2; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(2980300002)(189002)(199003)(9170700003)(87572001)(50986999)(76482005)(76176999)(87936001)(73392002)(81166006)(11100500001)(55446002)(189998001)(81442002)(229853001)(33646002)(5003940100001)(104016004)(8676002)(6806005)(82202001)(73972006)(36756003)(6260500002)(5008740100001)(61266001)(48376002)(19580405001)(50466002)(47776003)(86362001)(110136002)(19580395003)(83322999)(2950100001)(2351001)(586003)(105596002)(106466001)(77096005)(4326007)(5890100001)(2906002)(50226002)(92566002)(8936002)(41533002); DIR:OUT; SFP:1101; SCL:1; SRVR:BLUPR0301MB1588; H:az84smr01.freescale.net; FPR:; SPF:SoftFail; MLV:sfv; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BN1BFFO11FD016; 1:9pKYm8oWcEunNAW6rFS26OlfMmkNBlI0qEocf4UucGAHPN80hKfLsxw9jQhedzmXINUTvY308olh8ughqI6R/vVoKzjsn+tDN249T7cFZXawMTluqYv+r9QMYuEXj19LbcAVXhMlYT55u9hV1osPrQEdtnRMyjrAjhx9rPxbX2jYJxaY+lFVU3pR4BvZIeCJWO+g2UNPswkpzMQpSE8NpLdyIp9Ik7S4JnMndODuSEbTBPpa4qGxrU12vFCOuibExKy3qZ1e88WKe1qHRPukpJ2O1Bz1JlHgQ297nY5CO0Zy6zg7vzN3T3LNKZ4MLqfKEFPkNXRAdCNGa5QsCVn5ZoZQo8o8GSfjvDy1mgYszcIWysdfvo5cOmo91FCUe8npNP0LMZ/p3ZtI9jWkUgDz6F8SExEoUcZ/e++BMKwJpY3w1nX4SuPfBPPdikdr6sCJygleNyHup00TjZmN4aFQmf+3LS14Qq5hCw5aL1ykbmXOyHxubERiHfRunPO8N6FHNjHFAVDfxtsn3564pv8mLSffDjFLXe6OsL/eOdp5EUZYP0+yHcGGcCmsNPOzxMmb MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: c55548a9-7d65-4810-5c56-08d389357360 X-Microsoft-Exchange-Diagnostics: 1; BLUPR0301MB1588; 2:Gi0nr6I1TcSSVQzRMJ2ea5tky1ppePA2S7rRLj9gmM6I4thsrBPzdcexoTKG257D64hAXTwd4dzCIM9xg2tMfS0BNB7ANjDjdLizAQH78YSLip7900zEvlNg1G3dhaaeTS/Y2AZ/Q3keL7Oh5OQmRcniMrEWHc1XOzOXHb6FKkWrMVbHdDXCcZ8fD0rY8gS6; 3:IiPlObYvJO7KYX7p+MFlcveVoQjp5fD9gYPJqgw15fQfE2a8QWk7VDuLz4r8MguzqmIZRCu6lUDOQrWDjDvgesX+Mv5jcdnM0vDcln1xG8pa2ajS3rZYGXC2wEBm4OX4+91ddmH99D5R6PZ5KmOqxAeQbC225/9ZYxtupOOiRuoyfcb+UzI/lkKI0cdhd3wAc2Hr9DJQPqBajXGVEu2fecUw2FOZpC1qqmBJPfWwafE=; 25:P6lSEGT5/yL0lLjZd0Q48vdcydXzV7zYv3QzXw/wpt7Cz+m90B8fIBJwdYp1SNMzPBENKjTBr+A8vHwigYKkdNjpdZBoEm3tshCuHw2mJSCu35Q5Zrm2KAigyL82sIUcBSnrOi08dhS+uZGdxV/sl2r4MXhMlgGto1eijd1lKsrnHJArPglsTRqTF+xwBwlqHCwkpGRPpXSNRJIo3EMs/zaA/pwconC4MFuvsqDwFXwPrb7zXhHTgCisdysv89NcDGR8uRwIQT3bRgFHQP+UQKTAe003EL0ikb7qFjeBECZPB8zH0LABF457OqI4wUdtSx9fIzkDl7pD+ruNTpW/lM1/vU+mS1upf2i1OCSQMoubDAqwhff4U77eqN7qmpn47HnZQIYph+zgWtYHllr3fnEuJ9SDld6kYs1jKgQ3YUE= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BLUPR0301MB1588; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(13018025)(13017025)(13015025)(13023025)(13024025)(8121501046)(5005006)(3002001)(10201501046)(6055026); SRVR:BLUPR0301MB1588; BCL:0; PCL:0; RULEID:(400006); SRVR:BLUPR0301MB1588; X-Microsoft-Exchange-Diagnostics: 1; BLUPR0301MB1588; 4:YzUOL/jtED9JtZw5HSTYVD60vSEdTe3ePSuomTynkY7oUgg5OHLTWW06SNo9e+G5/D89b2tECxzmi5qwm7kdz4/Ov9L9oISCjJ163iqHP9c00jZwxBJ3BiwFPFz7HUctOSk6hQUtlWGks5Dt/64yo7A67T1EELV0zvmBHZu2x9+Ts4utnI1cV2T0JcbGdyXu1IosYkScg7S2s/ttC3ksPLkZMpRNfNrXuXtjcJqDtKc7/ddMtq/HdELw3bD95jjAWQA9CIKe++tRscPAI0QS4Ax3r/R+WHHAmgmE7HAOMiHeCfABlNA1H9P/p9Bghk/zrZlQHp1YpVSE1ea9aFidAHWmFNgtgscgjRH6Mae1vlmSQRMCT5EivPDexGUZCiT9jAFG85vlFStHLw41s3lDCc0fh8rYGWcracBnbehioO4RO+tzCWprLIunzeQ7PtBZ8VNi32EuuCeHEHgypj4lyibpSBIidDluPCLdMvyn7qw= X-Forefront-PRVS: 095972DF2F X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BLUPR0301MB1588; 23:bL8lPj/qaa1R7dh79LfPxonrO26umVmUPfISI+6?= =?us-ascii?Q?ZBKxRzYJTZhamHfJpZdwwRnJpViLeZ3Yg73MaFOjp9EYekkJw50Un0ZI3Y81?= =?us-ascii?Q?+WAadDUOfnnzHVHQ/9Rwujz3RmJgqPh5Bl2TxN66UQOmdjmqmDPkM9lUOQZl?= =?us-ascii?Q?VW9D5ILP1jfpIjIBUU7X6rWBh0HJDlqsLABop6Lp9O8i3BqisxmkeP+RGTZT?= =?us-ascii?Q?shbEmZSCb1DklEWnEinK1zdt9n2BdfiVY74CfDX/HSWX80peMepepuCu2bM6?= =?us-ascii?Q?uEF+JobcondrjRE5gINboLwrm0TNHyf+CHKmprUNt4yCkf9JTnUcbmKuJ8Kg?= =?us-ascii?Q?xMUhu6TqF/jwd0KBfh8sslPWM913fpYl5AqAG00DRX7opCMHL0JTBa7CRKz5?= =?us-ascii?Q?tF2BsKnPL69q/mOnHyuVirQIkua28hBji5VVGyv97xBSQla1F5QiwQtwXPme?= =?us-ascii?Q?BiCxoM3rD66n3rIPVLE0jhHiD9WdQkvstqwmk5tpb0Da/ZhShcBUfd259aHk?= =?us-ascii?Q?Q744ELeKd6OBBH+hZ5qfGUG2WNxRjfE6H39ek/KOjR1yrDXFmaGG7nVg15rT?= =?us-ascii?Q?6j6hXXz/b5aMrSyet79t69vfhqPLWeAL0D621pve2bG4iWKs2Hw0PTIeg7aL?= =?us-ascii?Q?BiR4/L51/NOMqVmFcp3J6CydHaBbdGtffYN5TYE6lDk+gTAV79FA2WJQyaph?= =?us-ascii?Q?VcWR4Fnm6PeJlFikzydi4zJY8AFmeym35Xl6Q/71v/YjwVx8zRTDSi6qfo8C?= =?us-ascii?Q?TeXCNtW30n2GMO7U3OnPYK+elrM6Bl5Qui2j7FK0DpkINobIJRi24S6uWMYT?= =?us-ascii?Q?TA+VMYj/UPHgLEdpCYBRBolDB9LiA/KQa3Sog033vDYnZP57h8B/kfVxhc/J?= =?us-ascii?Q?Bu3PzdA3fLsOTYZq1xt/R1WNisrLE0CxOQ7wiuItrUfHZrJ1you/DjunEd5N?= =?us-ascii?Q?D6VbFVh0BIw/r/OG0LGr3Lu6Vq0cZga/EhPfTKXNv7xLR3mZqTGEV/0ROp+p?= =?us-ascii?Q?TM4iPVnS2yvnF7MXoJHFgqkrVhXnxUhrBcB/gJRmAc5jnGMa3/hDNuGUsYpQ?= =?us-ascii?Q?Sk6cRZ3zZfZDVhKLGjh5zYM8zDPCRBGnnT2SKWeJIaL1MpplctV14vOK3Fv6?= =?us-ascii?Q?yHeMTAq8waSt31xLwzB9NN14EaCZSAdGnclvnAt4lVY9nYn+8K/mdw9tP2Zf?= =?us-ascii?Q?ji703oJYiM4vxnV8cORJMmDupRs81Q6J6qVWbOh/bREMNK1xomdJRfRdjmVL?= =?us-ascii?Q?Jk+lSJxv/sq2IlWTwmZE=3D?= X-Microsoft-Exchange-Diagnostics: 1; BLUPR0301MB1588; 5:xo3T/HeFl70KcGlvu2ZnRFASdemwPmwp08i5LAZhPuliuSrkNNG67LIVk+j3mDwZKJi7P9URy7UbtoS5EtSveYEvoU7s4l+0uwg2jGJ2PdjFbMMNPISXqtyCxetpjAXMuoLJcFGQGwsPik5cN7ywCOBgMMxByp8ZYr17yw5GqvE=; 24:czVI3RzBc/PjOH9Du3graewNrK42/kqhzx7yM6NTEt5iWgLpg+yh8sNfGdVuN4tkMoXa1Ss6WnG02bbU3Cx59syb/Fy2wmR+ZRpv8KoODY0=; 7:35fbSP3WX+9WfsEpHUyOIV59gCh3QpDJhgQNCMUDE4SyRYVB2QwgoA825kYoSbvWPDgBj/A4DQe33/4Ro/nanhfjnTgCZ8c6bQFK0Tc62PDerzw+bicepQiwVCaA+mnasj915hL4aM4rAVKr8o8oMDFsnS8LDNxSNU/ptjwRmjiPmdJ1HgwEULp1CAdhvy6j SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 31 May 2016 09:25:04.5566 (UTC) X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e; Ip=[192.88.158.2]; Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR0301MB1588 Cc: Russell King , Daniel Vetter 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-Virus-Scanned: ClamAV using ClamSMTP To support generic atomic page flip, this patch customizes ->atomic_commit for nonblock commits. Signed-off-by: Liu Ying --- v1->v2: * s/async/nonblock/ on this patch to address Daniel Vetter's comment. * Wait for pending commit on each CRTC for both block and nonblock atomic mode settings. This way, a block commit will not overwrite the hardware setting when a nonblock page flip is about to finish, so that the page flip may wait for vblank successfully. drivers/gpu/drm/imx/imx-drm-core.c | 135 +++++++++++++++++++++++++++++++- drivers/gpu/drm/imx/ipuv3-crtc.c | 156 ++----------------------------------- 2 files changed, 142 insertions(+), 149 deletions(-) diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 2a2ab8c..d2bb743 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -15,10 +15,14 @@ */ #include #include +#include #include #include #include +#include +#include #include +#include #include #include #include @@ -48,6 +52,14 @@ struct imx_drm_device { struct imx_drm_crtc { struct drm_crtc *crtc; struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs; + wait_queue_head_t commit_wait; + bool commit_pending; +}; + +struct imx_drm_commit { + struct work_struct work; + struct drm_device *dev; + struct drm_atomic_state *state; }; #if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) @@ -168,11 +180,130 @@ static void imx_drm_output_poll_changed(struct drm_device *drm) drm_fbdev_cma_hotplug_event(imxdrm->fbhelper); } +static void imx_drm_atomic_complete(struct imx_drm_commit *commit) +{ + struct drm_device *dev = commit->dev; + struct imx_drm_device *imxdrm = dev->dev_private; + struct imx_drm_crtc *imx_crtc; + struct drm_atomic_state *old_state = commit->state; + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; + struct drm_plane_state *plane_state; + struct drm_gem_cma_object *cma_obj; + struct fence *excl; + unsigned shared_count; + struct fence **shared; + unsigned int i, j; + int ret; + + /* Wait for fences. */ + for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { + if (crtc->state->event) { + plane_state = crtc->primary->state; + cma_obj = drm_fb_cma_get_gem_obj(plane_state->fb, 0); + if (cma_obj->base.dma_buf) { + ret = reservation_object_get_fences_rcu( + cma_obj->base.dma_buf->resv, &excl, + &shared_count, &shared); + if (unlikely(ret)) + DRM_ERROR("failed to get fences " + "for buffer\n"); + + if (excl) { + fence_wait(excl, false); + fence_put(excl); + } + for (j = 0; j < shared_count; i++) { + fence_wait(shared[j], false); + fence_put(shared[j]); + } + } + } + } + + /* Apply the atomic update. */ + drm_atomic_helper_commit_modeset_disables(dev, old_state); + drm_atomic_helper_commit_modeset_enables(dev, old_state); + drm_atomic_helper_commit_planes(dev, old_state, false); + drm_atomic_helper_wait_for_vblanks(dev, old_state); + drm_atomic_helper_cleanup_planes(dev, old_state); + + for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { + imx_crtc = imxdrm->crtc[i]; + + /* Complete the commit, wake up any waiter. */ + spin_lock(&imx_crtc->commit_wait.lock); + imx_crtc->commit_pending = false; + wake_up_all_locked(&imx_crtc->commit_wait); + spin_unlock(&imx_crtc->commit_wait.lock); + } + + drm_atomic_state_free(old_state); + + kfree(commit); +} + +static void imx_drm_atomic_work(struct work_struct *work) +{ + struct imx_drm_commit *commit = + container_of(work, struct imx_drm_commit, work); + + imx_drm_atomic_complete(commit); +} + +static int imx_drm_atomic_commit(struct drm_device *dev, + struct drm_atomic_state *state, bool nonblock) +{ + struct imx_drm_device *imxdrm = dev->dev_private; + struct imx_drm_crtc *imx_crtc; + struct imx_drm_commit *commit; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + unsigned int i; + int ret; + + commit = kzalloc(sizeof(*commit), GFP_KERNEL); + if (commit == NULL) + return -ENOMEM; + + commit->dev = dev; + commit->state = state; + + for_each_crtc_in_state(state, crtc, crtc_state, i) { + imx_crtc = imxdrm->crtc[i]; + + spin_lock(&imx_crtc->commit_wait.lock); + ret = wait_event_interruptible_locked( + imx_crtc->commit_wait, + !imx_crtc->commit_pending); + if (ret == 0) + imx_crtc->commit_pending = true; + spin_unlock(&imx_crtc->commit_wait.lock); + + if (ret) { + kfree(commit); + return ret; + } + } + + if (nonblock) + INIT_WORK(&commit->work, imx_drm_atomic_work); + + drm_atomic_helper_swap_state(dev, state); + + if (nonblock) + schedule_work(&commit->work); + else + imx_drm_atomic_complete(commit); + + return 0; +} + static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = { .fb_create = drm_fb_cma_create, .output_poll_changed = imx_drm_output_poll_changed, .atomic_check = drm_atomic_helper_check, - .atomic_commit = drm_atomic_helper_commit, + .atomic_commit = imx_drm_atomic_commit, }; /* @@ -307,6 +438,8 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs; imx_drm_crtc->crtc = crtc; + init_waitqueue_head(&imx_drm_crtc->commit_wait); + crtc->port = port; imxdrm->crtc[imxdrm->pipes++] = imx_drm_crtc; diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index f20340f..7ee51db 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -24,8 +24,6 @@ #include #include #include -#include -#include #include #include @@ -35,23 +33,6 @@ #define DRIVER_DESC "i.MX IPUv3 Graphics" -enum ipu_flip_status { - IPU_FLIP_NONE, - IPU_FLIP_PENDING, - IPU_FLIP_SUBMITTED, -}; - -struct ipu_flip_work { - struct work_struct unref_work; - struct drm_gem_object *bo; - struct drm_pending_vblank_event *page_flip_event; - struct work_struct fence_work; - struct ipu_crtc *crtc; - struct fence *excl; - unsigned shared_count; - struct fence **shared; -}; - struct ipu_crtc { struct device *dev; struct drm_crtc base; @@ -62,9 +43,6 @@ struct ipu_crtc { struct ipu_dc *dc; struct ipu_di *di; - enum ipu_flip_status flip_state; - struct workqueue_struct *flip_queue; - struct ipu_flip_work *flip_work; int irq; }; @@ -92,150 +70,35 @@ static void ipu_crtc_disable(struct drm_crtc *crtc) drm_crtc_vblank_off(&ipu_crtc->base); } -static void ipu_flip_unref_work_func(struct work_struct *__work) -{ - struct ipu_flip_work *work = - container_of(__work, struct ipu_flip_work, unref_work); - - drm_gem_object_unreference_unlocked(work->bo); - kfree(work); -} - -static void ipu_flip_fence_work_func(struct work_struct *__work) -{ - struct ipu_flip_work *work = - container_of(__work, struct ipu_flip_work, fence_work); - int i; - - /* wait for all fences attached to the FB obj to signal */ - if (work->excl) { - fence_wait(work->excl, false); - fence_put(work->excl); - } - for (i = 0; i < work->shared_count; i++) { - fence_wait(work->shared[i], false); - fence_put(work->shared[i]); - } - - work->crtc->flip_state = IPU_FLIP_SUBMITTED; -} - -static int ipu_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags) -{ - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - struct ipu_flip_work *flip_work; - int ret; - - if (ipu_crtc->flip_state != IPU_FLIP_NONE) - return -EBUSY; - - ret = imx_drm_crtc_vblank_get(ipu_crtc->imx_crtc); - if (ret) { - dev_dbg(ipu_crtc->dev, "failed to acquire vblank counter\n"); - list_del(&event->base.link); - - return ret; - } - - flip_work = kzalloc(sizeof *flip_work, GFP_KERNEL); - if (!flip_work) { - ret = -ENOMEM; - goto put_vblank; - } - INIT_WORK(&flip_work->unref_work, ipu_flip_unref_work_func); - flip_work->page_flip_event = event; - - /* get BO backing the old framebuffer and take a reference */ - flip_work->bo = &drm_fb_cma_get_gem_obj(crtc->primary->fb, 0)->base; - drm_gem_object_reference(flip_work->bo); - - ipu_crtc->flip_work = flip_work; - /* - * If the object has a DMABUF attached, we need to wait on its fences - * if there are any. - */ - if (cma_obj->base.dma_buf) { - INIT_WORK(&flip_work->fence_work, ipu_flip_fence_work_func); - flip_work->crtc = ipu_crtc; - - ret = reservation_object_get_fences_rcu( - cma_obj->base.dma_buf->resv, &flip_work->excl, - &flip_work->shared_count, &flip_work->shared); - - if (unlikely(ret)) { - DRM_ERROR("failed to get fences for buffer\n"); - goto free_flip_work; - } - - /* No need to queue the worker if the are no fences */ - if (!flip_work->excl && !flip_work->shared_count) { - ipu_crtc->flip_state = IPU_FLIP_SUBMITTED; - } else { - ipu_crtc->flip_state = IPU_FLIP_PENDING; - queue_work(ipu_crtc->flip_queue, - &flip_work->fence_work); - } - } else { - ipu_crtc->flip_state = IPU_FLIP_SUBMITTED; - } - - if (crtc->primary->state) - drm_atomic_set_fb_for_plane(crtc->primary->state, fb); - - return 0; - -free_flip_work: - drm_gem_object_unreference_unlocked(flip_work->bo); - kfree(flip_work); - ipu_crtc->flip_work = NULL; -put_vblank: - imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc); - - return ret; -} - static const struct drm_crtc_funcs ipu_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .destroy = drm_crtc_cleanup, - .page_flip = ipu_page_flip, + .page_flip = drm_atomic_helper_page_flip, .reset = drm_atomic_helper_crtc_reset, .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, }; -static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc) +static void ipu_crtc_handle_pageflip(struct drm_crtc *crtc) { + struct drm_device *drm = crtc->dev; unsigned long flags; - struct drm_device *drm = ipu_crtc->base.dev; - struct ipu_flip_work *work = ipu_crtc->flip_work; spin_lock_irqsave(&drm->event_lock, flags); - if (work->page_flip_event) - drm_crtc_send_vblank_event(&ipu_crtc->base, - work->page_flip_event); - imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; spin_unlock_irqrestore(&drm->event_lock, flags); } static irqreturn_t ipu_irq_handler(int irq, void *dev_id) { struct ipu_crtc *ipu_crtc = dev_id; + struct drm_crtc *crtc = &ipu_crtc->base; imx_drm_handle_vblank(ipu_crtc->imx_crtc); - if (ipu_crtc->flip_state == IPU_FLIP_SUBMITTED) { - struct ipu_plane *plane = ipu_crtc->plane[0]; - - ipu_plane_set_base(plane, ipu_crtc->base.primary->fb); - ipu_crtc_handle_pageflip(ipu_crtc); - queue_work(ipu_crtc->flip_queue, - &ipu_crtc->flip_work->unref_work); - ipu_crtc->flip_state = IPU_FLIP_NONE; - } + if (crtc->state->event) + ipu_crtc_handle_pageflip(crtc); return IRQ_HANDLED; } @@ -458,8 +321,6 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, /* Only enable IRQ when we actually need it to trigger work. */ disable_irq(ipu_crtc->irq); - ipu_crtc->flip_queue = create_singlethread_workqueue("ipu-crtc-flip"); - return 0; err_put_plane1_res: @@ -504,7 +365,6 @@ static void ipu_drm_unbind(struct device *dev, struct device *master, imx_drm_remove_crtc(ipu_crtc->imx_crtc); - destroy_workqueue(ipu_crtc->flip_queue); ipu_put_resources(ipu_crtc); if (ipu_crtc->plane[1]) ipu_plane_put_resources(ipu_crtc->plane[1]);