Commit 699e7e54 authored by Philipp Zabel's avatar Philipp Zabel

drm/imx: ipuv3-plane: use drm managed resources

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: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent c0ad88a9
...@@ -384,29 +384,14 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, ...@@ -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, drm_crtc_init_with_planes(drm, crtc, &ipu_crtc->plane[0]->base, NULL,
&ipu_crtc_funcs, 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 this crtc is using the DP, add an overlay plane */
if (pdata->dp >= 0 && pdata->dma[1] > 0) { if (pdata->dp >= 0 && pdata->dma[1] > 0) {
ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1], ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1],
IPU_DP_FLOW_SYNC_FG, IPU_DP_FLOW_SYNC_FG,
drm_crtc_mask(&ipu_crtc->base), drm_crtc_mask(&ipu_crtc->base),
DRM_PLANE_TYPE_OVERLAY); DRM_PLANE_TYPE_OVERLAY);
if (IS_ERR(ipu_crtc->plane[1])) { if (IS_ERR(ipu_crtc->plane[1]))
ipu_crtc->plane[1] = NULL; 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]); ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
...@@ -414,18 +399,13 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, ...@@ -414,18 +399,13 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
"imx_drm", ipu_crtc); "imx_drm", ipu_crtc);
if (ret < 0) { if (ret < 0) {
dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret); 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. */ /* Only enable IRQ when we actually need it to trigger work. */
disable_irq(ipu_crtc->irq); disable_irq(ipu_crtc->irq);
return 0; 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: err_put_resources:
ipu_put_resources(ipu_crtc); ipu_put_resources(ipu_crtc);
...@@ -452,9 +432,6 @@ static void ipu_drm_unbind(struct device *dev, struct device *master, ...@@ -452,9 +432,6 @@ static void ipu_drm_unbind(struct device *dev, struct device *master,
struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev); struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev);
ipu_put_resources(ipu_crtc); 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 = { static const struct component_ops ipu_crtc_ops = {
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_plane_helper.h> #include <drm/drm_plane_helper.h>
#include <video/imx-ipu-v3.h> #include <video/imx-ipu-v3.h>
...@@ -142,8 +143,10 @@ drm_plane_state_to_vbo(struct drm_plane_state *state) ...@@ -142,8 +143,10 @@ drm_plane_state_to_vbo(struct drm_plane_state *state)
fb->format->cpp[2] * x - eba; 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)) if (!IS_ERR_OR_NULL(ipu_plane->dp))
ipu_dp_put(ipu_plane->dp); ipu_dp_put(ipu_plane->dp);
if (!IS_ERR_OR_NULL(ipu_plane->dmfc)) if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
...@@ -154,7 +157,8 @@ void ipu_plane_put_resources(struct ipu_plane *ipu_plane) ...@@ -154,7 +157,8 @@ void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
ipu_idmac_put(ipu_plane->alpha_ch); 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 ret;
int alpha_ch; int alpha_ch;
...@@ -166,6 +170,10 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane) ...@@ -166,6 +170,10 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
return ret; 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); alpha_ch = ipu_channel_alpha_channel(ipu_plane->dma);
if (alpha_ch >= 0) { if (alpha_ch >= 0) {
ipu_plane->alpha_ch = ipu_idmac_get(ipu_plane->ipu, alpha_ch); 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) ...@@ -181,7 +189,7 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
if (IS_ERR(ipu_plane->dmfc)) { if (IS_ERR(ipu_plane->dmfc)) {
ret = PTR_ERR(ipu_plane->dmfc); ret = PTR_ERR(ipu_plane->dmfc);
DRM_ERROR("failed to get dmfc: ret %d\n", ret); DRM_ERROR("failed to get dmfc: ret %d\n", ret);
goto err_out; return ret;
} }
if (ipu_plane->dp_flow >= 0) { if (ipu_plane->dp_flow >= 0) {
...@@ -189,15 +197,11 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane) ...@@ -189,15 +197,11 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
if (IS_ERR(ipu_plane->dp)) { if (IS_ERR(ipu_plane->dp)) {
ret = PTR_ERR(ipu_plane->dp); ret = PTR_ERR(ipu_plane->dp);
DRM_ERROR("failed to get dp flow: %d\n", ret); DRM_ERROR("failed to get dp flow: %d\n", ret);
goto err_out; return ret;
} }
} }
return 0; return 0;
err_out:
ipu_plane_put_resources(ipu_plane);
return ret;
} }
static bool ipu_plane_separate_alpha(struct ipu_plane *ipu_plane) static bool ipu_plane_separate_alpha(struct ipu_plane *ipu_plane)
...@@ -262,16 +266,6 @@ void ipu_plane_disable_deferred(struct drm_plane *plane) ...@@ -262,16 +266,6 @@ void ipu_plane_disable_deferred(struct drm_plane *plane)
} }
EXPORT_SYMBOL_GPL(ipu_plane_disable_deferred); 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) static void ipu_plane_state_reset(struct drm_plane *plane)
{ {
unsigned int zpos = (plane->type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1; 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, ...@@ -336,7 +330,6 @@ static bool ipu_plane_format_mod_supported(struct drm_plane *plane,
static const struct drm_plane_funcs ipu_plane_funcs = { static const struct drm_plane_funcs ipu_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane, .update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane, .disable_plane = drm_atomic_helper_disable_plane,
.destroy = ipu_plane_destroy,
.reset = ipu_plane_state_reset, .reset = ipu_plane_state_reset,
.atomic_duplicate_state = ipu_plane_duplicate_state, .atomic_duplicate_state = ipu_plane_duplicate_state,
.atomic_destroy_state = ipu_plane_destroy_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, ...@@ -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", DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
dma, dp, possible_crtcs); dma, dp, possible_crtcs);
ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL); ipu_plane = drmm_universal_plane_alloc(dev, struct ipu_plane, base,
if (!ipu_plane) { possible_crtcs, &ipu_plane_funcs,
DRM_ERROR("failed to allocate plane\n"); ipu_plane_formats,
return ERR_PTR(-ENOMEM); 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; ipu_plane->ipu = ipu;
...@@ -847,22 +845,23 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, ...@@ -847,22 +845,23 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
if (ipu_prg_present(ipu)) if (ipu_prg_present(ipu))
modifiers = pre_format_modifiers; 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); drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG) 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 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; return ipu_plane;
} }
...@@ -41,9 +41,6 @@ int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc, ...@@ -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_x, uint32_t src_y, uint32_t src_w,
uint32_t src_h, bool interlaced); 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); int ipu_plane_irq(struct ipu_plane *plane);
void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel); void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment