OSDN Git Service

drm/imx: ipuv3-plane: use drm managed resources
authorPhilipp Zabel <p.zabel@pengutronix.de>
Thu, 10 Dec 2020 15:38:44 +0000 (16:38 +0100)
committerPhilipp Zabel <p.zabel@pengutronix.de>
Mon, 4 Jan 2021 11:59:34 +0000 (12:59 +0100)
Use drmm_universal_plane_alloc() to align plane memory lifetime with
the drm device. drm_plane_cleanup() is called automatically before the
memory is freed.
Also move the call to ipu_plane_get_resources() into ipu_plane_init()
and use drm managed resources to put IPU resources automatically when
required. Handle error return values of the plane property creation
functions.

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

index 7ebd99e..6ce8fa4 100644 (file)
@@ -384,29 +384,14 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
        drm_crtc_init_with_planes(drm, crtc, &ipu_crtc->plane[0]->base, NULL,
                                  &ipu_crtc_funcs, NULL);
 
-       ret = ipu_plane_get_resources(ipu_crtc->plane[0]);
-       if (ret) {
-               dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n",
-                       ret);
-               goto err_put_resources;
-       }
-
        /* If this crtc is using the DP, add an overlay plane */
        if (pdata->dp >= 0 && pdata->dma[1] > 0) {
                ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1],
                                                IPU_DP_FLOW_SYNC_FG,
                                                drm_crtc_mask(&ipu_crtc->base),
                                                DRM_PLANE_TYPE_OVERLAY);
-               if (IS_ERR(ipu_crtc->plane[1])) {
+               if (IS_ERR(ipu_crtc->plane[1]))
                        ipu_crtc->plane[1] = NULL;
-               } else {
-                       ret = ipu_plane_get_resources(ipu_crtc->plane[1]);
-                       if (ret) {
-                               dev_err(ipu_crtc->dev, "getting plane 1 "
-                                       "resources failed with %d.\n", ret);
-                               goto err_put_plane0_res;
-                       }
-               }
        }
 
        ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
@@ -414,18 +399,13 @@ 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_plane1_res;
+               goto err_put_resources;
        }
        /* Only enable IRQ when we actually need it to trigger work. */
        disable_irq(ipu_crtc->irq);
 
        return 0;
 
-err_put_plane1_res:
-       if (ipu_crtc->plane[1])
-               ipu_plane_put_resources(ipu_crtc->plane[1]);
-err_put_plane0_res:
-       ipu_plane_put_resources(ipu_crtc->plane[0]);
 err_put_resources:
        ipu_put_resources(ipu_crtc);
 
@@ -452,9 +432,6 @@ static void ipu_drm_unbind(struct device *dev, struct device *master,
        struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev);
 
        ipu_put_resources(ipu_crtc);
-       if (ipu_crtc->plane[1])
-               ipu_plane_put_resources(ipu_crtc->plane[1]);
-       ipu_plane_put_resources(ipu_crtc->plane[0]);
 }
 
 static const struct component_ops ipu_crtc_ops = {
index 8a4235d..0755080 100644 (file)
@@ -11,6 +11,7 @@
 #include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_managed.h>
 #include <drm/drm_plane_helper.h>
 
 #include <video/imx-ipu-v3.h>
@@ -142,8 +143,10 @@ drm_plane_state_to_vbo(struct drm_plane_state *state)
               fb->format->cpp[2] * x - eba;
 }
 
-void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
+static void ipu_plane_put_resources(struct drm_device *dev, void *ptr)
 {
+       struct ipu_plane *ipu_plane = ptr;
+
        if (!IS_ERR_OR_NULL(ipu_plane->dp))
                ipu_dp_put(ipu_plane->dp);
        if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
@@ -154,7 +157,8 @@ void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
                ipu_idmac_put(ipu_plane->alpha_ch);
 }
 
-int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
+static int ipu_plane_get_resources(struct drm_device *dev,
+                                  struct ipu_plane *ipu_plane)
 {
        int ret;
        int alpha_ch;
@@ -166,6 +170,10 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
                return ret;
        }
 
+       ret = drmm_add_action_or_reset(dev, ipu_plane_put_resources, ipu_plane);
+       if (ret)
+               return ret;
+
        alpha_ch = ipu_channel_alpha_channel(ipu_plane->dma);
        if (alpha_ch >= 0) {
                ipu_plane->alpha_ch = ipu_idmac_get(ipu_plane->ipu, alpha_ch);
@@ -181,7 +189,7 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
        if (IS_ERR(ipu_plane->dmfc)) {
                ret = PTR_ERR(ipu_plane->dmfc);
                DRM_ERROR("failed to get dmfc: ret %d\n", ret);
-               goto err_out;
+               return ret;
        }
 
        if (ipu_plane->dp_flow >= 0) {
@@ -189,15 +197,11 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
                if (IS_ERR(ipu_plane->dp)) {
                        ret = PTR_ERR(ipu_plane->dp);
                        DRM_ERROR("failed to get dp flow: %d\n", ret);
-                       goto err_out;
+                       return ret;
                }
        }
 
        return 0;
-err_out:
-       ipu_plane_put_resources(ipu_plane);
-
-       return ret;
 }
 
 static bool ipu_plane_separate_alpha(struct ipu_plane *ipu_plane)
@@ -262,16 +266,6 @@ void ipu_plane_disable_deferred(struct drm_plane *plane)
 }
 EXPORT_SYMBOL_GPL(ipu_plane_disable_deferred);
 
-static void ipu_plane_destroy(struct drm_plane *plane)
-{
-       struct ipu_plane *ipu_plane = to_ipu_plane(plane);
-
-       DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
-
-       drm_plane_cleanup(plane);
-       kfree(ipu_plane);
-}
-
 static void ipu_plane_state_reset(struct drm_plane *plane)
 {
        unsigned int zpos = (plane->type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1;
@@ -336,7 +330,6 @@ static bool ipu_plane_format_mod_supported(struct drm_plane *plane,
 static const struct drm_plane_funcs ipu_plane_funcs = {
        .update_plane   = drm_atomic_helper_update_plane,
        .disable_plane  = drm_atomic_helper_disable_plane,
-       .destroy        = ipu_plane_destroy,
        .reset          = ipu_plane_state_reset,
        .atomic_duplicate_state = ipu_plane_duplicate_state,
        .atomic_destroy_state   = ipu_plane_destroy_state,
@@ -834,10 +827,15 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
        DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
                      dma, dp, possible_crtcs);
 
-       ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL);
-       if (!ipu_plane) {
-               DRM_ERROR("failed to allocate plane\n");
-               return ERR_PTR(-ENOMEM);
+       ipu_plane = drmm_universal_plane_alloc(dev, struct ipu_plane, base,
+                                              possible_crtcs, &ipu_plane_funcs,
+                                              ipu_plane_formats,
+                                              ARRAY_SIZE(ipu_plane_formats),
+                                              modifiers, type, NULL);
+       if (IS_ERR(ipu_plane)) {
+               DRM_ERROR("failed to allocate and initialize %s plane\n",
+                         zpos ? "overlay" : "primary");
+               return ipu_plane;
        }
 
        ipu_plane->ipu = ipu;
@@ -847,22 +845,23 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
        if (ipu_prg_present(ipu))
                modifiers = pre_format_modifiers;
 
-       ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
-                                      &ipu_plane_funcs, ipu_plane_formats,
-                                      ARRAY_SIZE(ipu_plane_formats),
-                                      modifiers, type, NULL);
-       if (ret) {
-               DRM_ERROR("failed to initialize plane\n");
-               kfree(ipu_plane);
-               return ERR_PTR(ret);
-       }
-
        drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
 
        if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG)
-               drm_plane_create_zpos_property(&ipu_plane->base, zpos, 0, 1);
+               ret = drm_plane_create_zpos_property(&ipu_plane->base, zpos, 0,
+                                                    1);
        else
-               drm_plane_create_zpos_immutable_property(&ipu_plane->base, 0);
+               ret = drm_plane_create_zpos_immutable_property(&ipu_plane->base,
+                                                              0);
+       if (ret)
+               return ERR_PTR(ret);
+
+       ret = ipu_plane_get_resources(dev, ipu_plane);
+       if (ret) {
+               DRM_ERROR("failed to get %s plane resources: %pe\n",
+                         zpos ? "overlay" : "primary", &ret);
+               return ERR_PTR(ret);
+       }
 
        return ipu_plane;
 }
index ffacbcd..6d544e6 100644 (file)
@@ -41,9 +41,6 @@ int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc,
                       uint32_t src_x, uint32_t src_y, uint32_t src_w,
                       uint32_t src_h, bool interlaced);
 
-int ipu_plane_get_resources(struct ipu_plane *plane);
-void ipu_plane_put_resources(struct ipu_plane *plane);
-
 int ipu_plane_irq(struct ipu_plane *plane);
 
 void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel);