提交 43895599 编写于 作者: P Philipp Zabel

drm/imx: switch to universal planes

Use drm_universal_plane_init to create the planes, create the primary
plane first and use drm_crtc_init_with_planes to associate it with
the crtc.
This gets rid of the unused fallback primary plane previously created
by drm_crtc_init and fixes a NULL pointer dereference issue that can
be triggered by a modeset from userspace when fbdev helpers are
enabled [1].

[1] https://lkml.org/lkml/2015/11/4/107Reported-by: NLiu Ying <Ying.Liu@freescale.com>
Signed-off-by: NPhilipp Zabel <p.zabel@pengutronix.de>
Acked-by: NLiu Ying <Ying.Liu@freescale.com>
上级 8005c49d
...@@ -340,7 +340,7 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) ...@@ -340,7 +340,7 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
* imx_drm_add_crtc - add a new crtc * imx_drm_add_crtc - add a new crtc
*/ */
int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
struct imx_drm_crtc **new_crtc, struct imx_drm_crtc **new_crtc, struct drm_plane *primary_plane,
const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs, const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
struct device_node *port) struct device_node *port)
{ {
...@@ -379,7 +379,7 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, ...@@ -379,7 +379,7 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
drm_crtc_helper_add(crtc, drm_crtc_helper_add(crtc,
imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs); imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
drm_crtc_init(drm, crtc, drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs); imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
return 0; return 0;
......
...@@ -9,6 +9,7 @@ struct drm_display_mode; ...@@ -9,6 +9,7 @@ struct drm_display_mode;
struct drm_encoder; struct drm_encoder;
struct drm_fbdev_cma; struct drm_fbdev_cma;
struct drm_framebuffer; struct drm_framebuffer;
struct drm_plane;
struct imx_drm_crtc; struct imx_drm_crtc;
struct platform_device; struct platform_device;
...@@ -24,7 +25,7 @@ struct imx_drm_crtc_helper_funcs { ...@@ -24,7 +25,7 @@ struct imx_drm_crtc_helper_funcs {
}; };
int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
struct imx_drm_crtc **new_crtc, struct imx_drm_crtc **new_crtc, struct drm_plane *primary_plane,
const struct imx_drm_crtc_helper_funcs *imx_helper_funcs, const struct imx_drm_crtc_helper_funcs *imx_helper_funcs,
struct device_node *port); struct device_node *port);
int imx_drm_remove_crtc(struct imx_drm_crtc *); int imx_drm_remove_crtc(struct imx_drm_crtc *);
......
...@@ -349,7 +349,6 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, ...@@ -349,7 +349,6 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
int dp = -EINVAL; int dp = -EINVAL;
int ret; int ret;
int id;
ret = ipu_get_resources(ipu_crtc, pdata); ret = ipu_get_resources(ipu_crtc, pdata);
if (ret) { if (ret) {
...@@ -358,18 +357,19 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, ...@@ -358,18 +357,19 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
return ret; return ret;
} }
if (pdata->dp >= 0)
dp = IPU_DP_FLOW_SYNC_BG;
ipu_crtc->plane[0] = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0,
DRM_PLANE_TYPE_PRIMARY);
ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc, ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc,
&ipu_crtc_helper_funcs, ipu_crtc->dev->of_node); &ipu_crtc->plane[0]->base, &ipu_crtc_helper_funcs,
ipu_crtc->dev->of_node);
if (ret) { if (ret) {
dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret); dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
goto err_put_resources; goto err_put_resources;
} }
if (pdata->dp >= 0)
dp = IPU_DP_FLOW_SYNC_BG;
id = imx_drm_crtc_id(ipu_crtc->imx_crtc);
ipu_crtc->plane[0] = ipu_plane_init(ipu_crtc->base.dev, ipu,
pdata->dma[0], dp, BIT(id), true);
ret = ipu_plane_get_resources(ipu_crtc->plane[0]); ret = ipu_plane_get_resources(ipu_crtc->plane[0]);
if (ret) { if (ret) {
dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n", dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n",
...@@ -379,10 +379,10 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, ...@@ -379,10 +379,10 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
/* 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(ipu_crtc->base.dev, ipu, ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1],
pdata->dma[1], IPU_DP_FLOW_SYNC_FG,
IPU_DP_FLOW_SYNC_FG, drm_crtc_mask(&ipu_crtc->base),
BIT(id), false); 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;
} }
......
...@@ -381,7 +381,7 @@ static struct drm_plane_funcs ipu_plane_funcs = { ...@@ -381,7 +381,7 @@ static struct drm_plane_funcs ipu_plane_funcs = {
struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
int dma, int dp, unsigned int possible_crtcs, int dma, int dp, unsigned int possible_crtcs,
bool priv) enum drm_plane_type type)
{ {
struct ipu_plane *ipu_plane; struct ipu_plane *ipu_plane;
int ret; int ret;
...@@ -399,10 +399,9 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, ...@@ -399,10 +399,9 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
ipu_plane->dma = dma; ipu_plane->dma = dma;
ipu_plane->dp_flow = dp; ipu_plane->dp_flow = dp;
ret = drm_plane_init(dev, &ipu_plane->base, possible_crtcs, ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
&ipu_plane_funcs, ipu_plane_formats, &ipu_plane_funcs, ipu_plane_formats,
ARRAY_SIZE(ipu_plane_formats), ARRAY_SIZE(ipu_plane_formats), type);
priv);
if (ret) { if (ret) {
DRM_ERROR("failed to initialize plane\n"); DRM_ERROR("failed to initialize plane\n");
kfree(ipu_plane); kfree(ipu_plane);
......
...@@ -34,7 +34,7 @@ struct ipu_plane { ...@@ -34,7 +34,7 @@ struct ipu_plane {
struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
int dma, int dp, unsigned int possible_crtcs, int dma, int dp, unsigned int possible_crtcs,
bool priv); enum drm_plane_type type);
/* Init IDMAC, DMFC, DP */ /* Init IDMAC, DMFC, DP */
int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc, int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册