From nobody Mon Dec 1 23:10:29 2025 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2882A345CC0 for ; Wed, 26 Nov 2025 17:37:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764178653; cv=none; b=tDwpIIZm2yyJV1ZHwGpfB8/qhy2VqUrvi908TsogdSp8dQjv9xSpbW7yiyZg+M1L/EtsMO01rC+mIIlhRl4SGS4BIV6fbyeUqQfG3Y0i2XrWw/pOa885jplIsVsl4Oly0JCxc0Z6WtMS1BhBqkHYxv4qAjOLftMFbseBoU5EtHI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764178653; c=relaxed/simple; bh=E1JiYf0PNWj94HbkJimeEIxUZs0csEsJSqng/S7XHOI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WIJdEh9/oK9MkMy/wo+2DY+RgXA8uGW+Oa4/NfXhxStoqjtBvsDntWVe9xAlVuJAlMd+bU0SWFLeqii3uoSBvv3AAQi6HQcZeg6u45mcc0zrCHMxoDwDtYCW82hC2y2WUjIS5nMkzPtdyVELwktMssWWCHVTZ+swb/FdFkLxr/o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=ZLFZ1x5W; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="ZLFZ1x5W" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id BA78B1A1D85; Wed, 26 Nov 2025 17:37:29 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 880A760721; Wed, 26 Nov 2025 17:37:29 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id A1857102F2334; Wed, 26 Nov 2025 18:37:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1764178648; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=Da+mpPsZxs8p0C2kI+nf3F6mzzsIoNSMzhX4ZJmDJh4=; b=ZLFZ1x5Wn9u4MpZZN9uEQmb/+rp9dTHJ4+kxP5ls3lkv5alcy33+cOd5A3JnFi9yogScXp 9T4Wi0a0Rcs4wiIgrELaCx/LfUd+Nqan7gVKe9SE4Xs7d+gph5G1fk7N/c7rD8hRgxcq0Y +0jRGimWOmFoAnQ8vS+xsCUiKz2lxhbnHAG0CrP1VAc0pAUX5gFE82ovl2bl+5eYZmlBr2 aJLEpIojbPXGJ/OrMWgn3LcGHIqt+p+n4pGFQ7K4xBY3eAHJr7evu1W2GcCPN5DZE/Xd0l bOIlwwPAoUid3oxqhOjSVsZg1OZX5CwRob8GximdtHL3aOQi6msYw9L5C3XFWA== From: "Kory Maincent (TI.com)" Date: Wed, 26 Nov 2025 18:35:57 +0100 Subject: [PATCH 15/21] drm/tilcdc: Modernize driver initialization and cleanup paths Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251126-feature_tilcdc-v1-15-49b9ef2e3aa0@bootlin.com> References: <20251126-feature_tilcdc-v1-0-49b9ef2e3aa0@bootlin.com> In-Reply-To: <20251126-feature_tilcdc-v1-0-49b9ef2e3aa0@bootlin.com> To: Jyri Sarha , Tomi Valkeinen , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Russell King , Bartosz Golaszewski , Tony Lindgren , Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec Cc: Markus Schneider-Pargmann , Luca Ceresoli , Louis Chauvet , Thomas Petazzoni , Miguel Gazquez , dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-omap@vger.kernel.org, "Kory Maincent (TI.com)" X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 Refactor the driver initialization to use modern DRM managed resource APIs, simplifying the code. The tilcdc_init and tilcdc_fini wrapper functions are removed since they served no purpose after the component framework was eliminated. Their logic is integrated directly into probe and remove. Key changes: - Use devm_drm_dev_alloc() instead of drm_dev_alloc(). - Use drmm_mode_config_init() instead of drm_mode_config_init(). - Align the remove path with the probe error path to ensure consistent cleanup ordering in both success and failure cases. - Adjust platform_set_drvdata() to store the private structure instead of the drm_device, matching the new allocation pattern. These changes reduce error-prone code while maintaining the same functional behavior. Signed-off-by: Kory Maincent (TI.com) --- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 308 ++++++++++++++++----------------= ---- drivers/gpu/drm/tilcdc/tilcdc_drv.h | 2 + 2 files changed, 139 insertions(+), 171 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/t= ilcdc_drv.c index 9b31eaafd2be9..e08bea30585e0 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -134,65 +134,149 @@ static void tilcdc_irq_uninstall(struct drm_device *= dev) * DRM operations: */ =20 -static void tilcdc_fini(struct drm_device *dev) +#if defined(CONFIG_DEBUG_FS) +static const struct { + const char *name; + uint8_t rev; + uint8_t save; + uint32_t reg; +} registers[] =3D { +#define REG(rev, save, reg) { #reg, rev, save, reg } + /* exists in revision 1: */ + REG(1, false, LCDC_PID_REG), + REG(1, true, LCDC_CTRL_REG), + REG(1, false, LCDC_STAT_REG), + REG(1, true, LCDC_RASTER_CTRL_REG), + REG(1, true, LCDC_RASTER_TIMING_0_REG), + REG(1, true, LCDC_RASTER_TIMING_1_REG), + REG(1, true, LCDC_RASTER_TIMING_2_REG), + REG(1, true, LCDC_DMA_CTRL_REG), + REG(1, true, LCDC_DMA_FB_BASE_ADDR_0_REG), + REG(1, true, LCDC_DMA_FB_CEILING_ADDR_0_REG), + REG(1, true, LCDC_DMA_FB_BASE_ADDR_1_REG), + REG(1, true, LCDC_DMA_FB_CEILING_ADDR_1_REG), + /* new in revision 2: */ + REG(2, false, LCDC_RAW_STAT_REG), + REG(2, false, LCDC_MASKED_STAT_REG), + REG(2, true, LCDC_INT_ENABLE_SET_REG), + REG(2, false, LCDC_INT_ENABLE_CLR_REG), + REG(2, false, LCDC_END_OF_INT_IND_REG), + REG(2, true, LCDC_CLK_ENABLE_REG), +#undef REG +}; + +static int tilcdc_regs_show(struct seq_file *m, void *arg) { + struct drm_info_node *node =3D (struct drm_info_node *) m->private; + struct drm_device *dev =3D node->minor->dev; struct tilcdc_drm_private *priv =3D dev->dev_private; + unsigned i; =20 -#ifdef CONFIG_CPU_FREQ - if (priv->freq_transition.notifier_call) - cpufreq_unregister_notifier(&priv->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); + pm_runtime_get_sync(dev->dev); + + seq_printf(m, "revision: %d\n", priv->rev); + + for (i =3D 0; i < ARRAY_SIZE(registers); i++) + if (priv->rev >=3D registers[i].rev) + seq_printf(m, "%s:\t %08x\n", registers[i].name, + tilcdc_read(dev, registers[i].reg)); + + pm_runtime_put_sync(dev->dev); + + return 0; +} + +static int tilcdc_mm_show(struct seq_file *m, void *arg) +{ + struct drm_info_node *node =3D (struct drm_info_node *) m->private; + struct drm_device *dev =3D node->minor->dev; + struct drm_printer p =3D drm_seq_file_printer(m); + drm_mm_print(&dev->vma_offset_manager->vm_addr_space_mm, &p); + return 0; +} + +static struct drm_info_list tilcdc_debugfs_list[] =3D { + { "regs", tilcdc_regs_show, 0, NULL }, + { "mm", tilcdc_mm_show, 0, NULL }, +}; + +static void tilcdc_debugfs_init(struct drm_minor *minor) +{ + drm_debugfs_create_files(tilcdc_debugfs_list, + ARRAY_SIZE(tilcdc_debugfs_list), + minor->debugfs_root, minor); +} #endif =20 - if (priv->crtc) - tilcdc_crtc_shutdown(priv->crtc); +DEFINE_DRM_GEM_DMA_FOPS(fops); =20 - drm_dev_unregister(dev); +static const struct drm_driver tilcdc_driver =3D { + .driver_features =3D DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, + DRM_GEM_DMA_DRIVER_OPS, + DRM_FBDEV_DMA_DRIVER_OPS, +#ifdef CONFIG_DEBUG_FS + .debugfs_init =3D tilcdc_debugfs_init, +#endif + .fops =3D &fops, + .name =3D "tilcdc", + .desc =3D "TI LCD Controller DRM", + .major =3D 1, + .minor =3D 0, +}; =20 - drm_kms_helper_poll_fini(dev); - drm_atomic_helper_shutdown(dev); - tilcdc_irq_uninstall(dev); - drm_mode_config_cleanup(dev); +/* + * Power management: + */ =20 - if (priv->clk) - clk_put(priv->clk); +static int tilcdc_pm_suspend(struct device *dev) +{ + struct drm_device *ddev =3D dev_get_drvdata(dev); + int ret =3D 0; =20 - if (priv->wq) - destroy_workqueue(priv->wq); + ret =3D drm_mode_config_helper_suspend(ddev); + + /* Select sleep pin state */ + pinctrl_pm_select_sleep_state(dev); =20 - dev->dev_private =3D NULL; + return ret; +} =20 - pm_runtime_disable(dev->dev); +static int tilcdc_pm_resume(struct device *dev) +{ + struct drm_device *ddev =3D dev_get_drvdata(dev); =20 - drm_dev_put(dev); + /* Select default pin state */ + pinctrl_pm_select_default_state(dev); + return drm_mode_config_helper_resume(ddev); } =20 -static int tilcdc_init(const struct drm_driver *ddrv, struct device *dev) +static DEFINE_SIMPLE_DEV_PM_OPS(tilcdc_pm_ops, + tilcdc_pm_suspend, tilcdc_pm_resume); + +static int tilcdc_pdev_probe(struct platform_device *pdev) { - struct drm_device *ddev; - struct platform_device *pdev =3D to_platform_device(dev); - struct device_node *node =3D dev->of_node; + struct device_node *node =3D pdev->dev.of_node; + struct device *dev =3D &pdev->dev; struct tilcdc_drm_private *priv; + struct drm_device *ddev; u32 bpp =3D 0; int ret; =20 - priv =3D devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - ddev =3D drm_dev_alloc(ddrv, dev); - if (IS_ERR(ddev)) - return PTR_ERR(ddev); + priv =3D devm_drm_dev_alloc(dev, &tilcdc_driver, + struct tilcdc_drm_private, ddev); + if (IS_ERR(priv)) + return PTR_ERR(priv); =20 + platform_set_drvdata(pdev, priv); + ddev =3D &priv->ddev; ddev->dev_private =3D priv; - platform_set_drvdata(pdev, ddev); - drm_mode_config_init(ddev); + ret =3D drmm_mode_config_init(ddev); + if (ret) + return ret; =20 priv->wq =3D alloc_ordered_workqueue("tilcdc", 0); - if (!priv->wq) { - ret =3D -ENOMEM; - goto put_drm; - } + if (!priv->wq) + return -ENOMEM; =20 priv->mmio =3D devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->mmio)) { @@ -355,152 +439,34 @@ static int tilcdc_init(const struct drm_driver *ddrv= , struct device *dev) clk_put(priv->clk); free_wq: destroy_workqueue(priv->wq); -put_drm: - platform_set_drvdata(pdev, NULL); - ddev->dev_private =3D NULL; - drm_dev_put(ddev); =20 return ret; } =20 -#if defined(CONFIG_DEBUG_FS) -static const struct { - const char *name; - uint8_t rev; - uint8_t save; - uint32_t reg; -} registers[] =3D { -#define REG(rev, save, reg) { #reg, rev, save, reg } - /* exists in revision 1: */ - REG(1, false, LCDC_PID_REG), - REG(1, true, LCDC_CTRL_REG), - REG(1, false, LCDC_STAT_REG), - REG(1, true, LCDC_RASTER_CTRL_REG), - REG(1, true, LCDC_RASTER_TIMING_0_REG), - REG(1, true, LCDC_RASTER_TIMING_1_REG), - REG(1, true, LCDC_RASTER_TIMING_2_REG), - REG(1, true, LCDC_DMA_CTRL_REG), - REG(1, true, LCDC_DMA_FB_BASE_ADDR_0_REG), - REG(1, true, LCDC_DMA_FB_CEILING_ADDR_0_REG), - REG(1, true, LCDC_DMA_FB_BASE_ADDR_1_REG), - REG(1, true, LCDC_DMA_FB_CEILING_ADDR_1_REG), - /* new in revision 2: */ - REG(2, false, LCDC_RAW_STAT_REG), - REG(2, false, LCDC_MASKED_STAT_REG), - REG(2, true, LCDC_INT_ENABLE_SET_REG), - REG(2, false, LCDC_INT_ENABLE_CLR_REG), - REG(2, false, LCDC_END_OF_INT_IND_REG), - REG(2, true, LCDC_CLK_ENABLE_REG), -#undef REG -}; - -static int tilcdc_regs_show(struct seq_file *m, void *arg) -{ - struct drm_info_node *node =3D (struct drm_info_node *) m->private; - struct drm_device *dev =3D node->minor->dev; - struct tilcdc_drm_private *priv =3D dev->dev_private; - unsigned i; - - pm_runtime_get_sync(dev->dev); - - seq_printf(m, "revision: %d\n", priv->rev); - - for (i =3D 0; i < ARRAY_SIZE(registers); i++) - if (priv->rev >=3D registers[i].rev) - seq_printf(m, "%s:\t %08x\n", registers[i].name, - tilcdc_read(dev, registers[i].reg)); - - pm_runtime_put_sync(dev->dev); - - return 0; -} - -static int tilcdc_mm_show(struct seq_file *m, void *arg) -{ - struct drm_info_node *node =3D (struct drm_info_node *) m->private; - struct drm_device *dev =3D node->minor->dev; - struct drm_printer p =3D drm_seq_file_printer(m); - drm_mm_print(&dev->vma_offset_manager->vm_addr_space_mm, &p); - return 0; -} - -static struct drm_info_list tilcdc_debugfs_list[] =3D { - { "regs", tilcdc_regs_show, 0, NULL }, - { "mm", tilcdc_mm_show, 0, NULL }, -}; - -static void tilcdc_debugfs_init(struct drm_minor *minor) +static void tilcdc_pdev_remove(struct platform_device *pdev) { - drm_debugfs_create_files(tilcdc_debugfs_list, - ARRAY_SIZE(tilcdc_debugfs_list), - minor->debugfs_root, minor); -} -#endif - -DEFINE_DRM_GEM_DMA_FOPS(fops); + struct tilcdc_drm_private *priv =3D platform_get_drvdata(pdev); + struct drm_device *ddev =3D &priv->ddev; =20 -static const struct drm_driver tilcdc_driver =3D { - .driver_features =3D DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_DMA_DRIVER_OPS, - DRM_FBDEV_DMA_DRIVER_OPS, -#ifdef CONFIG_DEBUG_FS - .debugfs_init =3D tilcdc_debugfs_init, + drm_dev_unregister(ddev); + drm_kms_helper_poll_fini(ddev); + tilcdc_irq_uninstall(ddev); +#ifdef CONFIG_CPU_FREQ + cpufreq_unregister_notifier(&priv->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); #endif - .fops =3D &fops, - .name =3D "tilcdc", - .desc =3D "TI LCD Controller DRM", - .major =3D 1, - .minor =3D 0, -}; - -/* - * Power management: - */ - -static int tilcdc_pm_suspend(struct device *dev) -{ - struct drm_device *ddev =3D dev_get_drvdata(dev); - int ret =3D 0; - - ret =3D drm_mode_config_helper_suspend(ddev); - - /* Select sleep pin state */ - pinctrl_pm_select_sleep_state(dev); - - return ret; -} - -static int tilcdc_pm_resume(struct device *dev) -{ - struct drm_device *ddev =3D dev_get_drvdata(dev); - - /* Select default pin state */ - pinctrl_pm_select_default_state(dev); - return drm_mode_config_helper_resume(ddev); -} - -static DEFINE_SIMPLE_DEV_PM_OPS(tilcdc_pm_ops, - tilcdc_pm_suspend, tilcdc_pm_resume); - -static int tilcdc_pdev_probe(struct platform_device *pdev) -{ - /* bail out early if no DT data: */ - if (!pdev->dev.of_node) { - dev_err(&pdev->dev, "device-tree data is missing\n"); - return -ENXIO; - } - - return tilcdc_init(&tilcdc_driver, &pdev->dev); -} - -static void tilcdc_pdev_remove(struct platform_device *pdev) -{ - tilcdc_fini(platform_get_drvdata(pdev)); + tilcdc_crtc_destroy(priv->crtc); + pm_runtime_disable(&pdev->dev); + clk_put(priv->clk); + destroy_workqueue(priv->wq); } =20 static void tilcdc_pdev_shutdown(struct platform_device *pdev) { - drm_atomic_helper_shutdown(platform_get_drvdata(pdev)); + struct tilcdc_drm_private *priv =3D platform_get_drvdata(pdev); + struct drm_device *ddev =3D &priv->ddev; + + drm_atomic_helper_shutdown(ddev); } =20 static const struct of_device_id tilcdc_of_match[] =3D { diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/t= ilcdc_drv.h index 60e85e29b1063..e3d04a3eb25b4 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -48,6 +48,8 @@ struct tilcdc_drm_private { =20 unsigned int irq; =20 + struct drm_device ddev; + /* don't attempt resolutions w/ higher W * H * Hz: */ uint32_t max_bandwidth; /* --=20 2.43.0