From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7CB60C98302 for ; Wed, 23 Sep 2026 07:12:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: Content-Type:In-Reply-To:From:References:Cc:To:Subject:MIME-Version:Date: Message-ID:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=efMVPgm6+0XSeW0sitHcd4Xplq9NHsjfGrf1OMkuzVQ=; b=0/oeTYCCVFudume8qvoxyc2L1O e1ETawxn7DA88oadsOm6RWsaYvc+hSdgRRJJznaSwbM6ohTXAruZbecSM6wIvxB7qZkIqO7z91wsg PSWrkfQ/Y2Jq6lorZB18cR/P9iY81OXdc8gdreXMUmcOHDhB3iMxbkVHR4plF0ZKnQPxb5efUbrUj XZ7760DWYFZHU9v4G0X1E5xM3qNc4iF3pD9MajACzf8v2C3EkdgyKfH0D6A/Y5jrBBmbG5PeOqor3 NGPau58WEbmoIu3FC3F6LneTtdIBGOXbuNcIje9oaCBnpiKWBAtAHeQawSh0m5dJw3ySH+bugZ55u ZlyOSMpw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1x9H9m-00000007Mq0-2V8B; Wed, 23 Sep 2026 07:12:42 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1x9H9g-00000007Mm6-1PJa for linux-arm-kernel@bombadil.infradead.org; Wed, 23 Sep 2026 07:12:36 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Transfer-Encoding:Content-Type :In-Reply-To:From:References:Cc:To:Subject:MIME-Version:Date:Message-ID: Sender:Reply-To:Content-ID:Content-Description; bh=efMVPgm6+0XSeW0sitHcd4Xplq9NHsjfGrf1OMkuzVQ=; b=fgLs9plNHpiykXvU4DB2RIoqui O30sLNIX6PBptTdd9Niu8FVzG9BPva0qDqmEOvxGBZZnaAe3Y+f0R3eRdwzUeBHdpGWa8w0r6VBlS QhyR3JJh7hDHM9SXNE4ZBZoidgbVb6NyFoWf/XmLliILqY/yXNEOH5WWLYIU7VifQ4Y4mnHoi4oj2 ZEvkmw8iSKx3s+7qOwX7M+1rJoulH8PmPUbyFVh077FvLRzjIvAYJ5DydGQKVYFOIYzbYLZ/uH1oj l3yHUoH3EQ6EQlb6bCehrfLVpzJNx7T4/2tDHJMuky2QwNn+kCytw8Zt/CZlnfzhvr55g0IMTVYTw c1HYPDtg==; Received: from smtp-out2.suse.de ([2a07:de40:b251:101:10:150:64:2]) by desiato.infradead.org with esmtps (Exim 4.99.2 #2 (Red Hat Linux)) id 1x9H9N-0000000ESNn-2WV8 for linux-arm-kernel@lists.infradead.org; Wed, 23 Sep 2026 07:12:24 +0000 Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 292041FFA4; Wed, 23 Sep 2026 07:12:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1790147528; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:autocrypt:autocrypt; bh=efMVPgm6+0XSeW0sitHcd4Xplq9NHsjfGrf1OMkuzVQ=; b=zvW+mF4esVnryVOvXFNcX1b2hOy4+/k+kyyWkOh/9sTbvFzqKvRxlDrMLzsuk4Dy9HDqIC FPLBrb9Dz1npiwBHiLnaQXkkBDq3hvlD63QbC3MtZAOGVQodIBlrK2Kg9gVp8zl9fk4DZa gLTkzqd7BkoC585fLCEArg7zTBfyiRw= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1790147528; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:autocrypt:autocrypt; bh=efMVPgm6+0XSeW0sitHcd4Xplq9NHsjfGrf1OMkuzVQ=; b=X3nGbstk4Bu3KlYVSrN92Ig725rmcYPGPRBM6cua+4bSdiFzuVhLQ2wonMJYd5mzpbj32d 9bg78+mICo+v+7BQ== Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1790147524; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:autocrypt:autocrypt; bh=efMVPgm6+0XSeW0sitHcd4Xplq9NHsjfGrf1OMkuzVQ=; b=AcCwPvTvcD5Xn4YcJgn3+3+e/HOcK3nEXYO/V0hYF+oJXOIRFPzld/8cZwxUMvjdUiAtjb 9KB5ZYhDH3WjgNMwrRc0h8ew5R+tKMu3IMutizDfREOCwcjpnP3SVDZca9mlLOltaKnX4u ga8eXDjLZwrXRvdoJ3qZy9JXIuU4QCQ= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1790147524; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:autocrypt:autocrypt; bh=efMVPgm6+0XSeW0sitHcd4Xplq9NHsjfGrf1OMkuzVQ=; b=6mvWZqFohn2mlq/x75DedDq6f5HxZm/PZ+VJG3nZH6fg3kCWxT+eH8UUXxZbX7lOm7iFT2 jer++8/HP2x1uhBA== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 920CD13432; Wed, 23 Sep 2026 07:12:03 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id Hyj6EsN7s2pwUgAAD6G6ig (envelope-from ); Wed, 23 Sep 2026 07:12:03 +0000 Message-ID: Date: Wed, 23 Sep 2026 09:12:02 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v4 2/2] drm/imx: replace struct drm_simple_display_pipe with regular atomic helpers To: Ze Huang , Maarten Lankhorst , Maxime Ripard , David Airlie , Simona Vetter , Frank Li , Sascha Hauer , Pengutronix Kernel Team , Fabio Estevam , Philipp Zabel , =?UTF-8?Q?Uwe_Kleine-K=C3=B6nig?= , Marian Cichy Cc: dri-devel@lists.freedesktop.org, imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org References: <20260919-b4-imx-simple-kms-v4-v4-0-53b1fdf4589e@oss.qualcomm.com> <20260919-b4-imx-simple-kms-v4-v4-2-53b1fdf4589e@oss.qualcomm.com> Content-Language: en-US From: Thomas Zimmermann Autocrypt: addr=tzimmermann@suse.de; keydata= xsBNBFs50uABCADEHPidWt974CaxBVbrIBwqcq/WURinJ3+2WlIrKWspiP83vfZKaXhFYsdg XH47fDVbPPj+d6tQrw5lPQCyqjwrCPYnq3WlIBnGPJ4/jreTL6V+qfKRDlGLWFjZcsrPJGE0 BeB5BbqP5erN1qylK9i3gPoQjXGhpBpQYwRrEyQyjuvk+Ev0K1Jc5tVDeJAuau3TGNgah4Yc hdHm3bkPjz9EErV85RwvImQ1dptvx6s7xzwXTgGAsaYZsL8WCwDaTuqFa1d1jjlaxg6+tZsB 9GluwvIhSezPgnEmimZDkGnZRRSFiGP8yjqTjjWuf0bSj5rUnTGiyLyRZRNGcXmu6hjlABEB AAHNJ1Rob21hcyBaaW1tZXJtYW5uIDx0emltbWVybWFubkBzdXNlLmRlPsLAjgQTAQgAOAIb AwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYhBHIX+6yM6c9jRKFo5WgNwR1TC3ojBQJftODH AAoJEGgNwR1TC3ojx1wH/0hKGWugiqDgLNXLRD/4TfHBEKmxIrmfu9Z5t7vwUKfwhFL6hqvo lXPJJKQpQ2z8+X2vZm/slsLn7J1yjrOsoJhKABDi+3QWWSGkaGwRJAdPVVyJMfJRNNNIKwVb U6B1BkX2XDKDGffF4TxlOpSQzdtNI/9gleOoUA8+jy8knnDYzjBNOZqLG2FuTdicBXblz0Mf vg41gd9kCwYXDnD91rJU8tzylXv03E75NCaTxTM+FBXPmsAVYQ4GYhhgFt8S2UWMoaaABLDe 7l5FdnLdDEcbmd8uLU2CaG4W2cLrUaI4jz2XbkcPQkqTQ3EB67hYkjiEE6Zy3ggOitiQGcqp j//OwE0EWznS4AEIAMYmP4M/V+T5RY5at/g7rUdNsLhWv1APYrh9RQefODYHrNRHUE9eosYb T6XMryR9hT8XlGOYRwKWwiQBoWSDiTMo/Xi29jUnn4BXfI2px2DTXwc22LKtLAgTRjP+qbU6 3Y0xnQN29UGDbYgyyK51DW3H0If2a3JNsheAAK+Xc9baj0LGIc8T9uiEWHBnCH+RdhgATnWW GKdDegUR5BkDfDg5O/FISymJBHx2Dyoklv5g4BzkgqTqwmaYzsl8UxZKvbaxq0zbehDda8lv hFXodNFMAgTLJlLuDYOGLK2AwbrS3Sp0AEbkpdJBb44qVlGm5bApZouHeJ/+n+7r12+lqdsA EQEAAcLAdgQYAQgAIAIbDBYhBHIX+6yM6c9jRKFo5WgNwR1TC3ojBQJftOH6AAoJEGgNwR1T C3ojVSkIALpAPkIJPQoURPb1VWjh34l0HlglmYHvZszJWTXYwavHR8+k6Baa6H7ufXNQtThR yIxJrQLW6rV5lm7TjhffEhxVCn37+cg0zZ3j7zIsSS0rx/aMwi6VhFJA5hfn3T0TtrijKP4A SAQO9xD1Zk9/61JWk8OysuIh7MXkl0fxbRKWE93XeQBhIJHQfnc+YBLprdnxR446Sh8Wn/2D Ya8cavuWf2zrB6cZurs048xe0UbSW5AOSo4V9M0jzYI4nZqTmPxYyXbm30Kvmz0rYVRaitYJ 4kyYYMhuULvrJDMjZRvaNe52tkKAvMevcGdt38H4KSVXAylqyQOW5zvPc4/sq9c= In-Reply-To: <20260919-b4-imx-simple-kms-v4-v4-2-53b1fdf4589e@oss.qualcomm.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Spamd-Result: default: False [-4.30 / 50.00]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; NEURAL_HAM_SHORT(-0.20)[-0.999]; MIME_GOOD(-0.10)[text/plain]; RCVD_VIA_SMTP_AUTH(0.00)[]; ARC_NA(0.00)[]; MIME_TRACE(0.00)[0:+]; FREEMAIL_TO(0.00)[oss.qualcomm.com,linux.intel.com,kernel.org,gmail.com,ffwll.ch,nxp.com,pengutronix.de]; RCPT_COUNT_TWELVE(0.00)[16]; MID_RHS_MATCH_FROM(0.00)[]; FREEMAIL_ENVRCPT(0.00)[gmail.com]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; RCVD_TLS_ALL(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; DBL_BLOCKED_OPENRESOLVER(0.00)[qualcomm.com:email,imap1.dmz-prg2.suse.org:helo,suse.de:mid,suse.de:email,suse.com:url] X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260923_081222_487848_3F31BF64 X-CRM114-Status: GOOD ( 22.25 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Hi Am 19.09.26 um 16:59 schrieb Ze Huang: > Convert i.MX LCDC to explicit primary plane, CRTC and encoder objects. > Keep no-scaling plane check and GEM framebuffer prepare callback from > simple-KMS path. > > Wire the vblank lifecycle explicitly with CRTC vblank callbacks and > drm_crtc_vblank_on()/drm_crtc_vblank_off(). Use the old CRTC state in > the disable path for clock unwinding so the clock reference count > remains paired with the previous active state. > > Use the atomic_create_state helpers with > drm_mode_config_create_initial_state() in probe, and > drm_crtc_vblank_atomic_flush() for the flush callback. > > Signed-off-by: Ze Huang IDK how well (or if) this driver is still maintained. I'd give it the benefit of the doubt to make progress with the DRM cleanup. If there's a bug in this patch, users will report it quickly. Reviewed-by: Thomas Zimmermann Best regards Thomas > --- > drivers/gpu/drm/imx/lcdc/imx-lcdc.c | 250 +++++++++++++++++++++++++----------- > 1 file changed, 175 insertions(+), 75 deletions(-) > > diff --git a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c > index e00e52c1c46e..8f0a0d4cf61a 100644 > --- a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c > +++ b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c > @@ -2,6 +2,7 @@ > // SPDX-FileCopyrightText: 2020 Marian Cichy > > #include > +#include > #include > #include > #include > @@ -14,10 +15,11 @@ > #include > #include > #include > +#include > #include > #include > -#include > #include > +#include > #include > #include > #include > @@ -101,7 +103,9 @@ > > struct imx_lcdc { > struct drm_device drm; > - struct drm_simple_display_pipe pipe; > + struct drm_plane plane; > + struct drm_crtc crtc; > + struct drm_encoder encoder; > struct drm_connector *connector; > void __iomem *base; > > @@ -134,14 +138,15 @@ static unsigned int imx_lcdc_get_format(unsigned int drm_format) > } > } > > -static void imx_lcdc_update_hw_registers(struct drm_simple_display_pipe *pipe, > - struct drm_plane_state *old_state, > +static void imx_lcdc_update_hw_registers(struct drm_crtc *crtc, > + struct drm_crtc_state *old_crtc_state, > + struct drm_crtc_state *new_crtc_state, > + struct drm_plane_state *new_state, > bool mode_set) > { > - struct drm_crtc *crtc = &pipe->crtc; > - struct drm_plane_state *new_state = pipe->plane.state; > + struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(crtc->dev); > + const struct drm_display_mode *mode = &new_crtc_state->mode; > struct drm_framebuffer *fb = new_state->fb; > - struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(pipe->crtc.dev); > u32 lpcr, lvcr, lhcr; > u32 framesize; > dma_addr_t addr; > @@ -154,24 +159,24 @@ static void imx_lcdc_update_hw_registers(struct drm_simple_display_pipe *pipe, > return; > > /* Disable PER clock to make register write possible */ > - if (old_state && old_state->crtc && old_state->crtc->enabled) > + if (old_crtc_state && old_crtc_state->enable) > clk_disable_unprepare(lcdc->clk_per); > > /* Framesize */ > - framesize = FIELD_PREP(IMX21LCDC_LSR_XMAX, crtc->mode.hdisplay >> 4) | > - FIELD_PREP(IMX21LCDC_LSR_YMAX, crtc->mode.vdisplay); > + framesize = FIELD_PREP(IMX21LCDC_LSR_XMAX, mode->hdisplay >> 4) | > + FIELD_PREP(IMX21LCDC_LSR_YMAX, mode->vdisplay); > writel(framesize, lcdc->base + IMX21LCDC_LSR); > > /* HSYNC */ > - lhcr = FIELD_PREP(IMX21LCDC_LHCR_HFPORCH, crtc->mode.hsync_start - crtc->mode.hdisplay - 1) | > - FIELD_PREP(IMX21LCDC_LHCR_HWIDTH, crtc->mode.hsync_end - crtc->mode.hsync_start - 1) | > - FIELD_PREP(IMX21LCDC_LHCR_HBPORCH, crtc->mode.htotal - crtc->mode.hsync_end - 3); > + lhcr = FIELD_PREP(IMX21LCDC_LHCR_HFPORCH, mode->hsync_start - mode->hdisplay - 1) | > + FIELD_PREP(IMX21LCDC_LHCR_HWIDTH, mode->hsync_end - mode->hsync_start - 1) | > + FIELD_PREP(IMX21LCDC_LHCR_HBPORCH, mode->htotal - mode->hsync_end - 3); > writel(lhcr, lcdc->base + IMX21LCDC_LHCR); > > /* VSYNC */ > - lvcr = FIELD_PREP(IMX21LCDC_LVCR_VFPORCH, crtc->mode.vsync_start - crtc->mode.vdisplay) | > - FIELD_PREP(IMX21LCDC_LVCR_VWIDTH, crtc->mode.vsync_end - crtc->mode.vsync_start) | > - FIELD_PREP(IMX21LCDC_LVCR_VBPORCH, crtc->mode.vtotal - crtc->mode.vsync_end); > + lvcr = FIELD_PREP(IMX21LCDC_LVCR_VFPORCH, mode->vsync_start - mode->vdisplay) | > + FIELD_PREP(IMX21LCDC_LVCR_VWIDTH, mode->vsync_end - mode->vsync_start) | > + FIELD_PREP(IMX21LCDC_LVCR_VBPORCH, mode->vtotal - mode->vsync_end); > writel(lvcr, lcdc->base + IMX21LCDC_LVCR); > > lpcr = readl(lcdc->base + IMX21LCDC_LPCR); > @@ -183,19 +188,20 @@ static void imx_lcdc_update_hw_registers(struct drm_simple_display_pipe *pipe, > writel(new_state->fb->pitches[0] / 4, lcdc->base + IMX21LCDC_LVPWR); > > /* Enable PER clock */ > - if (new_state->crtc->enabled) > + if (new_crtc_state->enable) > clk_prepare_enable(lcdc->clk_per); > } > > -static void imx_lcdc_pipe_enable(struct drm_simple_display_pipe *pipe, > - struct drm_crtc_state *crtc_state, > - struct drm_plane_state *plane_state) > +static void imx_lcdc_crtc_helper_atomic_enable(struct drm_crtc *crtc, > + struct drm_atomic_commit *commit) > { > int ret; > int clk_div; > int bpp; > - struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(pipe->crtc.dev); > - struct drm_display_mode *mode = &pipe->crtc.mode; > + struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(crtc->dev); > + struct drm_crtc_state *cstate = drm_atomic_get_new_crtc_state(commit, crtc); > + struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(commit, &lcdc->plane); > + struct drm_display_mode *mode = &cstate->mode; > struct drm_display_info *disp_info = &lcdc->connector->display_info; > const int hsync_pol = (mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : 1; > const int vsync_pol = (mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : 1; > @@ -206,7 +212,7 @@ static void imx_lcdc_pipe_enable(struct drm_simple_display_pipe *pipe, > > clk_div = DIV_ROUND_CLOSEST_ULL(clk_get_rate(lcdc->clk_per), > mode->clock * 1000); > - bpp = imx_lcdc_get_format(plane_state->fb->format->format); > + bpp = imx_lcdc_get_format(pstate->fb->format->format); > > writel(FIELD_PREP(IMX21LCDC_LPCR_PCD, clk_div - 1) | > FIELD_PREP(IMX21LCDC_LPCR_LPPOL, hsync_pol) | > @@ -230,40 +236,46 @@ static void imx_lcdc_pipe_enable(struct drm_simple_display_pipe *pipe, > > ret = clk_prepare_enable(lcdc->clk_ipg); > if (ret) { > - dev_err(pipe->crtc.dev->dev, "Cannot enable ipg clock: %pe\n", ERR_PTR(ret)); > + dev_err(crtc->dev->dev, "Cannot enable ipg clock: %pe\n", ERR_PTR(ret)); > return; > } > ret = clk_prepare_enable(lcdc->clk_ahb); > if (ret) { > - dev_err(pipe->crtc.dev->dev, "Cannot enable ahb clock: %pe\n", ERR_PTR(ret)); > + dev_err(crtc->dev->dev, "Cannot enable ahb clock: %pe\n", ERR_PTR(ret)); > > clk_disable_unprepare(lcdc->clk_ipg); > > return; > } > > - imx_lcdc_update_hw_registers(pipe, NULL, true); > + imx_lcdc_update_hw_registers(crtc, NULL, cstate, pstate, true); > > /* Enable VBLANK Interrupt */ > writel(INTR_EOF, lcdc->base + IMX21LCDC_LIER); > + > + drm_crtc_vblank_on(crtc); > } > > -static void imx_lcdc_pipe_disable(struct drm_simple_display_pipe *pipe) > +static void imx_lcdc_crtc_helper_atomic_disable(struct drm_crtc *crtc, > + struct drm_atomic_commit *commit) > { > - struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(pipe->crtc.dev); > - struct drm_crtc *crtc = &lcdc->pipe.crtc; > + struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(commit, crtc); > + struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); > + struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(crtc->dev); > struct drm_pending_vblank_event *event; > > + drm_crtc_vblank_off(crtc); > + > clk_disable_unprepare(lcdc->clk_ahb); > clk_disable_unprepare(lcdc->clk_ipg); > > - if (pipe->crtc.enabled) > + if (old_crtc_state->enable) > clk_disable_unprepare(lcdc->clk_per); > > spin_lock_irq(&lcdc->drm.event_lock); > - event = crtc->state->event; > + event = new_crtc_state->event; > if (event) { > - crtc->state->event = NULL; > + new_crtc_state->event = NULL; > drm_crtc_send_vblank_event(crtc, event); > } > spin_unlock_irq(&lcdc->drm.event_lock); > @@ -272,66 +284,132 @@ static void imx_lcdc_pipe_disable(struct drm_simple_display_pipe *pipe) > writel(0, lcdc->base + IMX21LCDC_LIER); > } > > -static int imx_lcdc_pipe_check(struct drm_simple_display_pipe *pipe, > - struct drm_plane_state *plane_state, > - struct drm_crtc_state *crtc_state) > +static int imx_lcdc_crtc_helper_atomic_check(struct drm_crtc *crtc, > + struct drm_atomic_commit *commit) > { > + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); > + struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(commit, crtc); > const struct drm_display_mode *mode = &crtc_state->mode; > - const struct drm_display_mode *old_mode = &pipe->crtc.state->mode; > + const struct drm_display_mode *old_mode = &old_crtc_state->mode; > + int ret; > + > + if (crtc_state->enable) { > + ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); > + if (ret) > + return ret; > + } > > - if (mode->hdisplay < LCDC_MIN_XRES || mode->hdisplay > LCDC_MAX_XRES || > - mode->vdisplay < LCDC_MIN_YRES || mode->vdisplay > LCDC_MAX_YRES || > - mode->hdisplay % 0x10) { /* must be multiple of 16 */ > - drm_err(pipe->crtc.dev, "unsupported display mode (%u x %u)\n", > + if (crtc_state->enable && > + (mode->hdisplay < LCDC_MIN_XRES || mode->hdisplay > LCDC_MAX_XRES || > + mode->vdisplay < LCDC_MIN_YRES || mode->vdisplay > LCDC_MAX_YRES || > + mode->hdisplay % 0x10)) { /* must be multiple of 16 */ > + drm_err(crtc->dev, "unsupported display mode (%u x %u)\n", > mode->hdisplay, mode->vdisplay); > return -EINVAL; > } > > - crtc_state->mode_changed = > - old_mode->hdisplay != mode->hdisplay || > - old_mode->vdisplay != mode->vdisplay; > + if (old_mode->hdisplay != mode->hdisplay || > + old_mode->vdisplay != mode->vdisplay) > + crtc_state->mode_changed = true; > > - return 0; > + return drm_atomic_add_affected_planes(commit, crtc); > } > > -static void imx_lcdc_pipe_update(struct drm_simple_display_pipe *pipe, > - struct drm_plane_state *old_state) > +static void imx_lcdc_plane_helper_atomic_update(struct drm_plane *plane, > + struct drm_atomic_commit *commit) > { > - struct drm_crtc *crtc = &pipe->crtc; > - struct drm_pending_vblank_event *event = crtc->state->event; > - struct drm_plane_state *new_state = pipe->plane.state; > + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(commit, plane); > + struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(commit, plane); > + struct drm_crtc *crtc = new_state->crtc; > + struct drm_crtc_state *old_crtc_state = NULL; > + struct drm_crtc_state *new_crtc_state; > struct drm_framebuffer *fb = new_state->fb; > struct drm_framebuffer *old_fb = old_state->fb; > struct drm_crtc *old_crtc = old_state->crtc; > bool mode_changed = false; > > + if (!fb || !crtc) > + return; > + > + if (old_crtc) > + old_crtc_state = drm_atomic_get_old_crtc_state(commit, old_crtc); > + > + new_crtc_state = drm_atomic_get_new_crtc_state(commit, crtc); > + if (!new_crtc_state) > + return; > + > if (old_fb && old_fb->format != fb->format) > mode_changed = true; > else if (old_crtc != crtc) > mode_changed = true; > > - if (!drm_atomic_crtc_needs_modeset(crtc->state)) > - imx_lcdc_update_hw_registers(pipe, old_state, mode_changed); > + if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) > + imx_lcdc_update_hw_registers(crtc, old_crtc_state, new_crtc_state, > + new_state, mode_changed); > +} > > - if (event) { > - crtc->state->event = NULL; > +static int imx_lcdc_plane_helper_atomic_check(struct drm_plane *plane, > + struct drm_atomic_commit *commit) > +{ > + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(commit, plane); > + struct drm_crtc_state *crtc_state = NULL; > > - spin_lock_irq(&crtc->dev->event_lock); > + if (plane_state->crtc) { > + crtc_state = drm_atomic_get_crtc_state(commit, plane_state->crtc); > + if (IS_ERR(crtc_state)) > + return PTR_ERR(crtc_state); > + } > > - if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) > - drm_crtc_arm_vblank_event(crtc, event); > - else > - drm_crtc_send_vblank_event(crtc, event); > + return drm_atomic_helper_check_plane_state(plane_state, crtc_state, > + DRM_PLANE_NO_SCALING, > + DRM_PLANE_NO_SCALING, > + false, false); > +} > > - spin_unlock_irq(&crtc->dev->event_lock); > - } > +static const struct drm_plane_helper_funcs imx_lcdc_plane_helper_funcs = { > + .prepare_fb = drm_gem_plane_helper_prepare_fb, > + .atomic_check = imx_lcdc_plane_helper_atomic_check, > + .atomic_update = imx_lcdc_plane_helper_atomic_update, > +}; > + > +static const struct drm_plane_funcs imx_lcdc_plane_funcs = { > + .update_plane = drm_atomic_helper_update_plane, > + .disable_plane = drm_atomic_helper_disable_plane, > + .destroy = drm_plane_cleanup, > + .atomic_create_state = drm_atomic_helper_plane_create_state, > + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, > + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, > +}; > + > +static const struct drm_crtc_helper_funcs imx_lcdc_crtc_helper_funcs = { > + .atomic_check = imx_lcdc_crtc_helper_atomic_check, > + .atomic_enable = imx_lcdc_crtc_helper_atomic_enable, > + .atomic_disable = imx_lcdc_crtc_helper_atomic_disable, > + .atomic_flush = drm_crtc_vblank_atomic_flush, > +}; > + > +static int imx_lcdc_crtc_enable_vblank(struct drm_crtc *crtc) > +{ > + return 0; > } > > -static const struct drm_simple_display_pipe_funcs imx_lcdc_pipe_funcs = { > - .enable = imx_lcdc_pipe_enable, > - .disable = imx_lcdc_pipe_disable, > - .check = imx_lcdc_pipe_check, > - .update = imx_lcdc_pipe_update, > +static void imx_lcdc_crtc_disable_vblank(struct drm_crtc *crtc) > +{ > +} > + > +static const struct drm_crtc_funcs imx_lcdc_crtc_funcs = { > + .atomic_create_state = drm_atomic_helper_crtc_create_state, > + .destroy = drm_crtc_cleanup, > + .set_config = drm_atomic_helper_set_config, > + .page_flip = drm_atomic_helper_page_flip, > + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, > + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, > + .enable_vblank = imx_lcdc_crtc_enable_vblank, > + .disable_vblank = imx_lcdc_crtc_disable_vblank, > +}; > + > +static const struct drm_encoder_funcs imx_lcdc_encoder_funcs = { > + .destroy = drm_encoder_cleanup, > }; > > static const struct drm_mode_config_funcs imx_lcdc_mode_config_funcs = { > @@ -369,7 +447,7 @@ MODULE_DEVICE_TABLE(of, imx_lcdc_of_dev_id); > static irqreturn_t imx_lcdc_irq_handler(int irq, void *arg) > { > struct imx_lcdc *lcdc = arg; > - struct drm_crtc *crtc = &lcdc->pipe.crtc; > + struct drm_crtc *crtc = &lcdc->crtc; > unsigned int status; > > status = readl(lcdc->base + IMX21LCDC_LISR); > @@ -387,6 +465,9 @@ static int imx_lcdc_probe(struct platform_device *pdev) > struct imx_lcdc *lcdc; > struct drm_device *drm; > struct drm_bridge *bridge; > + struct drm_plane *plane; > + struct drm_crtc *crtc; > + struct drm_encoder *encoder; > int irq; > int ret; > struct device *dev = &pdev->dev; > @@ -428,23 +509,40 @@ static int imx_lcdc_probe(struct platform_device *pdev) > if (ret) > return dev_err_probe(dev, ret, "Cannot initialize mode configuration structure\n"); > > - /* CRTC, Plane, Encoder */ > - ret = drm_simple_display_pipe_init(drm, &lcdc->pipe, > - &imx_lcdc_pipe_funcs, > - imx_lcdc_formats, > - ARRAY_SIZE(imx_lcdc_formats), NULL, NULL); > + plane = &lcdc->plane; > + ret = drm_universal_plane_init(drm, plane, 0, > + &imx_lcdc_plane_funcs, > + imx_lcdc_formats, > + ARRAY_SIZE(imx_lcdc_formats), > + NULL, > + DRM_PLANE_TYPE_PRIMARY, NULL); > + if (ret < 0) > + return dev_err_probe(drm->dev, ret, "Cannot initialize primary plane\n"); > + drm_plane_helper_add(plane, &imx_lcdc_plane_helper_funcs); > + > + crtc = &lcdc->crtc; > + ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, > + &imx_lcdc_crtc_funcs, NULL); > + if (ret < 0) > + return dev_err_probe(drm->dev, ret, "Cannot initialize CRTC\n"); > + drm_crtc_helper_add(crtc, &imx_lcdc_crtc_helper_funcs); > + > + encoder = &lcdc->encoder; > + ret = drm_encoder_init(drm, encoder, &imx_lcdc_encoder_funcs, > + DRM_MODE_ENCODER_NONE, NULL); > if (ret < 0) > - return dev_err_probe(drm->dev, ret, "Cannot setup simple display pipe\n"); > + return dev_err_probe(drm->dev, ret, "Cannot initialize encoder\n"); > + encoder->possible_crtcs = drm_crtc_mask(crtc); > > ret = drm_vblank_init(drm, drm->mode_config.num_crtc); > if (ret < 0) > return dev_err_probe(drm->dev, ret, "Failed to initialize vblank\n"); > > - ret = drm_bridge_attach(&lcdc->pipe.encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); > + ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); > if (ret) > return dev_err_probe(drm->dev, ret, "Cannot attach bridge\n"); > > - lcdc->connector = drm_bridge_connector_init(drm, &lcdc->pipe.encoder); > + lcdc->connector = drm_bridge_connector_init(drm, encoder); > if (IS_ERR(lcdc->connector)) > return dev_err_probe(drm->dev, PTR_ERR(lcdc->connector), "Cannot init bridge connector\n"); > > @@ -483,7 +581,9 @@ static int imx_lcdc_probe(struct platform_device *pdev) > drm->mode_config.funcs = &imx_lcdc_mode_config_funcs; > drm->mode_config.helper_private = &imx_lcdc_mode_config_helpers; > > - drm_mode_config_reset(drm); > + ret = drm_mode_config_create_initial_state(drm); > + if (ret) > + return dev_err_probe(dev, ret, "Cannot create initial state\n"); > > irq = platform_get_irq(pdev, 0); > if (irq < 0) { > -- -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com GF: Jochen Jaser, Andrew McDonald, (HRB 36809, AG Nürnberg)