media: imx: Don't register IPU subdevs/links if CSI port missing
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: e130291212
("[media] media: Add i.MX media core driver")
Signed-off-by: Steve Longerbeam <slongerbeam@gmail.com>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Cc: stable@vger.kernel.org
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
Родитель
085b26da62
Коммит
dee747f881
|
@ -477,13 +477,6 @@ static int imx_media_probe(struct platform_device *pdev)
|
|||
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);
|
||||
if (ret)
|
||||
goto del_int;
|
||||
|
|
|
@ -298,13 +298,14 @@ static int add_internal_subdev(struct imx_media_dev *imxmd,
|
|||
}
|
||||
|
||||
/* 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;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < num_isd; i++) {
|
||||
const struct internal_subdev *isd = &int_subdev[i];
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* 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)
|
|||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
goto remove;
|
||||
}
|
||||
|
||||
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:
|
||||
imx_media_remove_ipu_internal_subdevs(imxmd);
|
||||
|
|
|
@ -23,36 +23,25 @@
|
|||
int imx_media_of_add_csi(struct imx_media_dev *imxmd,
|
||||
struct device_node *csi_np)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!of_device_is_available(csi_np)) {
|
||||
dev_dbg(imxmd->md.dev, "%s: %pOFn not enabled\n", __func__,
|
||||
csi_np);
|
||||
/* unavailable is not an error */
|
||||
return 0;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* add CSI fwnode to async notifier */
|
||||
ret = imx_media_add_async_subdev(imxmd, of_fwnode_handle(csi_np), NULL);
|
||||
if (ret) {
|
||||
if (ret == -EEXIST) {
|
||||
/* already added, everything is fine */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* other error, can't continue */
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return imx_media_add_async_subdev(imxmd, of_fwnode_handle(csi_np),
|
||||
NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(imx_media_of_add_csi);
|
||||
|
||||
int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
|
||||
struct device_node *np)
|
||||
{
|
||||
bool ipu_found[2] = {false, false};
|
||||
struct device_node *csi_np;
|
||||
int i, ret;
|
||||
u32 ipu_id;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
csi_np = of_parse_phandle(np, "ports", i);
|
||||
|
@ -60,12 +49,43 @@ int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
|
|||
break;
|
||||
|
||||
ret = imx_media_of_add_csi(imxmd, csi_np);
|
||||
of_node_put(csi_np);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) {
|
||||
/* unavailable or already added is not an error */
|
||||
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;
|
||||
|
||||
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);
|
|||
void imx_media_fim_free(struct imx_media_fim *fim);
|
||||
|
||||
/* 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,
|
||||
struct v4l2_subdev *sd);
|
||||
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)
|
|||
platform_set_drvdata(pdev, &csi->sd);
|
||||
|
||||
ret = imx_media_of_add_csi(imxmd, node);
|
||||
if (ret < 0)
|
||||
if (ret < 0 && ret != -ENODEV && ret != -EEXIST)
|
||||
goto cleanup;
|
||||
|
||||
ret = imx_media_dev_notifier_register(imxmd);
|
||||
|
|
Загрузка…
Ссылка в новой задаче