drm/imx: ipuv3-crtc: use drm managed resources
authorPhilipp Zabel <p.zabel@pengutronix.de>
Thu, 10 Dec 2020 15:38:45 +0000 (16:38 +0100)
committerPhilipp Zabel <p.zabel@pengutronix.de>
Mon, 4 Jan 2021 11:59:34 +0000 (12:59 +0100)
Use use drmm_crtc_alloc_with_planes() to align crtc memory lifetime
with the drm device. drm_crtc_cleanup() is called automatically before
the memory is freed.
Also use drmm_add_action_or_reset() to make sure IPU resources are
released automatically.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/imx/ipuv3-crtc.c

index 6ce8fa4348c989a7cae1aa1774c1e591773ca3aa..e6431a227feb17f7cce698593afa7fd2f9ca908e 100644 (file)
@@ -20,6 +20,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_managed.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 
@@ -163,7 +164,6 @@ static void ipu_disable_vblank(struct drm_crtc *crtc)
 
 static const struct drm_crtc_funcs ipu_crtc_funcs = {
        .set_config = drm_atomic_helper_set_config,
-       .destroy = drm_crtc_cleanup,
        .page_flip = drm_atomic_helper_page_flip,
        .reset = imx_drm_crtc_reset,
        .atomic_duplicate_state = imx_drm_crtc_duplicate_state,
@@ -322,67 +322,74 @@ static const struct drm_crtc_helper_funcs ipu_helper_funcs = {
        .atomic_enable = ipu_crtc_atomic_enable,
 };
 
-static void ipu_put_resources(struct ipu_crtc *ipu_crtc)
+static void ipu_put_resources(struct drm_device *dev, void *ptr)
 {
+       struct ipu_crtc *ipu_crtc = ptr;
+
        if (!IS_ERR_OR_NULL(ipu_crtc->dc))
                ipu_dc_put(ipu_crtc->dc);
        if (!IS_ERR_OR_NULL(ipu_crtc->di))
                ipu_di_put(ipu_crtc->di);
 }
 
-static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
-               struct ipu_client_platformdata *pdata)
+static int ipu_get_resources(struct drm_device *dev, struct ipu_crtc *ipu_crtc,
+                            struct ipu_client_platformdata *pdata)
 {
        struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
        int ret;
 
        ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc);
-       if (IS_ERR(ipu_crtc->dc)) {
-               ret = PTR_ERR(ipu_crtc->dc);
-               goto err_out;
-       }
+       if (IS_ERR(ipu_crtc->dc))
+               return PTR_ERR(ipu_crtc->dc);
+
+       ret = drmm_add_action_or_reset(dev, ipu_put_resources, ipu_crtc);
+       if (ret)
+               return ret;
 
        ipu_crtc->di = ipu_di_get(ipu, pdata->di);
-       if (IS_ERR(ipu_crtc->di)) {
-               ret = PTR_ERR(ipu_crtc->di);
-               goto err_out;
-       }
+       if (IS_ERR(ipu_crtc->di))
+               return PTR_ERR(ipu_crtc->di);
 
        return 0;
-err_out:
-       ipu_put_resources(ipu_crtc);
-
-       return ret;
 }
 
-static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
-       struct ipu_client_platformdata *pdata, struct drm_device *drm)
+static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
 {
-       struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
-       struct drm_crtc *crtc = &ipu_crtc->base;
+       struct ipu_client_platformdata *pdata = dev->platform_data;
+       struct ipu_soc *ipu = dev_get_drvdata(dev->parent);
+       struct drm_device *drm = data;
+       struct ipu_plane *primary_plane;
+       struct ipu_crtc *ipu_crtc;
+       struct drm_crtc *crtc;
        int dp = -EINVAL;
        int ret;
 
-       ret = ipu_get_resources(ipu_crtc, pdata);
-       if (ret) {
-               dev_err(ipu_crtc->dev, "getting resources failed with %d.\n",
-                               ret);
-               return ret;
-       }
-
        if (pdata->dp >= 0)
                dp = IPU_DP_FLOW_SYNC_BG;
-       ipu_crtc->plane[0] = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0,
-                                           DRM_PLANE_TYPE_PRIMARY);
-       if (IS_ERR(ipu_crtc->plane[0])) {
-               ret = PTR_ERR(ipu_crtc->plane[0]);
-               goto err_put_resources;
-       }
+       primary_plane = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0,
+                                      DRM_PLANE_TYPE_PRIMARY);
+       if (IS_ERR(primary_plane))
+               return PTR_ERR(primary_plane);
+
+       ipu_crtc = drmm_crtc_alloc_with_planes(drm, struct ipu_crtc, base,
+                                              &primary_plane->base, NULL,
+                                              &ipu_crtc_funcs, NULL);
+       if (IS_ERR(ipu_crtc))
+               return PTR_ERR(ipu_crtc);
+
+       ipu_crtc->dev = dev;
+       ipu_crtc->plane[0] = primary_plane;
 
+       crtc = &ipu_crtc->base;
        crtc->port = pdata->of_node;
        drm_crtc_helper_add(crtc, &ipu_helper_funcs);
-       drm_crtc_init_with_planes(drm, crtc, &ipu_crtc->plane[0]->base, NULL,
-                                 &ipu_crtc_funcs, NULL);
+
+       ret = ipu_get_resources(drm, ipu_crtc, pdata);
+       if (ret) {
+               dev_err(ipu_crtc->dev, "getting resources failed with %d.\n",
+                       ret);
+               return ret;
+       }
 
        /* If this crtc is using the DP, add an overlay plane */
        if (pdata->dp >= 0 && pdata->dma[1] > 0) {
@@ -399,50 +406,21 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
                        "imx_drm", ipu_crtc);
        if (ret < 0) {
                dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
-               goto err_put_resources;
+               return ret;
        }
        /* Only enable IRQ when we actually need it to trigger work. */
        disable_irq(ipu_crtc->irq);
 
        return 0;
-
-err_put_resources:
-       ipu_put_resources(ipu_crtc);
-
-       return ret;
-}
-
-static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
-{
-       struct ipu_client_platformdata *pdata = dev->platform_data;
-       struct drm_device *drm = data;
-       struct ipu_crtc *ipu_crtc;
-
-       ipu_crtc = dev_get_drvdata(dev);
-       memset(ipu_crtc, 0, sizeof(*ipu_crtc));
-
-       ipu_crtc->dev = dev;
-
-       return ipu_crtc_init(ipu_crtc, pdata, drm);
-}
-
-static void ipu_drm_unbind(struct device *dev, struct device *master,
-       void *data)
-{
-       struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev);
-
-       ipu_put_resources(ipu_crtc);
 }
 
 static const struct component_ops ipu_crtc_ops = {
        .bind = ipu_drm_bind,
-       .unbind = ipu_drm_unbind,
 };
 
 static int ipu_drm_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct ipu_crtc *ipu_crtc;
        int ret;
 
        if (!dev->platform_data)
@@ -452,12 +430,6 @@ static int ipu_drm_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL);
-       if (!ipu_crtc)
-               return -ENOMEM;
-
-       dev_set_drvdata(dev, ipu_crtc);
-
        return component_add(dev, &ipu_crtc_ops);
 }