| .. | .. |
|---|
| 346 | 346 | * |
|---|
| 347 | 347 | * Return a pointer to sensor media entity or NULL if not found |
|---|
| 348 | 348 | */ |
|---|
| 349 | | -static struct media_entity *camss_find_sensor(struct media_entity *entity) |
|---|
| 349 | +struct media_entity *camss_find_sensor(struct media_entity *entity) |
|---|
| 350 | 350 | { |
|---|
| 351 | 351 | struct media_pad *pad; |
|---|
| 352 | 352 | |
|---|
| .. | .. |
|---|
| 462 | 462 | * |
|---|
| 463 | 463 | * Return number of "port" nodes found in "ports" node |
|---|
| 464 | 464 | */ |
|---|
| 465 | | -static int camss_of_parse_ports(struct device *dev, |
|---|
| 466 | | - struct v4l2_async_notifier *notifier) |
|---|
| 465 | +static int camss_of_parse_ports(struct camss *camss) |
|---|
| 467 | 466 | { |
|---|
| 467 | + struct device *dev = camss->dev; |
|---|
| 468 | 468 | struct device_node *node = NULL; |
|---|
| 469 | 469 | struct device_node *remote = NULL; |
|---|
| 470 | | - unsigned int size, i; |
|---|
| 471 | | - int ret; |
|---|
| 470 | + int ret, num_subdevs = 0; |
|---|
| 472 | 471 | |
|---|
| 473 | | - while ((node = of_graph_get_next_endpoint(dev->of_node, node))) |
|---|
| 474 | | - if (of_device_is_available(node)) |
|---|
| 475 | | - notifier->num_subdevs++; |
|---|
| 476 | | - |
|---|
| 477 | | - of_node_put(node); |
|---|
| 478 | | - size = sizeof(*notifier->subdevs) * notifier->num_subdevs; |
|---|
| 479 | | - notifier->subdevs = devm_kzalloc(dev, size, GFP_KERNEL); |
|---|
| 480 | | - if (!notifier->subdevs) { |
|---|
| 481 | | - dev_err(dev, "Failed to allocate memory\n"); |
|---|
| 482 | | - return -ENOMEM; |
|---|
| 483 | | - } |
|---|
| 484 | | - |
|---|
| 485 | | - i = 0; |
|---|
| 486 | | - while ((node = of_graph_get_next_endpoint(dev->of_node, node))) { |
|---|
| 472 | + for_each_endpoint_of_node(dev->of_node, node) { |
|---|
| 487 | 473 | struct camss_async_subdev *csd; |
|---|
| 474 | + struct v4l2_async_subdev *asd; |
|---|
| 488 | 475 | |
|---|
| 489 | 476 | if (!of_device_is_available(node)) |
|---|
| 490 | 477 | continue; |
|---|
| 491 | 478 | |
|---|
| 492 | | - csd = devm_kzalloc(dev, sizeof(*csd), GFP_KERNEL); |
|---|
| 493 | | - if (!csd) { |
|---|
| 494 | | - of_node_put(node); |
|---|
| 495 | | - dev_err(dev, "Failed to allocate memory\n"); |
|---|
| 496 | | - return -ENOMEM; |
|---|
| 497 | | - } |
|---|
| 498 | | - |
|---|
| 499 | | - notifier->subdevs[i++] = &csd->asd; |
|---|
| 500 | | - |
|---|
| 501 | | - ret = camss_of_parse_endpoint_node(dev, node, csd); |
|---|
| 502 | | - if (ret < 0) { |
|---|
| 503 | | - of_node_put(node); |
|---|
| 504 | | - return ret; |
|---|
| 505 | | - } |
|---|
| 506 | | - |
|---|
| 507 | 479 | remote = of_graph_get_remote_port_parent(node); |
|---|
| 508 | 480 | if (!remote) { |
|---|
| 509 | 481 | dev_err(dev, "Cannot get remote parent\n"); |
|---|
| 510 | | - of_node_put(node); |
|---|
| 511 | | - return -EINVAL; |
|---|
| 482 | + ret = -EINVAL; |
|---|
| 483 | + goto err_cleanup; |
|---|
| 512 | 484 | } |
|---|
| 513 | 485 | |
|---|
| 514 | | - csd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; |
|---|
| 515 | | - csd->asd.match.fwnode = of_fwnode_handle(remote); |
|---|
| 516 | | - } |
|---|
| 517 | | - of_node_put(node); |
|---|
| 486 | + asd = v4l2_async_notifier_add_fwnode_subdev( |
|---|
| 487 | + &camss->notifier, of_fwnode_handle(remote), |
|---|
| 488 | + sizeof(*csd)); |
|---|
| 489 | + of_node_put(remote); |
|---|
| 490 | + if (IS_ERR(asd)) { |
|---|
| 491 | + ret = PTR_ERR(asd); |
|---|
| 492 | + goto err_cleanup; |
|---|
| 493 | + } |
|---|
| 518 | 494 | |
|---|
| 519 | | - return notifier->num_subdevs; |
|---|
| 495 | + csd = container_of(asd, struct camss_async_subdev, asd); |
|---|
| 496 | + |
|---|
| 497 | + ret = camss_of_parse_endpoint_node(dev, node, csd); |
|---|
| 498 | + if (ret < 0) |
|---|
| 499 | + goto err_cleanup; |
|---|
| 500 | + |
|---|
| 501 | + num_subdevs++; |
|---|
| 502 | + } |
|---|
| 503 | + |
|---|
| 504 | + return num_subdevs; |
|---|
| 505 | + |
|---|
| 506 | +err_cleanup: |
|---|
| 507 | + of_node_put(node); |
|---|
| 508 | + return ret; |
|---|
| 520 | 509 | } |
|---|
| 521 | 510 | |
|---|
| 522 | 511 | /* |
|---|
| .. | .. |
|---|
| 823 | 812 | { |
|---|
| 824 | 813 | struct device *dev = &pdev->dev; |
|---|
| 825 | 814 | struct camss *camss; |
|---|
| 826 | | - int ret; |
|---|
| 815 | + int num_subdevs, ret; |
|---|
| 827 | 816 | |
|---|
| 828 | 817 | camss = kzalloc(sizeof(*camss), GFP_KERNEL); |
|---|
| 829 | 818 | if (!camss) |
|---|
| .. | .. |
|---|
| 845 | 834 | camss->csid_num = 4; |
|---|
| 846 | 835 | camss->vfe_num = 2; |
|---|
| 847 | 836 | } else { |
|---|
| 848 | | - return -EINVAL; |
|---|
| 837 | + ret = -EINVAL; |
|---|
| 838 | + goto err_free; |
|---|
| 849 | 839 | } |
|---|
| 850 | 840 | |
|---|
| 851 | 841 | camss->csiphy = devm_kcalloc(dev, camss->csiphy_num, |
|---|
| 852 | 842 | sizeof(*camss->csiphy), GFP_KERNEL); |
|---|
| 853 | | - if (!camss->csiphy) |
|---|
| 854 | | - return -ENOMEM; |
|---|
| 843 | + if (!camss->csiphy) { |
|---|
| 844 | + ret = -ENOMEM; |
|---|
| 845 | + goto err_free; |
|---|
| 846 | + } |
|---|
| 855 | 847 | |
|---|
| 856 | 848 | camss->csid = devm_kcalloc(dev, camss->csid_num, sizeof(*camss->csid), |
|---|
| 857 | 849 | GFP_KERNEL); |
|---|
| 858 | | - if (!camss->csid) |
|---|
| 859 | | - return -ENOMEM; |
|---|
| 850 | + if (!camss->csid) { |
|---|
| 851 | + ret = -ENOMEM; |
|---|
| 852 | + goto err_free; |
|---|
| 853 | + } |
|---|
| 860 | 854 | |
|---|
| 861 | 855 | camss->vfe = devm_kcalloc(dev, camss->vfe_num, sizeof(*camss->vfe), |
|---|
| 862 | 856 | GFP_KERNEL); |
|---|
| 863 | | - if (!camss->vfe) |
|---|
| 864 | | - return -ENOMEM; |
|---|
| 857 | + if (!camss->vfe) { |
|---|
| 858 | + ret = -ENOMEM; |
|---|
| 859 | + goto err_free; |
|---|
| 860 | + } |
|---|
| 865 | 861 | |
|---|
| 866 | | - ret = camss_of_parse_ports(dev, &camss->notifier); |
|---|
| 867 | | - if (ret < 0) |
|---|
| 868 | | - return ret; |
|---|
| 862 | + v4l2_async_notifier_init(&camss->notifier); |
|---|
| 863 | + |
|---|
| 864 | + num_subdevs = camss_of_parse_ports(camss); |
|---|
| 865 | + if (num_subdevs < 0) { |
|---|
| 866 | + ret = num_subdevs; |
|---|
| 867 | + goto err_cleanup; |
|---|
| 868 | + } |
|---|
| 869 | 869 | |
|---|
| 870 | 870 | ret = camss_init_subdevices(camss); |
|---|
| 871 | 871 | if (ret < 0) |
|---|
| 872 | | - return ret; |
|---|
| 872 | + goto err_cleanup; |
|---|
| 873 | 873 | |
|---|
| 874 | 874 | ret = dma_set_mask_and_coherent(dev, 0xffffffff); |
|---|
| 875 | 875 | if (ret) |
|---|
| 876 | | - return ret; |
|---|
| 876 | + goto err_cleanup; |
|---|
| 877 | 877 | |
|---|
| 878 | 878 | camss->media_dev.dev = camss->dev; |
|---|
| 879 | | - strlcpy(camss->media_dev.model, "Qualcomm Camera Subsystem", |
|---|
| 879 | + strscpy(camss->media_dev.model, "Qualcomm Camera Subsystem", |
|---|
| 880 | 880 | sizeof(camss->media_dev.model)); |
|---|
| 881 | 881 | camss->media_dev.ops = &camss_media_ops; |
|---|
| 882 | 882 | media_device_init(&camss->media_dev); |
|---|
| .. | .. |
|---|
| 885 | 885 | ret = v4l2_device_register(camss->dev, &camss->v4l2_dev); |
|---|
| 886 | 886 | if (ret < 0) { |
|---|
| 887 | 887 | dev_err(dev, "Failed to register V4L2 device: %d\n", ret); |
|---|
| 888 | | - return ret; |
|---|
| 888 | + goto err_cleanup; |
|---|
| 889 | 889 | } |
|---|
| 890 | 890 | |
|---|
| 891 | 891 | ret = camss_register_entities(camss); |
|---|
| 892 | 892 | if (ret < 0) |
|---|
| 893 | 893 | goto err_register_entities; |
|---|
| 894 | 894 | |
|---|
| 895 | | - if (camss->notifier.num_subdevs) { |
|---|
| 895 | + if (num_subdevs) { |
|---|
| 896 | 896 | camss->notifier.ops = &camss_subdev_notifier_ops; |
|---|
| 897 | 897 | |
|---|
| 898 | 898 | ret = v4l2_async_notifier_register(&camss->v4l2_dev, |
|---|
| .. | .. |
|---|
| 942 | 942 | camss_unregister_entities(camss); |
|---|
| 943 | 943 | err_register_entities: |
|---|
| 944 | 944 | v4l2_device_unregister(&camss->v4l2_dev); |
|---|
| 945 | +err_cleanup: |
|---|
| 946 | + v4l2_async_notifier_cleanup(&camss->notifier); |
|---|
| 947 | +err_free: |
|---|
| 948 | + kfree(camss); |
|---|
| 945 | 949 | |
|---|
| 946 | 950 | return ret; |
|---|
| 947 | 951 | } |
|---|
| .. | .. |
|---|
| 970 | 974 | */ |
|---|
| 971 | 975 | static int camss_remove(struct platform_device *pdev) |
|---|
| 972 | 976 | { |
|---|
| 973 | | - unsigned int i; |
|---|
| 974 | | - |
|---|
| 975 | 977 | struct camss *camss = platform_get_drvdata(pdev); |
|---|
| 976 | 978 | |
|---|
| 977 | | - for (i = 0; i < camss->vfe_num; i++) |
|---|
| 978 | | - msm_vfe_stop_streaming(&camss->vfe[i]); |
|---|
| 979 | | - |
|---|
| 980 | 979 | v4l2_async_notifier_unregister(&camss->notifier); |
|---|
| 980 | + v4l2_async_notifier_cleanup(&camss->notifier); |
|---|
| 981 | 981 | camss_unregister_entities(camss); |
|---|
| 982 | 982 | |
|---|
| 983 | 983 | if (atomic_read(&camss->ref_count) == 0) |
|---|