Do hardware resume/suspend. Tested-by: Bhushan Shah <bshah@xxxxxxx> Signed-off-by: Qiang Yu <yuq825@xxxxxxxxx> --- drivers/gpu/drm/lima/lima_device.c | 65 ++++++++++++++++++++++++++++++ drivers/gpu/drm/lima/lima_device.h | 3 ++ drivers/gpu/drm/lima/lima_drv.c | 7 ++++ 3 files changed, 75 insertions(+) diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c index e5f1f84ba85a..aca2cab9899b 100644 --- a/drivers/gpu/drm/lima/lima_device.c +++ b/drivers/gpu/drm/lima/lima_device.c @@ -213,6 +213,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; @@ -408,3 +429,47 @@ 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; + + for (i = 0; i < lima_ip_num; i++) { + err = lima_resume_ip(ldev, i); + if (err) + goto err_out; + } + + err = lima_devfreq_resume(&ldev->devfreq); + if (err) + goto err_out; + + return 0; + +err_out: + while (--i >= 0) + lima_suspend_ip(ldev, i); + 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) + return err; + + for (i = lima_ip_num - 1; i >= 0; i--) + lima_suspend_ip(ldev, i); + + return 0; +} diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h index 095a0b5f1703..e06d1955f4a3 100644 --- a/drivers/gpu/drm/lima/lima_device.h +++ b/drivers/gpu/drm/lima/lima_device.h @@ -141,4 +141,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 diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c index bbbdc8455e2f..be66b448d44e 100644 --- a/drivers/gpu/drm/lima/lima_drv.c +++ b/drivers/gpu/drm/lima/lima_drv.c @@ -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> @@ -452,11 +453,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, }, }; -- 2.17.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel