|
27 | 27 | #include "sun6i_csi.h"
|
28 | 28 | #include "sun6i_csi_reg.h"
|
29 | 29 |
|
| 30 | +/* Helpers */ |
| 31 | + |
30 | 32 | /* TODO add 10&12 bit YUV, RGB support */
|
31 | 33 | bool sun6i_csi_is_format_supported(struct sun6i_csi_device *csi_dev,
|
32 | 34 | u32 pixformat, u32 mbus_code)
|
@@ -572,9 +574,8 @@ void sun6i_csi_set_stream(struct sun6i_csi_device *csi_dev, bool enable)
|
572 | 574 | CSI_CAP_CH0_VCAP_ON);
|
573 | 575 | }
|
574 | 576 |
|
575 |
| -/* ----------------------------------------------------------------------------- |
576 |
| - * Media Controller and V4L2 |
577 |
| - */ |
| 577 | +/* V4L2 */ |
| 578 | + |
578 | 579 | static int sun6i_csi_link_entity(struct sun6i_csi_device *csi_dev,
|
579 | 580 | struct media_entity *entity,
|
580 | 581 | struct fwnode_handle *fwnode)
|
@@ -666,83 +667,101 @@ static int sun6i_csi_fwnode_parse(struct device *dev,
|
666 | 667 | }
|
667 | 668 | }
|
668 | 669 |
|
669 |
| -static void sun6i_csi_v4l2_cleanup(struct sun6i_csi_device *csi_dev) |
| 670 | +static int sun6i_csi_v4l2_setup(struct sun6i_csi_device *csi_dev) |
670 | 671 | {
|
671 | 672 | struct sun6i_csi_v4l2 *v4l2 = &csi_dev->v4l2;
|
| 673 | + struct media_device *media_dev = &v4l2->media_dev; |
| 674 | + struct v4l2_device *v4l2_dev = &v4l2->v4l2_dev; |
| 675 | + struct v4l2_async_notifier *notifier = &v4l2->notifier; |
| 676 | + struct device *dev = csi_dev->dev; |
| 677 | + int ret; |
672 | 678 |
|
673 |
| - media_device_unregister(&v4l2->media_dev); |
674 |
| - v4l2_async_nf_unregister(&v4l2->notifier); |
675 |
| - v4l2_async_nf_cleanup(&v4l2->notifier); |
676 |
| - sun6i_video_cleanup(&csi_dev->video); |
677 |
| - v4l2_device_unregister(&v4l2->v4l2_dev); |
678 |
| - v4l2_ctrl_handler_free(&v4l2->ctrl_handler); |
679 |
| - media_device_cleanup(&v4l2->media_dev); |
680 |
| -} |
| 679 | + /* Media Device */ |
681 | 680 |
|
682 |
| -static int sun6i_csi_v4l2_init(struct sun6i_csi_device *csi_dev) |
683 |
| -{ |
684 |
| - struct sun6i_csi_v4l2 *v4l2 = &csi_dev->v4l2; |
685 |
| - int ret; |
| 681 | + strscpy(media_dev->model, SUN6I_CSI_DESCRIPTION, |
| 682 | + sizeof(media_dev->model)); |
| 683 | + media_dev->hw_revision = 0; |
| 684 | + media_dev->dev = dev; |
686 | 685 |
|
687 |
| - v4l2->media_dev.dev = csi_dev->dev; |
688 |
| - strscpy(v4l2->media_dev.model, SUN6I_CSI_DESCRIPTION, |
689 |
| - sizeof(v4l2->media_dev.model)); |
690 |
| - v4l2->media_dev.hw_revision = 0; |
| 686 | + media_device_init(media_dev); |
691 | 687 |
|
692 |
| - media_device_init(&v4l2->media_dev); |
693 |
| - v4l2_async_nf_init(&v4l2->notifier); |
| 688 | + /* V4L2 Control Handler */ |
694 | 689 |
|
695 | 690 | ret = v4l2_ctrl_handler_init(&v4l2->ctrl_handler, 0);
|
696 | 691 | if (ret) {
|
697 |
| - dev_err(csi_dev->dev, "V4L2 controls handler init failed (%d)\n", |
698 |
| - ret); |
699 |
| - goto clean_media; |
| 692 | + dev_err(dev, "failed to init v4l2 control handler: %d\n", ret); |
| 693 | + goto error_media; |
700 | 694 | }
|
701 | 695 |
|
702 |
| - v4l2->v4l2_dev.mdev = &v4l2->media_dev; |
703 |
| - v4l2->v4l2_dev.ctrl_handler = &v4l2->ctrl_handler; |
704 |
| - ret = v4l2_device_register(csi_dev->dev, &v4l2->v4l2_dev); |
| 696 | + /* V4L2 Device */ |
| 697 | + |
| 698 | + v4l2_dev->mdev = media_dev; |
| 699 | + v4l2_dev->ctrl_handler = &v4l2->ctrl_handler; |
| 700 | + |
| 701 | + ret = v4l2_device_register(dev, v4l2_dev); |
705 | 702 | if (ret) {
|
706 |
| - dev_err(csi_dev->dev, "V4L2 device registration failed (%d)\n", |
707 |
| - ret); |
708 |
| - goto free_ctrl; |
| 703 | + dev_err(dev, "failed to register v4l2 device: %d\n", ret); |
| 704 | + goto error_v4l2_ctrl; |
709 | 705 | }
|
710 | 706 |
|
| 707 | + /* Video */ |
| 708 | + |
711 | 709 | ret = sun6i_video_init(&csi_dev->video, csi_dev, SUN6I_CSI_NAME);
|
712 | 710 | if (ret)
|
713 |
| - goto unreg_v4l2; |
| 711 | + goto error_v4l2_device; |
714 | 712 |
|
715 |
| - ret = v4l2_async_nf_parse_fwnode_endpoints(csi_dev->dev, |
716 |
| - &v4l2->notifier, |
| 713 | + /* V4L2 Async */ |
| 714 | + |
| 715 | + v4l2_async_nf_init(notifier); |
| 716 | + notifier->ops = &sun6i_csi_async_ops; |
| 717 | + |
| 718 | + ret = v4l2_async_nf_parse_fwnode_endpoints(dev, notifier, |
717 | 719 | sizeof(struct
|
718 | 720 | v4l2_async_subdev),
|
719 | 721 | sun6i_csi_fwnode_parse);
|
720 | 722 | if (ret)
|
721 |
| - goto clean_video; |
722 |
| - |
723 |
| - v4l2->notifier.ops = &sun6i_csi_async_ops; |
| 723 | + goto error_video; |
724 | 724 |
|
725 |
| - ret = v4l2_async_nf_register(&v4l2->v4l2_dev, &v4l2->notifier); |
| 725 | + ret = v4l2_async_nf_register(v4l2_dev, notifier); |
726 | 726 | if (ret) {
|
727 |
| - dev_err(csi_dev->dev, "notifier registration failed\n"); |
728 |
| - goto clean_video; |
| 727 | + dev_err(dev, "failed to register v4l2 async notifier: %d\n", |
| 728 | + ret); |
| 729 | + goto error_v4l2_async_notifier; |
729 | 730 | }
|
730 | 731 |
|
731 | 732 | return 0;
|
732 | 733 |
|
733 |
| -clean_video: |
| 734 | +error_v4l2_async_notifier: |
| 735 | + v4l2_async_nf_cleanup(notifier); |
| 736 | + |
| 737 | +error_video: |
734 | 738 | sun6i_video_cleanup(&csi_dev->video);
|
735 |
| -unreg_v4l2: |
| 739 | + |
| 740 | +error_v4l2_device: |
736 | 741 | v4l2_device_unregister(&v4l2->v4l2_dev);
|
737 |
| -free_ctrl: |
| 742 | + |
| 743 | +error_v4l2_ctrl: |
738 | 744 | v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
|
739 |
| -clean_media: |
740 |
| - v4l2_async_nf_cleanup(&v4l2->notifier); |
741 |
| - media_device_cleanup(&v4l2->media_dev); |
| 745 | + |
| 746 | +error_media: |
| 747 | + media_device_cleanup(media_dev); |
742 | 748 |
|
743 | 749 | return ret;
|
744 | 750 | }
|
745 | 751 |
|
| 752 | +static void sun6i_csi_v4l2_cleanup(struct sun6i_csi_device *csi_dev) |
| 753 | +{ |
| 754 | + struct sun6i_csi_v4l2 *v4l2 = &csi_dev->v4l2; |
| 755 | + |
| 756 | + media_device_unregister(&v4l2->media_dev); |
| 757 | + v4l2_async_nf_unregister(&v4l2->notifier); |
| 758 | + v4l2_async_nf_cleanup(&v4l2->notifier); |
| 759 | + sun6i_video_cleanup(&csi_dev->video); |
| 760 | + v4l2_device_unregister(&v4l2->v4l2_dev); |
| 761 | + v4l2_ctrl_handler_free(&v4l2->ctrl_handler); |
| 762 | + media_device_cleanup(&v4l2->media_dev); |
| 763 | +} |
| 764 | + |
746 | 765 | /* Platform */
|
747 | 766 |
|
748 | 767 | static irqreturn_t sun6i_csi_interrupt(int irq, void *private)
|
@@ -939,7 +958,7 @@ static int sun6i_csi_probe(struct platform_device *platform_dev)
|
939 | 958 | if (ret)
|
940 | 959 | return ret;
|
941 | 960 |
|
942 |
| - ret = sun6i_csi_v4l2_init(csi_dev); |
| 961 | + ret = sun6i_csi_v4l2_setup(csi_dev); |
943 | 962 | if (ret)
|
944 | 963 | goto error_resources;
|
945 | 964 |
|
|
0 commit comments