@@ -342,6 +342,7 @@ err_kms:
* imx_drm_add_crtc - add a new crtc
*/
int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
+ struct drm_plane *primary,
struct imx_drm_crtc **new_crtc,
const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
struct device_node *port)
@@ -380,7 +381,7 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
drm_crtc_helper_add(crtc,
imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
- drm_crtc_init(drm, crtc,
+ drm_crtc_init_with_planes(drm, crtc, primary, NULL,
imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
return 0;
@@ -24,6 +24,7 @@ struct imx_drm_crtc_helper_funcs {
};
int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
+ struct drm_plane *primary,
struct imx_drm_crtc **new_crtc,
const struct imx_drm_crtc_helper_funcs *imx_helper_funcs,
struct device_node *port);
@@ -84,7 +84,8 @@ struct ipu_crtc {
const struct ipu_channels *ch;
/* plane[0] is the full plane, plane[1] is the partial plane */
- struct ipu_plane *plane[2];
+ struct ipu_plane plane[2];
+ bool have_overlay; /* we have a partial plane */
struct ipu_dc *dc;
struct ipu_di *di;
@@ -106,7 +107,7 @@ static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)
return;
ipu_dc_enable(ipu_crtc->dc);
- ipu_plane_enable(ipu_crtc->plane[0]);
+ ipu_plane_enable(&ipu_crtc->plane[0]);
/* Start DC channel and DI after IDMAC */
ipu_dc_enable_channel(ipu_crtc->dc);
ipu_di_enable(ipu_crtc->di);
@@ -123,7 +124,7 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
/* Stop DC channel and DI before IDMAC */
ipu_dc_disable_channel(ipu_crtc->dc);
ipu_di_disable(ipu_crtc->di);
- ipu_plane_disable(ipu_crtc->plane[0]);
+ ipu_plane_disable(&ipu_crtc->plane[0]);
ipu_dc_disable(ipu_crtc->dc);
ipu_di_disable_clock(ipu_crtc->di);
@@ -241,7 +242,7 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
return ret;
}
- return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode,
+ return ipu_plane_mode_set(&ipu_crtc->plane[0], crtc, mode,
crtc->primary->fb,
0, 0, mode->hdisplay, mode->vdisplay,
x, y, mode->hdisplay, mode->vdisplay);
@@ -267,7 +268,7 @@ static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
imx_drm_handle_vblank(ipu_crtc->imx_crtc);
if (ipu_crtc->newfb) {
- struct ipu_plane *plane = ipu_crtc->plane[0];
+ struct ipu_plane *plane = &ipu_crtc->plane[0];
ipu_crtc->newfb = NULL;
ipu_plane_set_base(plane, ipu_crtc->base.primary->fb,
@@ -474,20 +475,27 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
return ret;
}
- ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc,
- &ipu_crtc_helper_funcs, ipu_crtc->port);
+ ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->plane[0].base,
+ &ipu_crtc->imx_crtc, &ipu_crtc_helper_funcs,
+ ipu_crtc->port);
if (ret) {
dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
goto err_put_resources;
}
id = imx_drm_crtc_id(ipu_crtc->imx_crtc);
- ipu_crtc->plane[0] = ipu_plane_init(ipu_crtc->base.dev,
- ipu_crtc->ipu,
- ipu_crtc->ch->dma[0],
- ipu_crtc->ch->dp[0],
- BIT(id), true);
- ret = ipu_plane_get_resources(ipu_crtc->plane[0]);
+ ret = ipu_plane_init(&ipu_crtc->plane[0], drm,
+ ipu_crtc->ipu,
+ ipu_crtc->ch->dma[0],
+ ipu_crtc->ch->dp[0],
+ BIT(id), true);
+ if (ret) {
+ dev_err(ipu_crtc->dev, "init primary plane failed with %d\n",
+ ret);
+ goto err_remove_crtc;
+ }
+
+ 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);
@@ -496,16 +504,16 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
/* If this crtc is using the DP, add an overlay plane */
if (ipu_crtc->ch->dp[1] >= 0) {
- ipu_crtc->plane[1] = ipu_plane_init(ipu_crtc->base.dev,
- ipu_crtc->ipu,
- ipu_crtc->ch->dma[1],
- ipu_crtc->ch->dp[1],
- BIT(id), false);
- if (IS_ERR(ipu_crtc->plane[1]))
- ipu_crtc->plane[1] = NULL;
+ ret = ipu_plane_init(&ipu_crtc->plane[1], drm,
+ ipu_crtc->ipu,
+ ipu_crtc->ch->dma[1],
+ ipu_crtc->ch->dp[1],
+ BIT(id), false);
+
+ ipu_crtc->have_overlay = ret ? false : true;
}
- ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
+ ipu_crtc->irq = ipu_plane_irq(&ipu_crtc->plane[0]);
ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
"imx_drm", ipu_crtc);
if (ret < 0) {
@@ -516,7 +524,7 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
return 0;
err_put_plane_res:
- ipu_plane_put_resources(ipu_crtc->plane[0]);
+ ipu_plane_put_resources(&ipu_crtc->plane[0]);
err_remove_crtc:
imx_drm_remove_crtc(ipu_crtc->imx_crtc);
err_put_resources:
@@ -553,7 +561,7 @@ static void ipu_drm_unbind(struct device *dev, struct device *master,
imx_drm_remove_crtc(ipu_crtc->imx_crtc);
- ipu_plane_put_resources(ipu_crtc->plane[0]);
+ ipu_plane_put_resources(&ipu_crtc->plane[0]);
ipu_put_resources(ipu_crtc);
}
@@ -338,13 +338,10 @@ static int ipu_disable_plane(struct drm_plane *plane)
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__);
ipu_disable_plane(plane);
drm_plane_cleanup(plane);
- kfree(ipu_plane);
}
static int ipu_plane_set_global_alpha(struct ipu_plane *ipu_plane,
@@ -426,22 +423,15 @@ static struct drm_plane_funcs ipu_plane_funcs = {
.set_property = ipu_plane_set_property,
};
-struct ipu_plane *ipu_plane_init(struct drm_device *drm, struct ipu_soc *ipu,
- int dma, int dp, unsigned int possible_crtcs,
- bool priv)
+int ipu_plane_init(struct ipu_plane *ipu_plane, struct drm_device *drm,
+ struct ipu_soc *ipu, int dma, int dp,
+ unsigned int possible_crtcs, bool priv)
{
- struct ipu_plane *ipu_plane;
int ret;
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->ipu = ipu;
ipu_plane->dma = dma;
ipu_plane->dp_flow = dp;
@@ -452,7 +442,7 @@ struct ipu_plane *ipu_plane_init(struct drm_device *drm, struct ipu_soc *ipu,
priv);
if (ret) {
DRM_ERROR("failed to initialize plane\n");
- goto err_free;
+ return ret;
}
/* default global alpha is enabled and completely opaque */
@@ -461,7 +451,7 @@ struct ipu_plane *ipu_plane_init(struct drm_device *drm, struct ipu_soc *ipu,
/* for private planes, skip setting up properties */
if (priv)
- return ipu_plane;
+ return 0;
/*
* global alpha range is 0 - 255. Bit 8 is used as a
@@ -472,8 +462,7 @@ struct ipu_plane *ipu_plane_init(struct drm_device *drm, struct ipu_soc *ipu,
0, 0x1ff);
if (!ipu_plane->global_alpha_prop) {
DRM_ERROR("failed to create global alpha property\n");
- ret = -ENOMEM;
- goto err_free;
+ return -ENOMEM;
}
/*
@@ -485,8 +474,7 @@ struct ipu_plane *ipu_plane_init(struct drm_device *drm, struct ipu_soc *ipu,
0, 0x01ffffff);
if (!ipu_plane->colorkey_prop) {
DRM_ERROR("failed to create colorkey property\n");
- ret = -ENOMEM;
- goto err_free;
+ return -ENOMEM;
}
drm_object_attach_property(&ipu_plane->base.base,
@@ -495,9 +483,5 @@ struct ipu_plane *ipu_plane_init(struct drm_device *drm, struct ipu_soc *ipu,
drm_object_attach_property(&ipu_plane->base.base,
ipu_plane->colorkey_prop,
0);
- return ipu_plane;
-
-err_free:
- kfree(ipu_plane);
- return ERR_PTR(ret);
+ return 0;
}
@@ -37,9 +37,9 @@ struct ipu_plane {
bool enabled;
};
-struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
- int dma, int dp, unsigned int possible_crtcs,
- bool priv);
+int ipu_plane_init(struct ipu_plane *ipu_plane, struct drm_device *drm,
+ struct ipu_soc *ipu, int dma, int dp,
+ unsigned int possible_crtcs, bool priv);
/* Init IDMAC, DMFC, DP */
int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc,
drm_crtc_init() will create a primary plane object, while imx-drm also creates its own, thus two primary planes are separately created, and can cause difficult bugs to track down in the future. Fix by using drm_crtc_init_with_planes() instead of drm_crtc_init(), so that we can hand drm our own primary plane object, thus crtc->primary and ipu_crtc->plane[0].base now are the same object. To do this we need to statically declare the primary and overlay planes in the crtc driver, to avoid a chicken-before-the-egg problem, the primary plane must exist when imx_drm_add_crtc() is called but before ipu_plane_init(). Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com> --- drivers/staging/imx-drm/imx-drm-core.c | 3 +- drivers/staging/imx-drm/imx-drm.h | 1 + drivers/staging/imx-drm/ipuv3-crtc.c | 54 ++++++++++++++++++-------------- drivers/staging/imx-drm/ipuv3-plane.c | 32 +++++-------------- drivers/staging/imx-drm/ipuv3-plane.h | 6 ++-- 5 files changed, 45 insertions(+), 51 deletions(-)