Commit b803cd35 authored by Steve Longerbeam's avatar Steve Longerbeam Committed by Mauro Carvalho Chehab

media: staging/imx: Switch to v4l2_async_notifier_add_*_subdev

Switch to v4l2_async_notifier_add_*_subdev() when adding async subdevs
to the imx-media root notifier. This removes the need to check for
an already added asd, since v4l2_async_notifier_add_*_subdev() does this
check. Also no need to allocate a subdevs array when registering the
root notifier, or keeping an internal master asd_list, since this is
moved to the notifier's asd_list.
Signed-off-by: default avatarSteve Longerbeam <slongerbeam@gmail.com>
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 11e005f2
...@@ -33,43 +33,10 @@ static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n) ...@@ -33,43 +33,10 @@ static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n)
} }
/* /*
* Find an asd by fwnode or device name. This is called during * Adds a subdev to the root notifier's async subdev list. If fwnode is
* driver load to form the async subdev list and bind them. * non-NULL, adds the async as a V4L2_ASYNC_MATCH_FWNODE match type,
*/ * otherwise as a V4L2_ASYNC_MATCH_DEVNAME match type using the dev_name
static struct v4l2_async_subdev * * of the given platform_device. This is called during driver load when
find_async_subdev(struct imx_media_dev *imxmd,
struct fwnode_handle *fwnode,
const char *devname)
{
struct imx_media_async_subdev *imxasd;
struct v4l2_async_subdev *asd;
list_for_each_entry(imxasd, &imxmd->asd_list, list) {
asd = &imxasd->asd;
switch (asd->match_type) {
case V4L2_ASYNC_MATCH_FWNODE:
if (fwnode && asd->match.fwnode == fwnode)
return asd;
break;
case V4L2_ASYNC_MATCH_DEVNAME:
if (devname && !strcmp(asd->match.device_name,
devname))
return asd;
break;
default:
break;
}
}
return NULL;
}
/*
* Adds a subdev to the async subdev list. If fwnode is non-NULL, adds
* the async as a V4L2_ASYNC_MATCH_FWNODE match type, otherwise as
* a V4L2_ASYNC_MATCH_DEVNAME match type using the dev_name of the
* given platform_device. This is called during driver load when
* forming the async subdev list. * forming the async subdev list.
*/ */
int imx_media_add_async_subdev(struct imx_media_dev *imxmd, int imx_media_add_async_subdev(struct imx_media_dev *imxmd,
...@@ -80,47 +47,34 @@ int imx_media_add_async_subdev(struct imx_media_dev *imxmd, ...@@ -80,47 +47,34 @@ int imx_media_add_async_subdev(struct imx_media_dev *imxmd,
struct imx_media_async_subdev *imxasd; struct imx_media_async_subdev *imxasd;
struct v4l2_async_subdev *asd; struct v4l2_async_subdev *asd;
const char *devname = NULL; const char *devname = NULL;
int ret = 0; int ret;
mutex_lock(&imxmd->mutex);
if (pdev) if (fwnode) {
asd = v4l2_async_notifier_add_fwnode_subdev(
&imxmd->notifier, fwnode, sizeof(*imxasd));
} else {
devname = dev_name(&pdev->dev); devname = dev_name(&pdev->dev);
asd = v4l2_async_notifier_add_devname_subdev(
/* return -EEXIST if this asd already added */ &imxmd->notifier, devname, sizeof(*imxasd));
if (find_async_subdev(imxmd, fwnode, devname)) {
dev_dbg(imxmd->md.dev, "%s: already added %s\n",
__func__, np ? np->name : devname);
ret = -EEXIST;
goto out;
} }
imxasd = devm_kzalloc(imxmd->md.dev, sizeof(*imxasd), GFP_KERNEL); if (IS_ERR(asd)) {
if (!imxasd) { ret = PTR_ERR(asd);
ret = -ENOMEM; if (ret == -EEXIST)
goto out; dev_dbg(imxmd->md.dev, "%s: already added %s\n",
} __func__, np ? np->name : devname);
asd = &imxasd->asd; return ret;
if (fwnode) {
asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
asd->match.fwnode = fwnode;
} else {
asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
asd->match.device_name = devname;
imxasd->pdev = pdev;
} }
list_add_tail(&imxasd->list, &imxmd->asd_list); imxasd = to_imx_media_asd(asd);
imxmd->notifier.num_subdevs++; if (devname)
imxasd->pdev = pdev;
dev_dbg(imxmd->md.dev, "%s: added %s, match type %s\n", dev_dbg(imxmd->md.dev, "%s: added %s, match type %s\n",
__func__, np ? np->name : devname, np ? "FWNODE" : "DEVNAME"); __func__, np ? np->name : devname, np ? "FWNODE" : "DEVNAME");
out: return 0;
mutex_unlock(&imxmd->mutex);
return ret;
} }
/* /*
...@@ -483,10 +437,8 @@ static int imx_media_probe(struct platform_device *pdev) ...@@ -483,10 +437,8 @@ static int imx_media_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node; struct device_node *node = dev->of_node;
struct imx_media_async_subdev *imxasd;
struct v4l2_async_subdev **subdevs;
struct imx_media_dev *imxmd; struct imx_media_dev *imxmd;
int num_subdevs, i, ret; int ret;
imxmd = devm_kzalloc(dev, sizeof(*imxmd), GFP_KERNEL); imxmd = devm_kzalloc(dev, sizeof(*imxmd), GFP_KERNEL);
if (!imxmd) if (!imxmd)
...@@ -515,44 +467,31 @@ static int imx_media_probe(struct platform_device *pdev) ...@@ -515,44 +467,31 @@ static int imx_media_probe(struct platform_device *pdev)
dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd); dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd);
INIT_LIST_HEAD(&imxmd->asd_list);
INIT_LIST_HEAD(&imxmd->vdev_list); INIT_LIST_HEAD(&imxmd->vdev_list);
v4l2_async_notifier_init(&imxmd->notifier);
ret = imx_media_add_of_subdevs(imxmd, node); ret = imx_media_add_of_subdevs(imxmd, node);
if (ret) { if (ret) {
v4l2_err(&imxmd->v4l2_dev, v4l2_err(&imxmd->v4l2_dev,
"add_of_subdevs failed with %d\n", ret); "add_of_subdevs failed with %d\n", ret);
goto unreg_dev; goto notifier_cleanup;
} }
ret = imx_media_add_internal_subdevs(imxmd); ret = imx_media_add_internal_subdevs(imxmd);
if (ret) { if (ret) {
v4l2_err(&imxmd->v4l2_dev, v4l2_err(&imxmd->v4l2_dev,
"add_internal_subdevs failed with %d\n", ret); "add_internal_subdevs failed with %d\n", ret);
goto unreg_dev; goto notifier_cleanup;
} }
num_subdevs = imxmd->notifier.num_subdevs;
/* no subdevs? just bail */ /* no subdevs? just bail */
if (num_subdevs == 0) { if (list_empty(&imxmd->notifier.asd_list)) {
ret = -ENODEV; ret = -ENODEV;
goto unreg_dev; goto notifier_cleanup;
} }
subdevs = devm_kcalloc(imxmd->md.dev, num_subdevs, sizeof(*subdevs),
GFP_KERNEL);
if (!subdevs) {
ret = -ENOMEM;
goto unreg_dev;
}
i = 0;
list_for_each_entry(imxasd, &imxmd->asd_list, list)
subdevs[i++] = &imxasd->asd;
/* prepare the async subdev notifier and register it */ /* prepare the async subdev notifier and register it */
imxmd->notifier.subdevs = subdevs;
imxmd->notifier.ops = &imx_media_subdev_ops; imxmd->notifier.ops = &imx_media_subdev_ops;
ret = v4l2_async_notifier_register(&imxmd->v4l2_dev, ret = v4l2_async_notifier_register(&imxmd->v4l2_dev,
&imxmd->notifier); &imxmd->notifier);
...@@ -566,7 +505,8 @@ static int imx_media_probe(struct platform_device *pdev) ...@@ -566,7 +505,8 @@ static int imx_media_probe(struct platform_device *pdev)
del_int: del_int:
imx_media_remove_internal_subdevs(imxmd); imx_media_remove_internal_subdevs(imxmd);
unreg_dev: notifier_cleanup:
v4l2_async_notifier_cleanup(&imxmd->notifier);
v4l2_device_unregister(&imxmd->v4l2_dev); v4l2_device_unregister(&imxmd->v4l2_dev);
cleanup: cleanup:
media_device_cleanup(&imxmd->md); media_device_cleanup(&imxmd->md);
...@@ -582,6 +522,7 @@ static int imx_media_remove(struct platform_device *pdev) ...@@ -582,6 +522,7 @@ static int imx_media_remove(struct platform_device *pdev)
v4l2_async_notifier_unregister(&imxmd->notifier); v4l2_async_notifier_unregister(&imxmd->notifier);
imx_media_remove_internal_subdevs(imxmd); imx_media_remove_internal_subdevs(imxmd);
v4l2_async_notifier_cleanup(&imxmd->notifier);
v4l2_device_unregister(&imxmd->v4l2_dev); v4l2_device_unregister(&imxmd->v4l2_dev);
media_device_unregister(&imxmd->md); media_device_unregister(&imxmd->md);
media_device_cleanup(&imxmd->md); media_device_cleanup(&imxmd->md);
......
...@@ -350,8 +350,11 @@ int imx_media_add_internal_subdevs(struct imx_media_dev *imxmd) ...@@ -350,8 +350,11 @@ int imx_media_add_internal_subdevs(struct imx_media_dev *imxmd)
void imx_media_remove_internal_subdevs(struct imx_media_dev *imxmd) void imx_media_remove_internal_subdevs(struct imx_media_dev *imxmd)
{ {
struct imx_media_async_subdev *imxasd; struct imx_media_async_subdev *imxasd;
struct v4l2_async_subdev *asd;
list_for_each_entry(asd, &imxmd->notifier.asd_list, asd_list) {
imxasd = to_imx_media_asd(asd);
list_for_each_entry(imxasd, &imxmd->asd_list, list) {
if (!imxasd->pdev) if (!imxasd->pdev)
continue; continue;
......
...@@ -119,12 +119,11 @@ struct imx_media_internal_sd_platformdata { ...@@ -119,12 +119,11 @@ struct imx_media_internal_sd_platformdata {
int ipu_id; int ipu_id;
}; };
struct imx_media_async_subdev { struct imx_media_async_subdev {
/* the base asd - must be first in this struct */
struct v4l2_async_subdev asd; struct v4l2_async_subdev asd;
/* the platform device of IPU-internal subdevs */ /* the platform device of IPU-internal subdevs */
struct platform_device *pdev; struct platform_device *pdev;
struct list_head list;
}; };
static inline struct imx_media_async_subdev * static inline struct imx_media_async_subdev *
...@@ -149,7 +148,6 @@ struct imx_media_dev { ...@@ -149,7 +148,6 @@ struct imx_media_dev {
struct ipu_soc *ipu[2]; struct ipu_soc *ipu[2];
/* for async subdev registration */ /* for async subdev registration */
struct list_head asd_list;
struct v4l2_async_notifier notifier; struct v4l2_async_notifier notifier;
}; };
......
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