diff options
Diffstat (limited to 'drivers/media/platform/qcom/camss/camss.c')
-rw-r--r-- | drivers/media/platform/qcom/camss/camss.c | 91 |
1 files changed, 43 insertions, 48 deletions
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 669615fff6a0..45978db3b0be 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -462,61 +462,51 @@ static int camss_of_parse_endpoint_node(struct device *dev, * * Return number of "port" nodes found in "ports" node */ -static int camss_of_parse_ports(struct device *dev, - struct v4l2_async_notifier *notifier) +static int camss_of_parse_ports(struct camss *camss) { + struct device *dev = camss->dev; struct device_node *node = NULL; struct device_node *remote = NULL; - unsigned int size, i; - int ret; - - while ((node = of_graph_get_next_endpoint(dev->of_node, node))) - if (of_device_is_available(node)) - notifier->num_subdevs++; - - of_node_put(node); - size = sizeof(*notifier->subdevs) * notifier->num_subdevs; - notifier->subdevs = devm_kzalloc(dev, size, GFP_KERNEL); - if (!notifier->subdevs) { - dev_err(dev, "Failed to allocate memory\n"); - return -ENOMEM; - } + int ret, num_subdevs = 0; - i = 0; - while ((node = of_graph_get_next_endpoint(dev->of_node, node))) { + for_each_endpoint_of_node(dev->of_node, node) { struct camss_async_subdev *csd; + struct v4l2_async_subdev *asd; if (!of_device_is_available(node)) continue; - csd = devm_kzalloc(dev, sizeof(*csd), GFP_KERNEL); - if (!csd) { - of_node_put(node); - dev_err(dev, "Failed to allocate memory\n"); - return -ENOMEM; - } - - notifier->subdevs[i++] = &csd->asd; - - ret = camss_of_parse_endpoint_node(dev, node, csd); - if (ret < 0) { - of_node_put(node); - return ret; - } - remote = of_graph_get_remote_port_parent(node); if (!remote) { dev_err(dev, "Cannot get remote parent\n"); - of_node_put(node); - return -EINVAL; + ret = -EINVAL; + goto err_cleanup; } - csd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; - csd->asd.match.fwnode = of_fwnode_handle(remote); + asd = v4l2_async_notifier_add_fwnode_subdev( + &camss->notifier, of_fwnode_handle(remote), + sizeof(*csd)); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); + of_node_put(remote); + goto err_cleanup; + } + + csd = container_of(asd, struct camss_async_subdev, asd); + + ret = camss_of_parse_endpoint_node(dev, node, csd); + if (ret < 0) + goto err_cleanup; + + num_subdevs++; } - of_node_put(node); - return notifier->num_subdevs; + return num_subdevs; + +err_cleanup: + v4l2_async_notifier_cleanup(&camss->notifier); + of_node_put(node); + return ret; } /* @@ -823,7 +813,7 @@ static int camss_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct camss *camss; - int ret; + int num_subdevs, ret; camss = kzalloc(sizeof(*camss), GFP_KERNEL); if (!camss) @@ -863,20 +853,22 @@ static int camss_probe(struct platform_device *pdev) if (!camss->vfe) return -ENOMEM; - ret = camss_of_parse_ports(dev, &camss->notifier); - if (ret < 0) - return ret; + v4l2_async_notifier_init(&camss->notifier); + + num_subdevs = camss_of_parse_ports(camss); + if (num_subdevs < 0) + return num_subdevs; ret = camss_init_subdevices(camss); if (ret < 0) - return ret; + goto err_cleanup; ret = dma_set_mask_and_coherent(dev, 0xffffffff); if (ret) - return ret; + goto err_cleanup; camss->media_dev.dev = camss->dev; - strlcpy(camss->media_dev.model, "Qualcomm Camera Subsystem", + strscpy(camss->media_dev.model, "Qualcomm Camera Subsystem", sizeof(camss->media_dev.model)); camss->media_dev.ops = &camss_media_ops; media_device_init(&camss->media_dev); @@ -885,14 +877,14 @@ static int camss_probe(struct platform_device *pdev) ret = v4l2_device_register(camss->dev, &camss->v4l2_dev); if (ret < 0) { dev_err(dev, "Failed to register V4L2 device: %d\n", ret); - return ret; + goto err_cleanup; } ret = camss_register_entities(camss); if (ret < 0) goto err_register_entities; - if (camss->notifier.num_subdevs) { + if (num_subdevs) { camss->notifier.ops = &camss_subdev_notifier_ops; ret = v4l2_async_notifier_register(&camss->v4l2_dev, @@ -942,6 +934,8 @@ err_register_subdevs: camss_unregister_entities(camss); err_register_entities: v4l2_device_unregister(&camss->v4l2_dev); +err_cleanup: + v4l2_async_notifier_cleanup(&camss->notifier); return ret; } @@ -978,6 +972,7 @@ static int camss_remove(struct platform_device *pdev) msm_vfe_stop_streaming(&camss->vfe[i]); v4l2_async_notifier_unregister(&camss->notifier); + v4l2_async_notifier_cleanup(&camss->notifier); camss_unregister_entities(camss); if (atomic_read(&camss->ref_count) == 0) |