Commit e0cfe523 authored by Steve Longerbeam's avatar Steve Longerbeam Committed by Greg Kroah-Hartman

media: imx: Don't register IPU subdevs/links if CSI port missing

commit dee747f8 upstream.

The second IPU internal sub-devices were being registered and links
to them created even when the second IPU is not present. This is wrong
for i.MX6 S/DL and i.MX53 which have only a single IPU.

Fixes: e1302912 ("[media] media: Add i.MX media core driver")
Signed-off-by: default avatarSteve Longerbeam <slongerbeam@gmail.com>
Reviewed-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5774e9e5
...@@ -477,13 +477,6 @@ static int imx_media_probe(struct platform_device *pdev) ...@@ -477,13 +477,6 @@ static int imx_media_probe(struct platform_device *pdev)
goto cleanup; goto cleanup;
} }
ret = imx_media_add_ipu_internal_subdevs(imxmd);
if (ret) {
v4l2_err(&imxmd->v4l2_dev,
"add_ipu_internal_subdevs failed with %d\n", ret);
goto cleanup;
}
ret = imx_media_dev_notifier_register(imxmd); ret = imx_media_dev_notifier_register(imxmd);
if (ret) if (ret)
goto del_int; goto del_int;
......
...@@ -298,13 +298,14 @@ static int add_internal_subdev(struct imx_media_dev *imxmd, ...@@ -298,13 +298,14 @@ static int add_internal_subdev(struct imx_media_dev *imxmd,
} }
/* adds the internal subdevs in one ipu */ /* adds the internal subdevs in one ipu */
static int add_ipu_internal_subdevs(struct imx_media_dev *imxmd, int ipu_id) int imx_media_add_ipu_internal_subdevs(struct imx_media_dev *imxmd,
int ipu_id)
{ {
enum isd_enum i; enum isd_enum i;
int ret;
for (i = 0; i < num_isd; i++) { for (i = 0; i < num_isd; i++) {
const struct internal_subdev *isd = &int_subdev[i]; const struct internal_subdev *isd = &int_subdev[i];
int ret;
/* /*
* the CSIs are represented in the device-tree, so those * the CSIs are represented in the device-tree, so those
...@@ -322,25 +323,10 @@ static int add_ipu_internal_subdevs(struct imx_media_dev *imxmd, int ipu_id) ...@@ -322,25 +323,10 @@ static int add_ipu_internal_subdevs(struct imx_media_dev *imxmd, int ipu_id)
} }
if (ret) if (ret)
return ret; goto remove;
} }
return 0; return 0;
}
int imx_media_add_ipu_internal_subdevs(struct imx_media_dev *imxmd)
{
int ret;
ret = add_ipu_internal_subdevs(imxmd, 0);
if (ret)
goto remove;
ret = add_ipu_internal_subdevs(imxmd, 1);
if (ret)
goto remove;
return 0;
remove: remove:
imx_media_remove_ipu_internal_subdevs(imxmd); imx_media_remove_ipu_internal_subdevs(imxmd);
......
...@@ -23,36 +23,25 @@ ...@@ -23,36 +23,25 @@
int imx_media_of_add_csi(struct imx_media_dev *imxmd, int imx_media_of_add_csi(struct imx_media_dev *imxmd,
struct device_node *csi_np) struct device_node *csi_np)
{ {
int ret;
if (!of_device_is_available(csi_np)) { if (!of_device_is_available(csi_np)) {
dev_dbg(imxmd->md.dev, "%s: %pOFn not enabled\n", __func__, dev_dbg(imxmd->md.dev, "%s: %pOFn not enabled\n", __func__,
csi_np); csi_np);
/* unavailable is not an error */ return -ENODEV;
return 0;
} }
/* add CSI fwnode to async notifier */ /* add CSI fwnode to async notifier */
ret = imx_media_add_async_subdev(imxmd, of_fwnode_handle(csi_np), NULL); return imx_media_add_async_subdev(imxmd, of_fwnode_handle(csi_np),
if (ret) { NULL);
if (ret == -EEXIST) {
/* already added, everything is fine */
return 0;
}
/* other error, can't continue */
return ret;
}
return 0;
} }
EXPORT_SYMBOL_GPL(imx_media_of_add_csi); EXPORT_SYMBOL_GPL(imx_media_of_add_csi);
int imx_media_add_of_subdevs(struct imx_media_dev *imxmd, int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
struct device_node *np) struct device_node *np)
{ {
bool ipu_found[2] = {false, false};
struct device_node *csi_np; struct device_node *csi_np;
int i, ret; int i, ret;
u32 ipu_id;
for (i = 0; ; i++) { for (i = 0; ; i++) {
csi_np = of_parse_phandle(np, "ports", i); csi_np = of_parse_phandle(np, "ports", i);
...@@ -60,12 +49,43 @@ int imx_media_add_of_subdevs(struct imx_media_dev *imxmd, ...@@ -60,12 +49,43 @@ int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
break; break;
ret = imx_media_of_add_csi(imxmd, csi_np); ret = imx_media_of_add_csi(imxmd, csi_np);
of_node_put(csi_np); if (ret) {
if (ret) /* unavailable or already added is not an error */
return ret; if (ret == -ENODEV || ret == -EEXIST) {
of_node_put(csi_np);
continue;
}
/* other error, can't continue */
goto err_out;
}
ret = of_alias_get_id(csi_np->parent, "ipu");
if (ret < 0)
goto err_out;
if (ret > 1) {
ret = -EINVAL;
goto err_out;
}
ipu_id = ret;
if (!ipu_found[ipu_id]) {
ret = imx_media_add_ipu_internal_subdevs(imxmd,
ipu_id);
if (ret)
goto err_out;
}
ipu_found[ipu_id] = true;
} }
return 0; return 0;
err_out:
imx_media_remove_ipu_internal_subdevs(imxmd);
of_node_put(csi_np);
return ret;
} }
/* /*
......
...@@ -252,7 +252,8 @@ struct imx_media_fim *imx_media_fim_init(struct v4l2_subdev *sd); ...@@ -252,7 +252,8 @@ struct imx_media_fim *imx_media_fim_init(struct v4l2_subdev *sd);
void imx_media_fim_free(struct imx_media_fim *fim); void imx_media_fim_free(struct imx_media_fim *fim);
/* imx-media-internal-sd.c */ /* imx-media-internal-sd.c */
int imx_media_add_ipu_internal_subdevs(struct imx_media_dev *imxmd); int imx_media_add_ipu_internal_subdevs(struct imx_media_dev *imxmd,
int ipu_id);
int imx_media_create_ipu_internal_links(struct imx_media_dev *imxmd, int imx_media_create_ipu_internal_links(struct imx_media_dev *imxmd,
struct v4l2_subdev *sd); struct v4l2_subdev *sd);
void imx_media_remove_ipu_internal_subdevs(struct imx_media_dev *imxmd); void imx_media_remove_ipu_internal_subdevs(struct imx_media_dev *imxmd);
......
...@@ -1271,7 +1271,7 @@ static int imx7_csi_probe(struct platform_device *pdev) ...@@ -1271,7 +1271,7 @@ static int imx7_csi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, &csi->sd); platform_set_drvdata(pdev, &csi->sd);
ret = imx_media_of_add_csi(imxmd, node); ret = imx_media_of_add_csi(imxmd, node);
if (ret < 0) if (ret < 0 && ret != -ENODEV && ret != -EEXIST)
goto cleanup; goto cleanup;
ret = imx_media_dev_notifier_register(imxmd); ret = imx_media_dev_notifier_register(imxmd);
......
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