[PATCH 1/2] drm/omap: Add PM capabilities

Andy Gross andy.gross at ti.com
Mon Dec 17 22:02:43 PST 2012


Added resume hooks that will be called on resuming from DEVICE_OFF.
The dmm portion of the patch reprograms the LUT to point to the dummy
pages.  The omapdrm portion of the patch repins the buffers into the
DMM.

Signed-off-by: Andy Gross <andy.gross at ti.com>
---
 drivers/staging/omapdrm/omap_dmm_tiler.c |   34 ++++++++++++++++++++++++++++++
 drivers/staging/omapdrm/omap_drv.c       |   14 ++++++++++++
 drivers/staging/omapdrm/omap_drv.h       |    4 +++
 drivers/staging/omapdrm/omap_gem.c       |   28 ++++++++++++++++++++++++
 4 files changed, 80 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c
index 59bf438..c42c5e5 100644
--- a/drivers/staging/omapdrm/omap_dmm_tiler.c
+++ b/drivers/staging/omapdrm/omap_dmm_tiler.c
@@ -903,12 +903,46 @@ error:
 }
 #endif
 
+#ifdef CONFIG_PM
+static int omap_dmm_resume(struct device *dev)
+{
+	struct tcm_area area;
+	int i;
+
+	if (!omap_dmm)
+		return -ENODEV;
+
+	area = (struct tcm_area) {
+		.is2d = true,
+		.tcm = NULL,
+		.p1.x = omap_dmm->container_width - 1,
+		.p1.y = omap_dmm->container_height - 1,
+	};
+
+	/* initialize all LUTs to dummy page entries */
+	for (i = 0; i < omap_dmm->num_lut; i++) {
+		area.tcm = omap_dmm->tcm[i];
+		if (fill(&area, NULL, 0, 0, true))
+			dev_err(dev, "refill failed");
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops omap_dmm_pm_ops = {
+	.resume = omap_dmm_resume,
+};
+#endif
+
 struct platform_driver omap_dmm_driver = {
 	.probe = omap_dmm_probe,
 	.remove = omap_dmm_remove,
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = DMM_DRIVER_NAME,
+#ifdef CONFIG_PM
+		.pm = &omap_dmm_pm_ops,
+#endif
 	},
 };
 
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
index ae5ecc2..d246f85 100644
--- a/drivers/staging/omapdrm/omap_drv.c
+++ b/drivers/staging/omapdrm/omap_drv.c
@@ -368,6 +368,9 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
 		/* well, limp along without an fbdev.. maybe X11 will work? */
 	}
 
+	/* store off drm_device for use in pm ops */
+	dev_set_drvdata(dev->dev, dev);
+
 	drm_kms_helper_poll_init(dev);
 
 	return 0;
@@ -393,6 +396,8 @@ static int dev_unload(struct drm_device *dev)
 	kfree(dev->dev_private);
 	dev->dev_private = NULL;
 
+	dev_set_drvdata(dev->dev, NULL);
+
 	return 0;
 }
 
@@ -558,10 +563,19 @@ static int pdev_remove(struct platform_device *device)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static const struct dev_pm_ops omapdrm_pm_ops = {
+	.resume = omap_gem_resume,
+};
+#endif
+
 struct platform_driver pdev = {
 		.driver = {
 			.name = DRIVER_NAME,
 			.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+			.pm = &omapdrm_pm_ops,
+#endif
 		},
 		.probe = pdev_probe,
 		.remove = pdev_remove,
diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h
index cd1f22b..f921027 100644
--- a/drivers/staging/omapdrm/omap_drv.h
+++ b/drivers/staging/omapdrm/omap_drv.h
@@ -135,6 +135,10 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m);
 void omap_gem_describe_objects(struct list_head *list, struct seq_file *m);
 #endif
 
+#ifdef CONFIG_PM
+int omap_gem_resume(struct device *dev);
+#endif
+
 int omap_irq_enable_vblank(struct drm_device *dev, int crtc);
 void omap_irq_disable_vblank(struct drm_device *dev, int crtc);
 irqreturn_t omap_irq_handler(DRM_IRQ_ARGS);
diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c
index c38992b..08f1e292 100644
--- a/drivers/staging/omapdrm/omap_gem.c
+++ b/drivers/staging/omapdrm/omap_gem.c
@@ -964,6 +964,34 @@ void *omap_gem_vaddr(struct drm_gem_object *obj)
 	return omap_obj->vaddr;
 }
 
+#ifdef CONFIG_PM
+/* re-pin objects in DMM in resume path: */
+int omap_gem_resume(struct device *dev)
+{
+	struct drm_device *drm_dev = dev_get_drvdata(dev);
+	struct omap_drm_private *priv = drm_dev->dev_private;
+	struct omap_gem_object *omap_obj;
+	int ret = 0;
+
+	list_for_each_entry(omap_obj, &priv->obj_list, mm_list) {
+		if (omap_obj->block) {
+			struct drm_gem_object *obj = &omap_obj->base;
+			uint32_t npages = obj->size >> PAGE_SHIFT;
+			WARN_ON(!omap_obj->pages);  /* this can't happen */
+			ret = tiler_pin(omap_obj->block,
+					omap_obj->pages, npages,
+					omap_obj->roll, true);
+			if (ret) {
+				dev_err(dev, "could not repin: %d\n", ret);
+				return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_DEBUG_FS
 void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 {
-- 
1.7.5.4



More information about the dri-devel mailing list