]> git.itanic.dy.fi Git - linux-stable/commitdiff
drm: renesas: shmobile: Add support for Runtime PM
authorGeert Uytterhoeven <geert+renesas@glider.be>
Fri, 15 Sep 2023 08:53:22 +0000 (10:53 +0200)
committerGeert Uytterhoeven <geert+renesas@glider.be>
Mon, 16 Oct 2023 09:47:43 +0000 (11:47 +0200)
The SH-Mobile LCD Controller is part of a PM Domain on all relevant SoCs
(clock domain on all, power domain on some).  Hence it may not be
sufficient to manage the LCDC module clock explicitly (e.g. if the
selected clock source differs from SHMOB_DRM_CLK_BUS).

Fix this by using Runtime PM for all clock handling.  Add an explicit
dependency on CONFIG_PM, which should already be met on all affected
platforms.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/e7359a64963bd9a4f1531c2beae850774ce140bc.1694767209.git.geert+renesas@glider.be
drivers/gpu/drm/renesas/shmobile/Kconfig
drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c
drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c

index ad14112999ad8abaedf19f0e9c53685273fe7e8e..ba941587ca70e08c251af2942dba7ee9f4afa186 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 config DRM_SHMOBILE
        tristate "DRM Support for SH Mobile"
-       depends on DRM
+       depends on DRM && PM
        depends on ARCH_RENESAS || ARCH_SHMOBILE || COMPILE_TEST
        select BACKLIGHT_CLASS_DEVICE
        select DRM_KMS_HELPER
index fbfd906844da490c2f2d9760df66ea6a24212977..2d9ae0c6ab7b18a8fbedb1dbb3b7c9ce4ec61630 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/backlight.h>
 #include <linux/clk.h>
+#include <linux/pm_runtime.h>
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
  * TODO: panel support
  */
 
-/* -----------------------------------------------------------------------------
- * Clock management
- */
-
-static int shmob_drm_clk_on(struct shmob_drm_device *sdev)
-{
-       int ret;
-
-       if (sdev->clock) {
-               ret = clk_prepare_enable(sdev->clock);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static void shmob_drm_clk_off(struct shmob_drm_device *sdev)
-{
-       if (sdev->clock)
-               clk_disable_unprepare(sdev->clock);
-}
-
 /* -----------------------------------------------------------------------------
  * CRTC
  */
@@ -170,9 +148,8 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
        if (WARN_ON(format == NULL))
                return;
 
-       /* Enable clocks before accessing the hardware. */
-       ret = shmob_drm_clk_on(sdev);
-       if (ret < 0)
+       ret = pm_runtime_resume_and_get(sdev->dev);
+       if (ret)
                return;
 
        /* Reset and enable the LCDC. */
@@ -268,8 +245,7 @@ static void shmob_drm_crtc_stop(struct shmob_drm_crtc *scrtc)
        /* Disable the display output. */
        lcdc_write(sdev, LDCNT1R, 0);
 
-       /* Stop clocks. */
-       shmob_drm_clk_off(sdev);
+       pm_runtime_put(sdev->dev);
 
        scrtc->started = false;
 }
index e5db4e0095bad1feae6fe223cdd2d84f10be1200..a0f8b7666ab3336504d4801234d8e14dbde53b97 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 #include <drm/drm_drv.h>
@@ -165,8 +166,35 @@ static int shmob_drm_pm_resume(struct device *dev)
        return 0;
 }
 
-static DEFINE_SIMPLE_DEV_PM_OPS(shmob_drm_pm_ops,
-                               shmob_drm_pm_suspend, shmob_drm_pm_resume);
+static int shmob_drm_pm_runtime_suspend(struct device *dev)
+{
+       struct shmob_drm_device *sdev = dev_get_drvdata(dev);
+
+       if (sdev->clock)
+               clk_disable_unprepare(sdev->clock);
+
+       return 0;
+}
+
+static int shmob_drm_pm_runtime_resume(struct device *dev)
+{
+       struct shmob_drm_device *sdev = dev_get_drvdata(dev);
+       int ret;
+
+       if (sdev->clock) {
+               ret = clk_prepare_enable(sdev->clock);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static const struct dev_pm_ops shmob_drm_pm_ops = {
+       SYSTEM_SLEEP_PM_OPS(shmob_drm_pm_suspend, shmob_drm_pm_resume)
+       RUNTIME_PM_OPS(shmob_drm_pm_runtime_suspend,
+                      shmob_drm_pm_runtime_resume, NULL)
+};
 
 /* -----------------------------------------------------------------------------
  * Platform driver
@@ -218,6 +246,10 @@ static int shmob_drm_probe(struct platform_device *pdev)
        if (ret < 0)
                return ret;
 
+       ret = devm_pm_runtime_enable(&pdev->dev);
+       if (ret)
+               return ret;
+
        ret = shmob_drm_init_interface(sdev);
        if (ret < 0)
                return ret;
@@ -289,7 +321,7 @@ static struct platform_driver shmob_drm_platform_driver = {
        .remove_new     = shmob_drm_remove,
        .driver         = {
                .name   = "shmob-drm",
-               .pm     = pm_sleep_ptr(&shmob_drm_pm_ops),
+               .pm     = &shmob_drm_pm_ops,
        },
 };