2019-12-12 07:49:29

by James Qian Wang

[permalink] [raw]
Subject: [PATCH] drm/komeda: Add runtime_pm support

- 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) <[email protected]>
---
.../gpu/drm/arm/display/komeda/komeda_crtc.c | 3 +
.../gpu/drm/arm/display/komeda/komeda_dev.c | 55 +++++--------------
.../gpu/drm/arm/display/komeda/komeda_drv.c | 42 ++++++++++++--
.../gpu/drm/arm/display/komeda/komeda_kms.c | 6 --
4 files changed, 53 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
index 1c452ea75999..56bd938961ee 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
@@ -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
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
index 38b832804bad..1d767473ba8a 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
@@ -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;
}
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
index ad38bbc7431e..ea5cd1e17304 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
@@ -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 = {
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index e30a5b43caa9..9a7dcf92591a 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -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);
--
2.20.1


2019-12-23 13:03:36

by Mihail Atanassov

[permalink] [raw]
Subject: Re: [PATCH] drm/komeda: Add runtime_pm support

On Thursday, 12 December 2019 07:48:13 GMT james qian wang (Arm Technology China) wrote:
> - 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) <[email protected]>
> ---
> .../gpu/drm/arm/display/komeda/komeda_crtc.c | 3 +
> .../gpu/drm/arm/display/komeda/komeda_dev.c | 55 +++++--------------
> .../gpu/drm/arm/display/komeda/komeda_drv.c | 42 ++++++++++++--
> .../gpu/drm/arm/display/komeda/komeda_kms.c | 6 --
> 4 files changed, 53 insertions(+), 53 deletions(-)
>
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
> index 1c452ea75999..56bd938961ee 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
> @@ -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
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
> index 38b832804bad..1d767473ba8a 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c
> @@ -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;
> }
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
> index ad38bbc7431e..ea5cd1e17304 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
> @@ -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 = {
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> index e30a5b43caa9..9a7dcf92591a 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -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);
>

Reviewed-by: Mihail Atanassov <[email protected]>

--
Mihail