diff options
| author | Sarah Walker <sarah.walker@imgtec.com> | 2023-11-22 16:34:33 +0000 |
|---|---|---|
| committer | Maxime Ripard <mripard@kernel.org> | 2023-11-23 09:01:46 +0100 |
| commit | 727538a4bbff07736ecfd704efd7e21718fca3e4 (patch) | |
| tree | 5eb5f5382274583f9f3fb5120b1d2eecce4ecfc6 /drivers/gpu/drm/imagination/pvr_drv.c | |
| parent | ff5f643de0bf27874c4033cd57a0bd034b5c7d11 (diff) | |
drm/imagination: Implement power management
Add power management to the driver, using runtime pm. The power off
sequence depends on firmware commands which are not implemented in this
patch.
Changes since v8:
- Corrected license identifiers
Changes since v5:
- Use RUNTIME_PM_OPS() to declare PM callbacks
- Add Kconfig dependency on CONFIG_PM
Changes since v4:
- Suspend runtime PM before unplugging device on rmmod
Changes since v3:
- Don't power device when calling pvr_device_gpu_fini()
- Documentation for pvr_dev->lost has been improved
- pvr_power_init() renamed to pvr_watchdog_init()
- Use drm_dev_{enter,exit}
Changes since v2:
- Use runtime PM
- Implement watchdog
Signed-off-by: Sarah Walker <sarah.walker@imgtec.com>
Signed-off-by: Donald Robson <donald.robson@imgtec.com>
Reviewed-by: Maxime Ripard <mripard@kernel.org>
Link: https://lore.kernel.org/r/e09af4ef1ff514e1d6d7f97c7c5032c643c56f9c.1700668843.git.donald.robson@imgtec.com
Signed-off-by: Maxime Ripard <mripard@kernel.org>
Diffstat (limited to 'drivers/gpu/drm/imagination/pvr_drv.c')
| -rw-r--r-- | drivers/gpu/drm/imagination/pvr_drv.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c index 6d3bc886e1c3..12e136217c45 100644 --- a/drivers/gpu/drm/imagination/pvr_drv.c +++ b/drivers/gpu/drm/imagination/pvr_drv.c @@ -5,6 +5,7 @@ #include "pvr_drv.h" #include "pvr_gem.h" #include "pvr_mmu.h" +#include "pvr_power.h" #include "pvr_rogue_defs.h" #include "pvr_rogue_fwif_client.h" #include "pvr_rogue_fwif_shared.h" @@ -1265,9 +1266,16 @@ pvr_probe(struct platform_device *plat_dev) platform_set_drvdata(plat_dev, drm_dev); + devm_pm_runtime_enable(&plat_dev->dev); + pm_runtime_mark_last_busy(&plat_dev->dev); + + pm_runtime_set_autosuspend_delay(&plat_dev->dev, 50); + pm_runtime_use_autosuspend(&plat_dev->dev); + pvr_watchdog_init(pvr_dev); + err = pvr_device_init(pvr_dev); if (err) - return err; + goto err_watchdog_fini; err = drm_dev_register(drm_dev, 0); if (err) @@ -1278,6 +1286,9 @@ pvr_probe(struct platform_device *plat_dev) err_device_fini: pvr_device_fini(pvr_dev); +err_watchdog_fini: + pvr_watchdog_fini(pvr_dev); + return err; } @@ -1287,8 +1298,10 @@ pvr_remove(struct platform_device *plat_dev) struct drm_device *drm_dev = platform_get_drvdata(plat_dev); struct pvr_device *pvr_dev = to_pvr_device(drm_dev); + pm_runtime_suspend(drm_dev->dev); pvr_device_fini(pvr_dev); drm_dev_unplug(drm_dev); + pvr_watchdog_fini(pvr_dev); return 0; } @@ -1299,11 +1312,16 @@ static const struct of_device_id dt_match[] = { }; MODULE_DEVICE_TABLE(of, dt_match); +static const struct dev_pm_ops pvr_pm_ops = { + RUNTIME_PM_OPS(pvr_power_device_suspend, pvr_power_device_resume, pvr_power_device_idle) +}; + static struct platform_driver pvr_driver = { .probe = pvr_probe, .remove = pvr_remove, .driver = { .name = PVR_DRIVER_NAME, + .pm = &pvr_pm_ops, .of_match_table = dt_match, }, }; |
