drm/komeda: Add runtime_pm support
authorjames qian wang (Arm Technology China) <james.qian.wang@arm.com>
Thu, 12 Dec 2019 07:48:13 +0000 (07:48 +0000)
committerjames qian wang (Arm Technology China) <james.qian.wang@arm.com>
Fri, 27 Dec 2019 05:45:44 +0000 (13:45 +0800)
- Add pm_runtime_get/put to crtc_enable/disable along with the real
  display usage
- Add runtime_get/put to register_show, since register_show() will
  access register, need to wakeup HW.
- For the case that PM is not enabled or configured, manually wakeup HW

Signed-off-by: james qian wang (Arm Technology China) <james.qian.wang@arm.com>
Reviewed-by: Mihail Atanassov <mihail.atanassov@arm.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191212074756.14678-1-james.qian.wang@arm.com
drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
drivers/gpu/drm/arm/display/komeda/komeda_dev.c
drivers/gpu/drm/arm/display/komeda/komeda_drv.c
drivers/gpu/drm/arm/display/komeda/komeda_kms.c

index 1c452ea75999f289a24fa028230b681d91cbe509..56bd938961eeea29a1895616a4a3f3da716aad5d 100644 (file)
@@ -5,6 +5,7 @@
  *
  */
 #include <linux/clk.h>
+#include <linux/pm_runtime.h>
 #include <linux/spinlock.h>
 
 #include <drm/drm_atomic.h>
@@ -274,6 +275,7 @@ static void
 komeda_crtc_atomic_enable(struct drm_crtc *crtc,
                          struct drm_crtc_state *old)
 {
+       pm_runtime_get_sync(crtc->dev->dev);
        komeda_crtc_prepare(to_kcrtc(crtc));
        drm_crtc_vblank_on(crtc);
        WARN_ON(drm_crtc_vblank_get(crtc));
@@ -372,6 +374,7 @@ komeda_crtc_atomic_disable(struct drm_crtc *crtc,
        drm_crtc_vblank_put(crtc);
        drm_crtc_vblank_off(crtc);
        komeda_crtc_unprepare(kcrtc);
+       pm_runtime_put(crtc->dev->dev);
 }
 
 static void
index 38b832804badbb8b2c44e1e624566447a00d181c..1d767473ba8a0613fc96d8ae9fae8feedcd0e0c9 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/of_graph.h>
 #include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/dma-mapping.h>
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
@@ -27,12 +28,16 @@ static int komeda_register_show(struct seq_file *sf, void *x)
 
        seq_puts(sf, "\n====== Komeda register dump =========\n");
 
+       pm_runtime_get_sync(mdev->dev);
+
        if (mdev->funcs->dump_register)
                mdev->funcs->dump_register(mdev, sf);
 
        for (i = 0; i < mdev->n_pipelines; i++)
                komeda_pipeline_dump_register(mdev->pipelines[i], sf);
 
+       pm_runtime_put(mdev->dev);
+
        return 0;
 }
 
@@ -263,15 +268,6 @@ struct komeda_dev *komeda_dev_create(struct device *dev)
        if (!mdev->iommu)
                DRM_INFO("continue without IOMMU support!\n");
 
-       if (mdev->iommu && mdev->funcs->connect_iommu) {
-               err = mdev->funcs->connect_iommu(mdev);
-               if (err) {
-                       DRM_ERROR("connect iommu failed.\n");
-                       mdev->iommu = NULL;
-                       goto disable_clk;
-               }
-       }
-
        clk_disable_unprepare(mdev->aclk);
 
        err = sysfs_create_group(&dev->kobj, &komeda_sysfs_attr_group);
@@ -310,11 +306,6 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
        if (mdev->aclk)
                clk_prepare_enable(mdev->aclk);
 
-       if (mdev->iommu && mdev->funcs->disconnect_iommu)
-               if (mdev->funcs->disconnect_iommu(mdev))
-                       DRM_ERROR("disconnect iommu failed.\n");
-       mdev->iommu = NULL;
-
        for (i = 0; i < mdev->n_pipelines; i++) {
                komeda_pipeline_destroy(mdev, mdev->pipelines[i]);
                mdev->pipelines[i] = NULL;
@@ -343,44 +334,26 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
 
 int komeda_dev_resume(struct komeda_dev *mdev)
 {
-       int ret = 0;
-
        clk_prepare_enable(mdev->aclk);
 
-       if (mdev->iommu && mdev->funcs->connect_iommu) {
-               ret = mdev->funcs->connect_iommu(mdev);
-               if (ret < 0) {
-                       DRM_ERROR("connect iommu failed.\n");
-                       goto disable_clk;
-               }
-       }
-
-       ret = mdev->funcs->enable_irq(mdev);
+       mdev->funcs->enable_irq(mdev);
 
-disable_clk:
-       clk_disable_unprepare(mdev->aclk);
+       if (mdev->iommu && mdev->funcs->connect_iommu)
+               if (mdev->funcs->connect_iommu(mdev))
+                       DRM_ERROR("connect iommu failed.\n");
 
-       return ret;
+       return 0;
 }
 
 int komeda_dev_suspend(struct komeda_dev *mdev)
 {
-       int ret = 0;
-
-       clk_prepare_enable(mdev->aclk);
-
-       if (mdev->iommu && mdev->funcs->disconnect_iommu) {
-               ret = mdev->funcs->disconnect_iommu(mdev);
-               if (ret < 0) {
+       if (mdev->iommu && mdev->funcs->disconnect_iommu)
+               if (mdev->funcs->disconnect_iommu(mdev))
                        DRM_ERROR("disconnect iommu failed.\n");
-                       goto disable_clk;
-               }
-       }
 
-       ret = mdev->funcs->disable_irq(mdev);
+       mdev->funcs->disable_irq(mdev);
 
-disable_clk:
        clk_disable_unprepare(mdev->aclk);
 
-       return ret;
+       return 0;
 }
index ad38bbc7431e5fc8e84b9f6fff36708bd7848f50..ea5cd1e1730494e60bca57643f65dc23bcfb7f00 100644 (file)
@@ -33,6 +33,12 @@ static void komeda_unbind(struct device *dev)
                return;
 
        komeda_kms_detach(mdrv->kms);
+
+       if (pm_runtime_enabled(dev))
+               pm_runtime_disable(dev);
+       else
+               komeda_dev_suspend(mdrv->mdev);
+
        komeda_dev_destroy(mdrv->mdev);
 
        dev_set_drvdata(dev, NULL);
@@ -54,6 +60,10 @@ static int komeda_bind(struct device *dev)
                goto free_mdrv;
        }
 
+       pm_runtime_enable(dev);
+       if (!pm_runtime_enabled(dev))
+               komeda_dev_resume(mdrv->mdev);
+
        mdrv->kms = komeda_kms_attach(mdrv->mdev);
        if (IS_ERR(mdrv->kms)) {
                err = PTR_ERR(mdrv->kms);
@@ -65,6 +75,11 @@ static int komeda_bind(struct device *dev)
        return 0;
 
 destroy_mdev:
+       if (pm_runtime_enabled(dev))
+               pm_runtime_disable(dev);
+       else
+               komeda_dev_suspend(mdrv->mdev);
+
        komeda_dev_destroy(mdrv->mdev);
 
 free_mdrv:
@@ -131,15 +146,29 @@ static const struct of_device_id komeda_of_match[] = {
 
 MODULE_DEVICE_TABLE(of, komeda_of_match);
 
+static int komeda_rt_pm_suspend(struct device *dev)
+{
+       struct komeda_drv *mdrv = dev_get_drvdata(dev);
+
+       return komeda_dev_suspend(mdrv->mdev);
+}
+
+static int komeda_rt_pm_resume(struct device *dev)
+{
+       struct komeda_drv *mdrv = dev_get_drvdata(dev);
+
+       return komeda_dev_resume(mdrv->mdev);
+}
+
 static int __maybe_unused komeda_pm_suspend(struct device *dev)
 {
        struct komeda_drv *mdrv = dev_get_drvdata(dev);
-       struct drm_device *drm = &mdrv->kms->base;
        int res;
 
-       res = drm_mode_config_helper_suspend(drm);
+       res = drm_mode_config_helper_suspend(&mdrv->kms->base);
 
-       komeda_dev_suspend(mdrv->mdev);
+       if (!pm_runtime_status_suspended(dev))
+               komeda_dev_suspend(mdrv->mdev);
 
        return res;
 }
@@ -147,15 +176,16 @@ static int __maybe_unused komeda_pm_suspend(struct device *dev)
 static int __maybe_unused komeda_pm_resume(struct device *dev)
 {
        struct komeda_drv *mdrv = dev_get_drvdata(dev);
-       struct drm_device *drm = &mdrv->kms->base;
 
-       komeda_dev_resume(mdrv->mdev);
+       if (!pm_runtime_status_suspended(dev))
+               komeda_dev_resume(mdrv->mdev);
 
-       return drm_mode_config_helper_resume(drm);
+       return drm_mode_config_helper_resume(&mdrv->kms->base);
 }
 
 static const struct dev_pm_ops komeda_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(komeda_pm_suspend, komeda_pm_resume)
+       SET_RUNTIME_PM_OPS(komeda_rt_pm_suspend, komeda_rt_pm_resume, NULL)
 };
 
 static struct platform_driver komeda_platform_driver = {
index e30a5b43caa96cd283043cfca5f354f0d3ef4eeb..9a7dcf92591ab3001141cd9b334dd07492496a8b 100644 (file)
@@ -307,10 +307,6 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
        if (err)
                goto free_component_binding;
 
-       err = mdev->funcs->enable_irq(mdev);
-       if (err)
-               goto free_component_binding;
-
        drm->irq_enabled = true;
 
        drm_kms_helper_poll_init(drm);
@@ -324,7 +320,6 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
 free_interrupts:
        drm_kms_helper_poll_fini(drm);
        drm->irq_enabled = false;
-       mdev->funcs->disable_irq(mdev);
 free_component_binding:
        component_unbind_all(mdev->dev, drm);
 cleanup_mode_config:
@@ -346,7 +341,6 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
        drm_kms_helper_poll_fini(drm);
        drm_atomic_helper_shutdown(drm);
        drm->irq_enabled = false;
-       mdev->funcs->disable_irq(mdev);
        component_unbind_all(mdev->dev, drm);
        drm_mode_config_cleanup(drm);
        komeda_kms_cleanup_private_objs(kms);