drm/imx: ipuv3-crtc: use drm managed resources
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>
This commit is contained in:
parent
699e7e543f
commit
16da8e9a77
@ -20,6 +20,7 @@
|
|||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_fb_cma_helper.h>
|
#include <drm/drm_fb_cma_helper.h>
|
||||||
#include <drm/drm_gem_cma_helper.h>
|
#include <drm/drm_gem_cma_helper.h>
|
||||||
|
#include <drm/drm_managed.h>
|
||||||
#include <drm/drm_probe_helper.h>
|
#include <drm/drm_probe_helper.h>
|
||||||
#include <drm/drm_vblank.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 = {
|
static const struct drm_crtc_funcs ipu_crtc_funcs = {
|
||||||
.set_config = drm_atomic_helper_set_config,
|
.set_config = drm_atomic_helper_set_config,
|
||||||
.destroy = drm_crtc_cleanup,
|
|
||||||
.page_flip = drm_atomic_helper_page_flip,
|
.page_flip = drm_atomic_helper_page_flip,
|
||||||
.reset = imx_drm_crtc_reset,
|
.reset = imx_drm_crtc_reset,
|
||||||
.atomic_duplicate_state = imx_drm_crtc_duplicate_state,
|
.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,
|
.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))
|
if (!IS_ERR_OR_NULL(ipu_crtc->dc))
|
||||||
ipu_dc_put(ipu_crtc->dc);
|
ipu_dc_put(ipu_crtc->dc);
|
||||||
if (!IS_ERR_OR_NULL(ipu_crtc->di))
|
if (!IS_ERR_OR_NULL(ipu_crtc->di))
|
||||||
ipu_di_put(ipu_crtc->di);
|
ipu_di_put(ipu_crtc->di);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
|
static int ipu_get_resources(struct drm_device *dev, struct ipu_crtc *ipu_crtc,
|
||||||
struct ipu_client_platformdata *pdata)
|
struct ipu_client_platformdata *pdata)
|
||||||
{
|
{
|
||||||
struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
|
struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc);
|
ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc);
|
||||||
if (IS_ERR(ipu_crtc->dc)) {
|
if (IS_ERR(ipu_crtc->dc))
|
||||||
ret = PTR_ERR(ipu_crtc->dc);
|
return PTR_ERR(ipu_crtc->dc);
|
||||||
goto err_out;
|
|
||||||
}
|
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);
|
ipu_crtc->di = ipu_di_get(ipu, pdata->di);
|
||||||
if (IS_ERR(ipu_crtc->di)) {
|
if (IS_ERR(ipu_crtc->di))
|
||||||
ret = PTR_ERR(ipu_crtc->di);
|
return PTR_ERR(ipu_crtc->di);
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err_out:
|
|
||||||
ipu_put_resources(ipu_crtc);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
|
static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
|
||||||
struct ipu_client_platformdata *pdata, struct drm_device *drm)
|
|
||||||
{
|
{
|
||||||
struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
|
struct ipu_client_platformdata *pdata = dev->platform_data;
|
||||||
struct drm_crtc *crtc = &ipu_crtc->base;
|
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 dp = -EINVAL;
|
||||||
int ret;
|
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)
|
if (pdata->dp >= 0)
|
||||||
dp = IPU_DP_FLOW_SYNC_BG;
|
dp = IPU_DP_FLOW_SYNC_BG;
|
||||||
ipu_crtc->plane[0] = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0,
|
primary_plane = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0,
|
||||||
DRM_PLANE_TYPE_PRIMARY);
|
DRM_PLANE_TYPE_PRIMARY);
|
||||||
if (IS_ERR(ipu_crtc->plane[0])) {
|
if (IS_ERR(primary_plane))
|
||||||
ret = PTR_ERR(ipu_crtc->plane[0]);
|
return PTR_ERR(primary_plane);
|
||||||
goto err_put_resources;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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;
|
crtc->port = pdata->of_node;
|
||||||
drm_crtc_helper_add(crtc, &ipu_helper_funcs);
|
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 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) {
|
||||||
@ -399,50 +406,21 @@ 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_resources;
|
return ret;
|
||||||
}
|
}
|
||||||
/* 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_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 = {
|
static const struct component_ops ipu_crtc_ops = {
|
||||||
.bind = ipu_drm_bind,
|
.bind = ipu_drm_bind,
|
||||||
.unbind = ipu_drm_unbind,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ipu_drm_probe(struct platform_device *pdev)
|
static int ipu_drm_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct ipu_crtc *ipu_crtc;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!dev->platform_data)
|
if (!dev->platform_data)
|
||||||
@ -452,12 +430,6 @@ static int ipu_drm_probe(struct platform_device *pdev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return 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);
|
return component_add(dev, &ipu_crtc_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user