]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/lima: add pm resume/suspend ops
authorQiang Yu <yuq825@gmail.com>
Tue, 21 Apr 2020 13:35:50 +0000 (21:35 +0800)
committerQiang Yu <yuq825@gmail.com>
Fri, 24 Apr 2020 12:51:19 +0000 (20:51 +0800)
Add driver pm system and runtime hardware resume/suspend ops.
Note this won't enable runtime pm of the device yet.

v2:
Do clock and power gating when suspend/resume.

Tested-by: Bhushan Shah <bshah@kde.org>
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
Signed-off-by: Qiang Yu <yuq825@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200421133551.31481-10-yuq825@gmail.com
drivers/gpu/drm/lima/lima_device.c
drivers/gpu/drm/lima/lima_device.h
drivers/gpu/drm/lima/lima_drv.c

index 1d9b7f415da132fdf902cfc0f7e21403c3dd381e..65fdca366e41f00d940f13a0865234fc47df5595 100644 (file)
@@ -247,6 +247,27 @@ static void lima_fini_ip(struct lima_device *ldev, int index)
                desc->fini(ip);
 }
 
+static int lima_resume_ip(struct lima_device *ldev, int index)
+{
+       struct lima_ip_desc *desc = lima_ip_desc + index;
+       struct lima_ip *ip = ldev->ip + index;
+       int ret = 0;
+
+       if (ip->present)
+               ret = desc->resume(ip);
+
+       return ret;
+}
+
+static void lima_suspend_ip(struct lima_device *ldev, int index)
+{
+       struct lima_ip_desc *desc = lima_ip_desc + index;
+       struct lima_ip *ip = ldev->ip + index;
+
+       if (ip->present)
+               desc->suspend(ip);
+}
+
 static int lima_init_gp_pipe(struct lima_device *dev)
 {
        struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp;
@@ -441,3 +462,72 @@ void lima_device_fini(struct lima_device *ldev)
 
        lima_clk_fini(ldev);
 }
+
+int lima_device_resume(struct device *dev)
+{
+       struct lima_device *ldev = dev_get_drvdata(dev);
+       int i, err;
+
+       err = lima_clk_enable(ldev);
+       if (err) {
+               dev_err(dev, "resume clk fail %d\n", err);
+               return err;
+       }
+
+       err = lima_regulator_enable(ldev);
+       if (err) {
+               dev_err(dev, "resume regulator fail %d\n", err);
+               goto err_out0;
+       }
+
+       for (i = 0; i < lima_ip_num; i++) {
+               err = lima_resume_ip(ldev, i);
+               if (err) {
+                       dev_err(dev, "resume ip %d fail\n", i);
+                       goto err_out1;
+               }
+       }
+
+       err = lima_devfreq_resume(&ldev->devfreq);
+       if (err) {
+               dev_err(dev, "devfreq resume fail\n");
+               goto err_out1;
+       }
+
+       return 0;
+
+err_out1:
+       while (--i >= 0)
+               lima_suspend_ip(ldev, i);
+       lima_regulator_disable(ldev);
+err_out0:
+       lima_clk_disable(ldev);
+       return err;
+}
+
+int lima_device_suspend(struct device *dev)
+{
+       struct lima_device *ldev = dev_get_drvdata(dev);
+       int i, err;
+
+       /* check any task running */
+       for (i = 0; i < lima_pipe_num; i++) {
+               if (atomic_read(&ldev->pipe[i].base.hw_rq_count))
+                       return -EBUSY;
+       }
+
+       err = lima_devfreq_suspend(&ldev->devfreq);
+       if (err) {
+               dev_err(dev, "devfreq suspend fail\n");
+               return err;
+       }
+
+       for (i = lima_ip_num - 1; i >= 0; i--)
+               lima_suspend_ip(ldev, i);
+
+       lima_regulator_disable(ldev);
+
+       lima_clk_disable(ldev);
+
+       return 0;
+}
index d9df1b45dfa91bab2882cb1edd688f92389b6cfc..41b9d7b4bcc7a0128adda97379b6048735310096 100644 (file)
@@ -140,4 +140,7 @@ static inline int lima_poll_timeout(struct lima_ip *ip, lima_poll_func_t func,
        return 0;
 }
 
+int lima_device_suspend(struct device *dev);
+int lima_device_resume(struct device *dev);
+
 #endif
index 3d63d496cfc2fe99ab0d854ebc4e6ba0e6df1324..f3fe0a2f764b6e348a74b29e1b9802cf19777021 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/of_platform.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 #include <drm/drm_ioctl.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_prime.h>
@@ -451,11 +452,17 @@ static const struct of_device_id dt_match[] = {
 };
 MODULE_DEVICE_TABLE(of, dt_match);
 
+static const struct dev_pm_ops lima_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
+       SET_RUNTIME_PM_OPS(lima_device_suspend, lima_device_resume, NULL)
+};
+
 static struct platform_driver lima_platform_driver = {
        .probe      = lima_pdev_probe,
        .remove     = lima_pdev_remove,
        .driver     = {
                .name   = "lima",
+               .pm     = &lima_pm_ops,
                .of_match_table = dt_match,
        },
 };