mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
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: Philipp Zabel <p.zabel@pengutronix.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
c0ad88a9d8
commit
699e7e543f
3 changed files with 36 additions and 63 deletions
|
@ -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 = {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue