[PATCH 1/2] drm/omap: Add PM capabilities
Rob Clark
rob at ti.com
Tue Dec 18 16:18:08 PST 2012
On Tue, Dec 18, 2012 at 12:02 AM, Andy Gross <andy.gross at ti.com> wrote:
> 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>
I am sort of thinking it might be worth a comment somewhere explaining
why this works (ie. resume order between the two platform devices),
even if only in the commit msg. But with that:
Signed-off-by: Rob Clark <rob 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
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
More information about the dri-devel
mailing list