From patchwork Fri Jul 8 09:40:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ying Liu X-Patchwork-Id: 9220339 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 1287360572 for ; Fri, 8 Jul 2016 09:41:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 021EC28638 for ; Fri, 8 Jul 2016 09:41:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EA98B2863A; Fri, 8 Jul 2016 09:41:42 +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 1EB2E28638 for ; Fri, 8 Jul 2016 09:41:41 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7CFF36E188; Fri, 8 Jul 2016 09:41:37 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from NAM02-SN1-obe.outbound.protection.outlook.com (mail-sn1nam02on0078.outbound.protection.outlook.com [104.47.36.78]) by gabe.freedesktop.org (Postfix) with ESMTPS id 3984D6E188 for ; Fri, 8 Jul 2016 09:41:36 +0000 (UTC) Received: from DM2PR03CA0003.namprd03.prod.outlook.com (10.141.96.13) by BLUPR0301MB2018.namprd03.prod.outlook.com (10.164.22.20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.528.16; Fri, 8 Jul 2016 09:41:33 +0000 Received: from BL2FFO11FD006.protection.gbl (2a01:111:f400:7c09::105) by DM2PR03CA0003.outlook.office365.com (2a01:111:e400:2428::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.534.14 via Frontend Transport; Fri, 8 Jul 2016 09:41:33 +0000 Authentication-Results: spf=softfail (sender IP is 192.88.168.50) 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.168.50 as permitted sender) Received: from tx30smr01.am.freescale.net (192.88.168.50) by BL2FFO11FD006.mail.protection.outlook.com (10.173.161.2) with Microsoft SMTP Server (TLS) id 15.1.534.7 via Frontend Transport; Fri, 8 Jul 2016 09:41:33 +0000 Received: from victor.ap.freescale.net (victor.ap.freescale.net [10.192.241.62]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id u689fBMt003192; Fri, 8 Jul 2016 02:41:31 -0700 From: Liu Ying To: Subject: [PATCH v4 07/10] drm/imx: atomic phase 3 step 1: Use atomic configuration Date: Fri, 8 Jul 2016 17:40:59 +0800 Message-ID: <1467970862-28012-8-git-send-email-gnuiyl@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1467970862-28012-1-git-send-email-gnuiyl@gmail.com> References: <1467970862-28012-1-git-send-email-gnuiyl@gmail.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131124444935384492; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.168.50; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(7916002)(2980300002)(189002)(199003)(305945005)(87572001)(76482005)(50986999)(97736004)(6260500002)(110136002)(76176999)(50466002)(48376002)(8676002)(106466001)(81156014)(189998001)(77096005)(81166006)(586003)(81442002)(61266001)(50226002)(8936002)(33646002)(5003940100001)(47776003)(5890100001)(73392002)(68736007)(36756003)(11100500001)(229853001)(92566002)(87936001)(4326007)(86362001)(104016004)(356003)(2351001)(82202001)(55446002)(6806005)(2950100001)(105596002)(19580405001)(83322999)(19580395003)(7846002)(73972006)(2906002); DIR:OUT; SFP:1101; SCL:1; SRVR:BLUPR0301MB2018; H:tx30smr01.am.freescale.net; FPR:; SPF:SoftFail; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BL2FFO11FD006; 1:voFEr5zPj1+HmRqzr3YuwVjhKQlYo1btpLnUnCx5zxSgdQR/97oRB04UxIkPyFh769f/UZVJZUsKXojpuKZBEA0DzkAadVH2T0MUGQsWKas0b0jw8rVs1nT20U6JskLXLcLXn40wD/L9zb05UbMXyTIXW5T+AkS22Q0FJ/R7jlkQViSRliE0Is9SFGql7Z7DotjHhSz5UT6Krvqueq8Gyw5U44nEAXmlXo667n2YujHmOCjrexpVYk8J8TcezXPAHLeoIOwVqltGY7OUsxfUfVdfVJYcogb+g5QuyfjX8Vl0J09rqJV62nsmVjcwXvW0e8gJsqlAu+vmrxJoqTVExTjGTYY/pbRrWankdCET+BgwPL2gj6t1hGcTikTkC1LxvdMMBYr5tiun/5kjMoOjPRgwcva8A1v7ev/RPphZ2Rw0hgTTngIQ7wucS9iJ+CqJIKYb1yt09RHxi8AL/yyRV6AhCA/1e9xw1I80h7u8s/ogb0OPO2DMsbaRIeALLMfeqLloGdz2qObnDkkaaX/4sW96x0jCtcQ5L+KxRNT3/3CFu7zfbw5Jnynbp4C/QdLPXLoQOE/v3WfeQgilJlZKqQ== MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: f7e42a68-a216-4aa6-0c4b-08d3a7140c33 X-Microsoft-Exchange-Diagnostics: 1; BLUPR0301MB2018; 2:CUBpW8cuRayXjlnDWeJGRhUAFBiFYgx8GdY2eRkfou9o9Qoz38fXU5GtWGQGxC1hTmsx4L3o50F7re5B2sW5+RUsz8KZY+hupKXwpX3XKF+P39iQDuBbddbFh1zLRNwvzoyZpMBzkTbrAyPmPUECmj1QiXimiT6H0ggCKlyTVWEcRo8odTm+mURt1fcpizvW; 3:D4LhB7EsezI0DuRx2c9VP5PfJKlGkDzSaCJRothOwYe0LdlHewAHJL1jCWiNeqqZJTB4o5SIQELODy+3v7jUuH02oAC3fki2knUcsy5mmUdKbwqWB4cZ7EEvN596M0DlCzOUEg5NvNyl5fxpny5rOFnwoEqaFwhL0FhgNHTr4xlpBiw49tTdGcMz7erQJ1xRRxP6fl6g59rsJZSfcPyiINf3ztmnldV5TpWxMtEuYuk=; 25:JekelOHxCx5dyF6RMaLoyF6CuY1WKiEU7KwoLZehqbdRwT6ecBl9PPebG/6RN1YlkbIPJMQ6DFMXUaWesoge5Xd56WOfQ3MoeqGqJUTkJJihrVAKnKTshurPtM0o3s88l+jVnInPXEuLlAEl0QxPmpKUS83XRfhU0FOXkkyfZuSmJJkvQ2P9E225GmcBh2y/Rpl8J5W7KfRsEGBrFkgD7r9DKScCuwE6ExHm8nR5MKEN/nAFEsqQrYF/in3UGdEk0J4HWEIn44+5vnoCqPqcNmrcPxkCZ1IDeFqYOWYA8yd4Cv54sRFpn057DQGZiqJPYMfDklgvDcdLKt/qNsT8V67aWlR6tQO6w/Qk0ewBzKM0Xh97G3g5y01ZO7gAW0xef4GZbqceQtR/gGx7dXJWiADwFzHTqcxSBv02ck+ux8c= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BLUPR0301MB2018; X-Microsoft-Exchange-Diagnostics: 1; BLUPR0301MB2018; 31:4YFSti0zCvJZpq14PvFSgYZ96XDDoXhlg2SXdtqg8WjJ908vGPYsgnS9glUYdzIhuw/gkkfUNh1JJYkGE22VukgPEQSmPYYgPl9AAG0bsXHEE1VhyHk3AkibVoHEyDLWROaZitmPFVX3uYLLQOgiOTbTETRXC+SJujfE3zXbRBCvkPl1woURs3G8q01Ny2EaPc7vScBoFwdDV/N9ubQZmA==; 4:zkHtbtLxnqORDAQuSaMnMccc2hOTJvG2dQO70V45JHMcFBHI9ovdwr8wVgonVYiZDNkPKb4b3OFXn6wHDzIyZAwMyQQ5xw9jzC44dPOAfXvaxGCOMjsk7AxaMpNcY2nRuxmpRbXuieOXlQqLrMyitmqx3Tm9zvzvqvrk0WBG3OgrRm+urCHuPp4VqUXOhHSLWawEAsG9x7D+rgDPWb0qX9PPxs2uPGbK32rvavgEqZcwOJRgokNt+5zTc5EeSVPAfffeO50zKtYxj4A8QKtOXb+x77GcndcBPXjCZaY5okBIEvvXnY5L0+r+NqYlX/UFK6jaKL0lHEEO9czF9pJUj3Mqy3/Kd/LSXg9boP0T0gDi2wHjunw4jNtHH1Ox2CAGm4fSPlL0vOBB+afRScaQ/RKLKCYpX4qw4BASWXDu8dAeUvYHIVQWLWMHvOI5ceOlHtRRsLTmcDRFYuzc2CBXIH0zEYptqNXaziEuGwon/oE= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(13023025)(13018025)(13024025)(13015025)(13017025)(5005006)(8121501046)(10201501046)(3002001)(6055026); SRVR:BLUPR0301MB2018; BCL:0; PCL:0; RULEID:(400006); SRVR:BLUPR0301MB2018; X-Forefront-PRVS: 0997523C40 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BLUPR0301MB2018; 23:Y9vCO4S+/5FKpxZ5GDvDmCKydfajXLCePUKtsSd?= =?us-ascii?Q?ITEqCnYTKlEk/Dd5oT2gyFUm+7b5i+Csu+ECI2gChHRV4DVC01cDhdHIlqE+?= =?us-ascii?Q?agiOgRR8EOlsLuztMhFlJUTMkBE5/o0uK+ewsQkM+wwB3dxlSFxb2B39m4ds?= =?us-ascii?Q?2nTQeJALLC8XWmiapPrLtkqcupzxINdt4wD66Y8Rv5umuY7dSF3FRTDRlDVN?= =?us-ascii?Q?odjWoZb0tvT0KFeObxiwBxGBnmW1cswZ700x0WqgyZFp6QIEA8uITjBeJrol?= =?us-ascii?Q?RzSK8YOuGXMspuZhn8GvJpt3cMHUL/eQm88IMmKJRttg9XNhssBYsm8wtpax?= =?us-ascii?Q?cC99kVnKxipL7ch9AlKQ21IJLdkHeSIYQkGzjzoNyFXRaIVzSmx9Cp17C6GX?= =?us-ascii?Q?jEBm94RgbTijOMznfF5Yt+cGtLq0Oa8HiHDKfAh4uO+8fSb2hofSKcrv/xmC?= =?us-ascii?Q?gLNFYTuEt4B1Pl7g6X0VXLLWK4x7eM5cYL0uPPsdaYWFsgsLxH0d5JPqVNMh?= =?us-ascii?Q?PP6voeH8ROMfG0CfdimoVm0N9fIAvdepbRAbN/kiyFmKpxRNca2UqY/YyG9/?= =?us-ascii?Q?Po2Z809uh32zU1puLpCg9+kr+k/iRppje9AYWjzIz/lBpPxBqNvvDuREtH7M?= =?us-ascii?Q?w9oWnOnQ+WjXTREG+VBu9ltKkS99wb/5riVDmzBv4lpGVTHEbBcO1liV260I?= =?us-ascii?Q?30WqkWz3on5cMPs7wtNzk28GYQOQnxcNhdPOrb3JcPG6MHARRY8mjN4XPVBU?= =?us-ascii?Q?Egxm8qZPcZvHA9oqkQ67ASI5FsZGsqdJnvnkfOZmKfxPh6JD7Wzt9wEEgXK1?= =?us-ascii?Q?aLdVyOxLTcMqw+hqpUqTB3vUEwkpzlY8fmZ2JKsMfJrMhP4tf1lzoKBFjeIM?= =?us-ascii?Q?gPs2RSkOCw13y/zx2Vf79tqT+RGKCRIM4DWBTX6vZvWiNZUfwMrj6bfSxIKw?= =?us-ascii?Q?EoP9NZpRyAbdRPQMup5RM9I7MM5eXM8bOxYpX0ijMmOPTqcodyLf+Q2xBUew?= =?us-ascii?Q?4rTajbHPEoPEwfDHnbK0w+dB5M6qjJBEphuzt++LGxbH9iTpf0zpNJN06RhP?= =?us-ascii?Q?iZSWZrPl9viYaUxKJyRWc4uQ5kCujPho/qXTgpOJknnKGdXXr0a9T+UC0VEI?= =?us-ascii?Q?IBzrbt2Y9qUCIkRAZmp9dfPvogECAdVAgOjso0JhGsHSiimSa6vy14Pkq49E?= =?us-ascii?Q?hgvvZ0ql6vPzaeZLCZxE0ysyQcI2uNsJ8v3zb3mcfBS2YQJWdAcCJn1roRCe?= =?us-ascii?Q?99NXsFQNKweTk9wwiOtNZPDJ16OnxsfpZksA+FQHg?= X-Microsoft-Exchange-Diagnostics: 1; BLUPR0301MB2018; 6:LSR9Ex2UdPXsSBb7+2p3Oncq6h/6yC/PDBG4pk47kH8CVzCHKgbIJfFvvGck2UAMKdwVqyFxPxT4Kky1L5i5sNuogEqR6PhlXalwrrL6/WqVxuthc/wIZbfeWm8hrQApODh29hIn1ZHF/p2aVDMoLprJqsww/ubIj/Bq5kkeDrus4ipprNosHsizKwjMxRvRbx/5swffQ3KXIslSDcZEGYpwAPNazAGXrgNqblPlcb2SHclBKdukoaCD4HRLNW3P00ZR8iye7nihPd1bhKqIhkEV7JRycfT39CQpO3f4+qQ=; 5:+VhFGfosKTxkpYTi+NOVWZYFb4ATO/ajyfzQqcEn9RdVNChFvsZ8iHQuFlbuBKIHUnWHaKxOWOgF/605V7U3TZJiLVSFfN9OaGSTlZPhxl2WFjvWU+oq26gg9hX40bdWbkpWXyvGS1ugR57ZWceMxqkfsm0I46IWI5E+JsdXEQk=; 24:dyWA+TFzVPO/IykwKha/JtNkEj+kWuK6+knS2EDSTCsh2bh2TtF+4xE7EwzfucxSQAp63sjfv9xbJptMiw+v0mdaCLJGDcI21otij8D303c=; 7:GxJg7feY9EEGIImtB2Hpt/5PF2j3zeCoN5m6t7Nd0xfgDZ/JTdXZfYrxnzF0yiV5ge49qZcJDJ9irKRyo5/hQUCApIFe9k4j95qZCVd6oVADhJy3ndRVUaYhZPR7B4QwxlhQhOprZWDG+GHFkqkWyNW1iC7VV6Ls/q/KSwt+KcdgJQ8zNCRw1cjgydVfKWt7ojICvT9wAhy8HYOvW1QwKs37+R1PzK8z/a+gZtwUjjGP8hojUe+AifhWJFwJ31iB SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 08 Jul 2016 09:41:33.3668 (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.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR0301MB2018 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 Replacing drm_crtc_helper_set_config() by drm_atomic_helper_set_config() and converting the suspend/resume operations to atomic make us be able to use atomic configurations. All of these allow us to remove the crtc_funcs->mode_set callback as it is no longer used. Also, change the plane_funcs->update/disable_plane callbacks from the transitional version to the atomic version. Furthermore, switching to the pure atomic version of set_config callback means that we may implement CRTC/plane atomic checks by using the new CRTC/plane states instead of the legacy ones and we may remove the private ipu_crtc->enabled state which was left there for the transitional atomic helpers in phase 1. Page flip is also switched to the atomic version. Last, the legacy function drm_helper_disable_unused_functions() is removed from ->load in order not to confuse the atomic driver. Signed-off-by: Liu Ying --- v3->v4: * None. v2->v3: * Newly introduced, but this contains some important logic in patch 06/10 , 07/10 and 09/10 of v2 to support nonblock atomic commit(including page flip) - the ->set_config and ->update_plane/disable_plane hooks are updated to be pure atomic version, and ->atomic_check/atomic_commit hooks of drm_mode_config_funcs are wired up. drivers/gpu/drm/imx/imx-drm-core.c | 76 +++++++++++++- drivers/gpu/drm/imx/ipuv3-crtc.c | 209 +++++-------------------------------- drivers/gpu/drm/imx/ipuv3-plane.c | 135 +++--------------------- drivers/gpu/drm/imx/ipuv3-plane.h | 2 - 4 files changed, 114 insertions(+), 308 deletions(-) diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index f6e44c2..f14ad2b 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 @@ -41,6 +45,7 @@ struct imx_drm_device { struct imx_drm_crtc *crtc[MAX_CRTC]; unsigned int pipes; struct drm_fbdev_cma *fbhelper; + struct drm_atomic_state *state; }; struct imx_drm_crtc { @@ -169,6 +174,63 @@ static void imx_drm_output_poll_changed(struct drm_device *drm) 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, +}; + +static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state) +{ + struct drm_device *dev = state->dev; + struct drm_crtc *crtc; + struct drm_crtc_state *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(state, crtc, crtc_state, i) { + plane_state = crtc->primary->state; + if (plane_state->fb) { + 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]); + } + } + } + } + + drm_atomic_helper_commit_modeset_disables(dev, state); + + drm_atomic_helper_commit_planes(dev, state, true); + + drm_atomic_helper_commit_modeset_enables(dev, state); + + drm_atomic_helper_commit_hw_done(state); + + drm_atomic_helper_wait_for_vblanks(dev, state); + + drm_atomic_helper_cleanup_planes(dev, state); +} + +static struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = { + .atomic_commit_tail = imx_drm_atomic_commit_tail, }; /* @@ -210,6 +272,7 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) drm->mode_config.max_width = 4096; drm->mode_config.max_height = 4096; drm->mode_config.funcs = &imx_drm_mode_config_funcs; + drm->mode_config.helper_private = &imx_drm_mode_config_helpers; drm_mode_config_init(drm); @@ -252,7 +315,6 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) dev_warn(drm->dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n"); legacyfb_depth = 16; } - drm_helper_disable_unused_functions(drm); imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth, drm->mode_config.num_crtc, MAX_CRTC); if (IS_ERR(imxdrm->fbhelper)) { @@ -454,6 +516,7 @@ static int imx_drm_platform_remove(struct platform_device *pdev) static int imx_drm_suspend(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); + struct imx_drm_device *imxdrm; /* The drm_dev is NULL before .load hook is called */ if (drm_dev == NULL) @@ -461,17 +524,26 @@ static int imx_drm_suspend(struct device *dev) drm_kms_helper_poll_disable(drm_dev); + imxdrm = drm_dev->dev_private; + imxdrm->state = drm_atomic_helper_suspend(drm_dev); + if (IS_ERR(imxdrm->state)) { + drm_kms_helper_poll_enable(drm_dev); + return PTR_ERR(imxdrm->state); + } + return 0; } static int imx_drm_resume(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); + struct imx_drm_device *imx_drm; if (drm_dev == NULL) return 0; - drm_helper_resume_force_mode(drm_dev); + imx_drm = drm_dev->dev_private; + drm_atomic_helper_resume(drm_dev, imx_drm->state); drm_kms_helper_poll_enable(drm_dev); return 0; diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index f9d5d7c..3e82534 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,10 +43,6 @@ struct ipu_crtc { struct ipu_dc *dc; struct ipu_di *di; - int enabled; - enum ipu_flip_status flip_state; - struct workqueue_struct *flip_queue; - struct ipu_flip_work *flip_work; int irq; }; @@ -75,34 +52,26 @@ static void ipu_crtc_enable(struct ipu_crtc *ipu_crtc) { struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); - if (ipu_crtc->enabled) - return; - ipu_dc_enable(ipu); ipu_dc_enable_channel(ipu_crtc->dc); ipu_di_enable(ipu_crtc->di); - ipu_crtc->enabled = 1; - - /* - * In order not to be warned on enabling vblank failure, - * we should call drm_crtc_vblank_on() after ->enabled is set to 1. - */ - drm_crtc_vblank_on(&ipu_crtc->base); } static void ipu_crtc_disable(struct ipu_crtc *ipu_crtc) { struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); - - if (!ipu_crtc->enabled) - return; + struct drm_crtc *crtc = &ipu_crtc->base; ipu_dc_disable_channel(ipu_crtc->dc); ipu_di_disable(ipu_crtc->di); ipu_dc_disable(ipu); - ipu_crtc->enabled = 0; - drm_crtc_vblank_off(&ipu_crtc->base); + spin_lock_irq(&crtc->dev->event_lock); + if (crtc->state->event) { + drm_crtc_send_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; + } + spin_unlock_irq(&crtc->dev->event_lock); } static void ipu_crtc_dpms(struct drm_crtc *crtc, int mode) @@ -123,151 +92,21 @@ static void ipu_crtc_dpms(struct drm_crtc *crtc, int mode) } } -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_crtc_helper_set_config, + .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) -{ - 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); - 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; 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; - } - return IRQ_HANDLED; } @@ -310,9 +149,26 @@ static void ipu_crtc_commit(struct drm_crtc *crtc) static int ipu_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { + u32 primary_plane_mask = 1 << drm_plane_index(crtc->primary); + + if (state->active && (primary_plane_mask & state->plane_mask) == 0) + return -EINVAL; + return 0; } +static void ipu_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) +{ + spin_lock_irq(&crtc->dev->event_lock); + if (crtc->state->event) { + WARN_ON(drm_crtc_vblank_get(crtc)); + drm_crtc_arm_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; + } + spin_unlock_irq(&crtc->dev->event_lock); +} + static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -371,25 +227,17 @@ static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc) static const struct drm_crtc_helper_funcs ipu_helper_funcs = { .dpms = ipu_crtc_dpms, .mode_fixup = ipu_crtc_mode_fixup, - .mode_set = drm_helper_crtc_mode_set, .mode_set_nofb = ipu_crtc_mode_set_nofb, .prepare = ipu_crtc_prepare, .commit = ipu_crtc_commit, .atomic_check = ipu_crtc_atomic_check, + .atomic_begin = ipu_crtc_atomic_begin, }; static int ipu_enable_vblank(struct drm_crtc *crtc) { struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - /* - * ->commit is done after ->mode_set in drm_crtc_helper_set_mode(), - * so waiting for vblank in drm_plane_helper_commit() will timeout. - * Check the state here to avoid the waiting. - */ - if (!ipu_crtc->enabled) - return -EINVAL; - enable_irq(ipu_crtc->irq); return 0; @@ -508,8 +356,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: @@ -554,7 +400,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]); diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index afbc740..3f5f956 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -55,122 +56,6 @@ int ipu_plane_irq(struct ipu_plane *ipu_plane) IPU_IRQ_EOF); } -int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb) -{ - struct drm_gem_cma_object *cma_obj[3], *old_cma_obj[3]; - struct drm_plane_state *state = ipu_plane->base.state; - struct drm_framebuffer *old_fb = state->fb; - unsigned long eba, ubo, vbo, old_eba, old_ubo, old_vbo; - int active, i; - int x = state->src_x >> 16; - int y = state->src_y >> 16; - - for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { - cma_obj[i] = drm_fb_cma_get_gem_obj(fb, i); - if (!cma_obj[i]) { - DRM_DEBUG_KMS("plane %d entry is null.\n", i); - return -EFAULT; - } - } - - for (i = 0; i < drm_format_num_planes(old_fb->pixel_format); i++) { - old_cma_obj[i] = drm_fb_cma_get_gem_obj(old_fb, i); - if (!old_cma_obj[i]) { - DRM_DEBUG_KMS("plane %d entry is null.\n", i); - return -EFAULT; - } - } - - eba = cma_obj[0]->paddr + fb->offsets[0] + - fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x; - - if (eba & 0x7) { - DRM_DEBUG_KMS("base address must be a multiple of 8.\n"); - return -EINVAL; - } - - if (fb->pitches[0] < 1 || fb->pitches[0] > 16384) { - DRM_DEBUG_KMS("pitches out of range.\n"); - return -EINVAL; - } - - if (fb->pitches[0] != old_fb->pitches[0]) { - DRM_DEBUG_KMS("pitches must not change while plane is enabled.\n"); - return -EINVAL; - } - - switch (fb->pixel_format) { - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - /* - * Multiplanar formats have to meet the following restrictions: - * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO - * - EBA, UBO and VBO are a multiple of 8 - * - UBO and VBO are unsigned and not larger than 0xfffff8 - * - Only EBA may be changed while scanout is active - * - The strides of U and V planes must be identical. - */ - ubo = cma_obj[1]->paddr + fb->offsets[1] + - fb->pitches[1] * y / 2 + x / 2 - eba; - vbo = cma_obj[2]->paddr + fb->offsets[2] + - fb->pitches[2] * y / 2 + x / 2 - eba; - - old_eba = old_cma_obj[0]->paddr + old_fb->offsets[0] + - old_fb->pitches[0] * y + - (old_fb->bits_per_pixel >> 3) * x; - old_ubo = old_cma_obj[1]->paddr + old_fb->offsets[1] + - old_fb->pitches[1] * y / 2 + x / 2 - old_eba; - old_vbo = old_cma_obj[2]->paddr + old_fb->offsets[2] + - old_fb->pitches[2] * y / 2 + x / 2 - old_eba; - - if ((ubo & 0x7) || (vbo & 0x7)) { - DRM_DEBUG_KMS("U/V buffer offsets must be a multiple of 8.\n"); - return -EINVAL; - } - - if ((ubo > 0xfffff8) || (vbo > 0xfffff8)) { - DRM_DEBUG_KMS("U/V buffer offsets must be positive and not larger than 0xfffff8.\n"); - return -EINVAL; - } - - if (old_ubo != ubo || old_vbo != vbo) { - DRM_DEBUG_KMS("U/V buffer offsets must not change while plane is enabled.\n"); - return -EINVAL; - } - - if (fb->pitches[1] != fb->pitches[2]) { - DRM_DEBUG_KMS("U/V pitches must be identical.\n"); - return -EINVAL; - } - - if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) { - DRM_DEBUG_KMS("U/V pitches out of range.\n"); - return -EINVAL; - } - - if (old_fb->pitches[1] != fb->pitches[1]) { - DRM_DEBUG_KMS("U/V pitches must not change while plane is enabled.\n"); - return -EINVAL; - } - - dev_dbg(ipu_plane->base.dev->dev, - "phys = %pad %pad %pad, x = %d, y = %d", - &cma_obj[0]->paddr, &cma_obj[1]->paddr, - &cma_obj[2]->paddr, x, y); - break; - default: - dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d", - &cma_obj[0]->paddr, x, y); - break; - } - - active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); - ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); - ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); - - return 0; -} - static inline unsigned long drm_plane_state_to_eba(struct drm_plane_state *state) { @@ -360,8 +245,8 @@ static void ipu_plane_destroy(struct drm_plane *plane) } static const struct drm_plane_funcs ipu_plane_funcs = { - .update_plane = drm_plane_helper_update, - .disable_plane = drm_plane_helper_disable, + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, .destroy = ipu_plane_destroy, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, @@ -380,10 +265,18 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, /* Ok to disable */ if (!fb) - return old_fb ? 0 : -EINVAL; + return 0; + + if (!state->crtc) + return -EINVAL; + + crtc_state = + drm_atomic_get_existing_crtc_state(state->state, state->crtc); + if (WARN_ON(!crtc_state)) + return -EINVAL; /* CRTC should be enabled */ - if (!state->crtc->enabled) + if (!crtc_state->enable) return -EINVAL; /* no scaling */ @@ -391,8 +284,6 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, state->src_h >> 16 != state->crtc_h) return -EINVAL; - crtc_state = state->crtc->state; - switch (plane->type) { case DRM_PLANE_TYPE_PRIMARY: /* full plane doesn't support partial off screen */ diff --git a/drivers/gpu/drm/imx/ipuv3-plane.h b/drivers/gpu/drm/imx/ipuv3-plane.h index c51a44b..338b88a 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.h +++ b/drivers/gpu/drm/imx/ipuv3-plane.h @@ -37,8 +37,6 @@ int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, bool interlaced); -int ipu_plane_set_base(struct ipu_plane *plane, struct drm_framebuffer *fb); - int ipu_plane_get_resources(struct ipu_plane *plane); void ipu_plane_put_resources(struct ipu_plane *plane);