Commit efb46508 authored by james qian wang (Arm Technology China)'s avatar james qian wang (Arm Technology China)
Browse files

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: default avatarjames qian wang (Arm Technology China) <james.qian.wang@arm.com>
Reviewed-by: default avatarMihail Atanassov <mihail.atanassov@arm.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191212074756.14678-1-james.qian.wang@arm.com
parent 8f902dbd
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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
+14 −41
Original line number Diff line number Diff line
@@ -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;
}
+36 −6
Original line number Diff line number Diff line
@@ -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,14 +146,28 @@ 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);

	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;

	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 = {
+0 −6
Original line number Diff line number Diff line
@@ -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);