drm/lima: add pm resume/suspend ops
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
This commit is contained in:
parent
7a475eb470
commit
63945d5149
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user