.. | .. |
---|
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) |
---|