diff --git a/drivers/media/platform/rk3288-vpu/rk3288_vpu.c b/drivers/media/platform/rk3288-vpu/rk3288_vpu.c index c7e5d9918671..c9ea748148a2 100644 --- a/drivers/media/platform/rk3288-vpu/rk3288_vpu.c +++ b/drivers/media/platform/rk3288-vpu/rk3288_vpu.c @@ -102,7 +102,8 @@ static void rk3288_vpu_try_run(struct rk3288_vpu_dev *dev) spin_lock_irqsave(&dev->irqlock, flags); - if (list_empty(&dev->ready_ctxs)) + if (list_empty(&dev->ready_ctxs) || + test_bit(VPU_SUSPENDED, &dev->state)) /* Nothing to do. */ goto out; @@ -716,6 +717,32 @@ static const struct of_device_id of_rk3288_vpu_match[] = { MODULE_DEVICE_TABLE(of, of_rk3288_vpu_match); #endif +#ifdef CONFIG_PM_SLEEP +static int rk3288_vpu_suspend(struct device *dev) +{ + struct rk3288_vpu_dev *vpu = dev_get_drvdata(dev); + + set_bit(VPU_SUSPENDED, &vpu->state); + wait_event(vpu->run_wq, vpu->current_ctx == NULL); + + return 0; +} + +static int rk3288_vpu_resume(struct device *dev) +{ + struct rk3288_vpu_dev *vpu = dev_get_drvdata(dev); + + clear_bit(VPU_SUSPENDED, &vpu->state); + rk3288_vpu_try_run(vpu); + + return 0; +} +#endif + +static const struct dev_pm_ops rk3288_vpu_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(rk3288_vpu_suspend, rk3288_vpu_resume) +}; + static struct platform_driver rk3288_vpu_driver = { .probe = rk3288_vpu_probe, .remove = rk3288_vpu_remove, @@ -724,6 +751,7 @@ static struct platform_driver rk3288_vpu_driver = { .name = RK3288_VPU_NAME, .owner = THIS_MODULE, .of_match_table = of_match_ptr(of_rk3288_vpu_match), + .pm = &rk3288_vpu_pm_ops, }, }; module_platform_driver(rk3288_vpu_driver); diff --git a/drivers/media/platform/rk3288-vpu/rk3288_vpu_common.h b/drivers/media/platform/rk3288-vpu/rk3288_vpu_common.h index 34828369875f..a074e2c63d60 100644 --- a/drivers/media/platform/rk3288-vpu/rk3288_vpu_common.h +++ b/drivers/media/platform/rk3288-vpu/rk3288_vpu_common.h @@ -121,9 +121,12 @@ struct rk3288_vpu_buf { * enum rk3288_vpu_state - bitwise flags indicating hardware state. * @VPU_RUNNING: The hardware has been programmed for operation * and is running at the moment. + * @VPU_SUSPENDED: System is entering sleep state and no more runs + * should be executed on hardware. */ enum rk3288_vpu_state { VPU_RUNNING = BIT(0), + VPU_SUSPENDED = BIT(1), }; /**