Lines Matching full:vin

3  * Driver for Renesas R-Car VIN
26 #include "rcar-vin.h"
32 * CSI-2 receiver to/from the VIN internal channel number simply
40 * routing for other VIN's. We can figure out which VIN is
43 #define rvin_group_id_to_master(vin) ((vin) < 4 ? 0 : 4) argument
67 static unsigned int rvin_group_get_mask(struct rvin_dev *vin, in rvin_group_get_mask() argument
74 for (route = vin->info->routes; route->mask; route++) { in rvin_group_get_mask()
75 if (route->vin == vin->id && in rvin_group_get_mask()
78 vin_dbg(vin, in rvin_group_get_mask()
79 "Adding route: vin: %d csi: %d channel: %d\n", in rvin_group_get_mask()
80 route->vin, route->csi, route->channel); in rvin_group_get_mask()
89 * Link setup for the links between a VIN and a CSI-2 receiver is a bit
91 * is not present in each VIN instance. There are special VINs which
95 * master VIN need to be taken into account when making the decision
98 * 1. Find out which VIN the link the user tries to enable is connected to.
99 * 2. Lookup which master VIN controls the links for this VIN.
101 * 4. For each previously enabled link from the master VIN bitwise AND its
107 * master VIN and inform the user that the link could be enabled.
109 * Please note that no link can be enabled if any VIN in the group is
122 struct rvin_dev *vin = NULL; in rvin_group_link_notify() local
129 /* Only care about link enablement for VIN nodes. */ in rvin_group_link_notify()
145 /* Find the master VIN that controls the routes. */ in rvin_group_link_notify()
147 vin = container_of(vdev, struct rvin_dev, vdev); in rvin_group_link_notify()
148 master_id = rvin_group_id_to_master(vin->id); in rvin_group_link_notify()
150 if (WARN_ON(!group->vin[master_id])) { in rvin_group_link_notify()
157 if (!group->vin[i]) in rvin_group_link_notify()
162 &group->vin[i]->vdev.entity.pads[0]); in rvin_group_link_notify()
169 mask &= rvin_group_get_mask(group->vin[i], csi_id, channel); in rvin_group_link_notify()
188 if (group->vin[i] && group->vin[i]->parallel && in rvin_group_link_notify()
189 group->vin[i]->parallel->subdev == sd) { in rvin_group_link_notify()
190 group->vin[i]->is_csi = false; in rvin_group_link_notify()
196 vin_err(vin, "Subdevice %s not registered to any VIN\n", in rvin_group_link_notify()
203 mask_new = mask & rvin_group_get_mask(vin, csi_id, channel); in rvin_group_link_notify()
204 vin_dbg(vin, "Try link change mask: 0x%x new: 0x%x\n", mask, mask_new); in rvin_group_link_notify()
212 ret = rvin_set_channel_routing(group->vin[master_id], __ffs(mask_new)); in rvin_group_link_notify()
216 vin->is_csi = true; in rvin_group_link_notify()
250 static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin) in rvin_group_init() argument
260 for_each_matching_node(np, vin->dev->driver->of_match_table) in rvin_group_init()
264 vin_dbg(vin, "found %u enabled VIN's in DT", group->count); in rvin_group_init()
266 mdev->dev = vin->dev; in rvin_group_init()
269 match = of_match_node(vin->dev->driver->of_match_table, in rvin_group_init()
270 vin->dev->of_node); in rvin_group_init()
298 static int rvin_group_get(struct rvin_dev *vin) in rvin_group_get() argument
304 /* Make sure VIN id is present and sane */ in rvin_group_get()
305 ret = of_property_read_u32(vin->dev->of_node, "renesas,id", &id); in rvin_group_get()
307 vin_err(vin, "%pOF: No renesas,id property found\n", in rvin_group_get()
308 vin->dev->of_node); in rvin_group_get()
313 vin_err(vin, "%pOF: Invalid renesas,id '%u'\n", in rvin_group_get()
314 vin->dev->of_node, id); in rvin_group_get()
318 /* Join or create a VIN group */ in rvin_group_get()
330 ret = rvin_group_init(group, vin); in rvin_group_get()
333 vin_err(vin, "Failed to initialize group\n"); in rvin_group_get()
343 /* Add VIN to group */ in rvin_group_get()
346 if (group->vin[id]) { in rvin_group_get()
347 vin_err(vin, "Duplicate renesas,id property value %u\n", id); in rvin_group_get()
353 group->vin[id] = vin; in rvin_group_get()
355 vin->id = id; in rvin_group_get()
356 vin->group = group; in rvin_group_get()
357 vin->v4l2_dev.mdev = &group->mdev; in rvin_group_get()
367 static void rvin_group_put(struct rvin_dev *vin) in rvin_group_put() argument
369 struct rvin_group *group = vin->group; in rvin_group_put()
373 vin->group = NULL; in rvin_group_put()
374 vin->v4l2_dev.mdev = NULL; in rvin_group_put()
376 if (WARN_ON(group->vin[vin->id] != vin)) in rvin_group_put()
379 group->vin[vin->id] = NULL; in rvin_group_put()
392 struct rvin_dev *vin = in rvin_s_ctrl() local
397 rvin_set_alpha(vin, ctrl->val); in rvin_s_ctrl()
430 /* The vin lock should be held when calling the subdevice attach and detach */
431 static int rvin_parallel_subdevice_attach(struct rvin_dev *vin, in rvin_parallel_subdevice_attach() argument
443 vin->parallel->source_pad = ret; in rvin_parallel_subdevice_attach()
446 vin->parallel->sink_pad = ret < 0 ? 0 : ret; in rvin_parallel_subdevice_attach()
448 if (vin->info->use_mc) { in rvin_parallel_subdevice_attach()
449 vin->parallel->subdev = subdev; in rvin_parallel_subdevice_attach()
454 vin->mbus_code = 0; in rvin_parallel_subdevice_attach()
456 code.pad = vin->parallel->source_pad; in rvin_parallel_subdevice_attach()
457 while (!vin->mbus_code && in rvin_parallel_subdevice_attach()
466 vin->mbus_code = code.code; in rvin_parallel_subdevice_attach()
467 vin_dbg(vin, "Found media bus format for %s: %d\n", in rvin_parallel_subdevice_attach()
468 subdev->name, vin->mbus_code); in rvin_parallel_subdevice_attach()
475 if (!vin->mbus_code) { in rvin_parallel_subdevice_attach()
476 vin_err(vin, "Unsupported media bus format for %s\n", in rvin_parallel_subdevice_attach()
482 ret = v4l2_subdev_call(subdev, video, g_tvnorms, &vin->vdev.tvnorms); in rvin_parallel_subdevice_attach()
487 vin->std = V4L2_STD_UNKNOWN; in rvin_parallel_subdevice_attach()
488 ret = v4l2_subdev_call(subdev, video, g_std, &vin->std); in rvin_parallel_subdevice_attach()
493 ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 16); in rvin_parallel_subdevice_attach()
497 v4l2_ctrl_new_std(&vin->ctrl_handler, &rvin_ctrl_ops, in rvin_parallel_subdevice_attach()
500 if (vin->ctrl_handler.error) { in rvin_parallel_subdevice_attach()
501 ret = vin->ctrl_handler.error; in rvin_parallel_subdevice_attach()
502 v4l2_ctrl_handler_free(&vin->ctrl_handler); in rvin_parallel_subdevice_attach()
506 ret = v4l2_ctrl_add_handler(&vin->ctrl_handler, subdev->ctrl_handler, in rvin_parallel_subdevice_attach()
509 v4l2_ctrl_handler_free(&vin->ctrl_handler); in rvin_parallel_subdevice_attach()
513 vin->vdev.ctrl_handler = &vin->ctrl_handler; in rvin_parallel_subdevice_attach()
515 vin->parallel->subdev = subdev; in rvin_parallel_subdevice_attach()
520 static void rvin_parallel_subdevice_detach(struct rvin_dev *vin) in rvin_parallel_subdevice_detach() argument
522 rvin_v4l2_unregister(vin); in rvin_parallel_subdevice_detach()
523 vin->parallel->subdev = NULL; in rvin_parallel_subdevice_detach()
525 if (!vin->info->use_mc) { in rvin_parallel_subdevice_detach()
526 v4l2_ctrl_handler_free(&vin->ctrl_handler); in rvin_parallel_subdevice_detach()
527 vin->vdev.ctrl_handler = NULL; in rvin_parallel_subdevice_detach()
533 struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev); in rvin_parallel_notify_complete() local
538 ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev); in rvin_parallel_notify_complete()
540 vin_err(vin, "Failed to register subdev nodes\n"); in rvin_parallel_notify_complete()
544 if (!video_is_registered(&vin->vdev)) { in rvin_parallel_notify_complete()
545 ret = rvin_v4l2_register(vin); in rvin_parallel_notify_complete()
550 if (!vin->info->use_mc) in rvin_parallel_notify_complete()
554 source = &vin->parallel->subdev->entity; in rvin_parallel_notify_complete()
555 sink = &vin->vdev.entity; in rvin_parallel_notify_complete()
557 ret = media_create_pad_link(source, vin->parallel->source_pad, in rvin_parallel_notify_complete()
558 sink, vin->parallel->sink_pad, 0); in rvin_parallel_notify_complete()
560 vin_err(vin, "Error adding link from %s to %s: %d\n", in rvin_parallel_notify_complete()
570 struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev); in rvin_parallel_notify_unbind() local
572 vin_dbg(vin, "unbind parallel subdev %s\n", subdev->name); in rvin_parallel_notify_unbind()
574 mutex_lock(&vin->lock); in rvin_parallel_notify_unbind()
575 rvin_parallel_subdevice_detach(vin); in rvin_parallel_notify_unbind()
576 mutex_unlock(&vin->lock); in rvin_parallel_notify_unbind()
583 struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev); in rvin_parallel_notify_bound() local
586 mutex_lock(&vin->lock); in rvin_parallel_notify_bound()
587 ret = rvin_parallel_subdevice_attach(vin, subdev); in rvin_parallel_notify_bound()
588 mutex_unlock(&vin->lock); in rvin_parallel_notify_bound()
592 v4l2_set_subdev_hostdata(subdev, vin); in rvin_parallel_notify_bound()
594 vin_dbg(vin, "bound subdev %s source pad: %u sink pad: %u\n", in rvin_parallel_notify_bound()
595 subdev->name, vin->parallel->source_pad, in rvin_parallel_notify_bound()
596 vin->parallel->sink_pad); in rvin_parallel_notify_bound()
611 struct rvin_dev *vin = dev_get_drvdata(dev); in rvin_parallel_parse_v4l2() local
618 vin->parallel = rvpe; in rvin_parallel_parse_v4l2()
619 vin->parallel->mbus_type = vep->bus_type; in rvin_parallel_parse_v4l2()
621 switch (vin->parallel->mbus_type) { in rvin_parallel_parse_v4l2()
624 vin_dbg(vin, "Found %s media bus\n", in rvin_parallel_parse_v4l2()
625 vin->parallel->mbus_type == V4L2_MBUS_PARALLEL ? in rvin_parallel_parse_v4l2()
627 vin->parallel->bus = vep->bus.parallel; in rvin_parallel_parse_v4l2()
630 vin_err(vin, "Unknown media bus type\n"); in rvin_parallel_parse_v4l2()
637 static int rvin_parallel_init(struct rvin_dev *vin) in rvin_parallel_init() argument
641 v4l2_async_notifier_init(&vin->notifier); in rvin_parallel_init()
644 vin->dev, &vin->notifier, sizeof(struct rvin_parallel_entity), in rvin_parallel_init()
650 if (!vin->parallel) in rvin_parallel_init()
651 return vin->info->use_mc ? 0 : -ENODEV; in rvin_parallel_init()
653 vin_dbg(vin, "Found parallel subdevice %pOF\n", in rvin_parallel_init()
654 to_of_node(vin->parallel->asd.match.fwnode)); in rvin_parallel_init()
656 vin->notifier.ops = &rvin_parallel_notify_ops; in rvin_parallel_init()
657 ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier); in rvin_parallel_init()
659 vin_err(vin, "Notifier registration failed\n"); in rvin_parallel_init()
660 v4l2_async_notifier_cleanup(&vin->notifier); in rvin_parallel_init()
673 struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev); in rvin_group_notify_complete() local
678 ret = media_device_register(&vin->group->mdev); in rvin_group_notify_complete()
682 ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev); in rvin_group_notify_complete()
684 vin_err(vin, "Failed to register subdev nodes\n"); in rvin_group_notify_complete()
690 if (vin->group->vin[i] && in rvin_group_notify_complete()
691 !video_is_registered(&vin->group->vin[i]->vdev)) { in rvin_group_notify_complete()
692 ret = rvin_v4l2_register(vin->group->vin[i]); in rvin_group_notify_complete()
699 mutex_lock(&vin->group->lock); in rvin_group_notify_complete()
700 for (route = vin->info->routes; route->mask; route++) { in rvin_group_notify_complete()
705 /* Check that VIN is part of the group. */ in rvin_group_notify_complete()
706 if (!vin->group->vin[route->vin]) in rvin_group_notify_complete()
709 /* Check that VIN' master is part of the group. */ in rvin_group_notify_complete()
710 if (!vin->group->vin[rvin_group_id_to_master(route->vin)]) in rvin_group_notify_complete()
714 if (!vin->group->csi[route->csi].subdev) in rvin_group_notify_complete()
717 source = &vin->group->csi[route->csi].subdev->entity; in rvin_group_notify_complete()
721 sink = &vin->group->vin[route->vin]->vdev.entity; in rvin_group_notify_complete()
730 vin_err(vin, "Error adding link from %s to %s\n", in rvin_group_notify_complete()
735 mutex_unlock(&vin->group->lock); in rvin_group_notify_complete()
744 struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev); in rvin_group_notify_unbind() local
748 if (vin->group->vin[i]) in rvin_group_notify_unbind()
749 rvin_v4l2_unregister(vin->group->vin[i]); in rvin_group_notify_unbind()
751 mutex_lock(&vin->group->lock); in rvin_group_notify_unbind()
754 if (vin->group->csi[i].fwnode != asd->match.fwnode) in rvin_group_notify_unbind()
756 vin->group->csi[i].subdev = NULL; in rvin_group_notify_unbind()
757 vin_dbg(vin, "Unbind CSI-2 %s from slot %u\n", subdev->name, i); in rvin_group_notify_unbind()
761 mutex_unlock(&vin->group->lock); in rvin_group_notify_unbind()
763 media_device_unregister(&vin->group->mdev); in rvin_group_notify_unbind()
770 struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev); in rvin_group_notify_bound() local
773 mutex_lock(&vin->group->lock); in rvin_group_notify_bound()
776 if (vin->group->csi[i].fwnode != asd->match.fwnode) in rvin_group_notify_bound()
778 vin->group->csi[i].subdev = subdev; in rvin_group_notify_bound()
779 vin_dbg(vin, "Bound CSI-2 %s to slot %u\n", subdev->name, i); in rvin_group_notify_bound()
783 mutex_unlock(&vin->group->lock); in rvin_group_notify_bound()
798 struct rvin_dev *vin = dev_get_drvdata(dev); in rvin_mc_parse_of_endpoint() local
805 vin_dbg(vin, "OF device %pOF disabled, ignoring\n", in rvin_mc_parse_of_endpoint()
810 mutex_lock(&vin->group->lock); in rvin_mc_parse_of_endpoint()
812 if (vin->group->csi[vep->base.id].fwnode) { in rvin_mc_parse_of_endpoint()
813 vin_dbg(vin, "OF device %pOF already handled\n", in rvin_mc_parse_of_endpoint()
819 vin->group->csi[vep->base.id].fwnode = asd->match.fwnode; in rvin_mc_parse_of_endpoint()
821 vin_dbg(vin, "Add group OF device %pOF to slot %u\n", in rvin_mc_parse_of_endpoint()
824 mutex_unlock(&vin->group->lock); in rvin_mc_parse_of_endpoint()
829 static int rvin_mc_parse_of_graph(struct rvin_dev *vin) in rvin_mc_parse_of_graph() argument
835 mutex_lock(&vin->group->lock); in rvin_mc_parse_of_graph()
837 /* If not all VIN's are registered don't register the notifier. */ in rvin_mc_parse_of_graph()
839 if (vin->group->vin[i]) { in rvin_mc_parse_of_graph()
845 if (vin->group->count != count) { in rvin_mc_parse_of_graph()
846 mutex_unlock(&vin->group->lock); in rvin_mc_parse_of_graph()
850 mutex_unlock(&vin->group->lock); in rvin_mc_parse_of_graph()
852 v4l2_async_notifier_init(&vin->group->notifier); in rvin_mc_parse_of_graph()
855 * Have all VIN's look for CSI-2 subdevices. Some subdevices will in rvin_mc_parse_of_graph()
864 vin->group->vin[i]->dev, &vin->group->notifier, in rvin_mc_parse_of_graph()
871 if (list_empty(&vin->group->notifier.asd_list)) in rvin_mc_parse_of_graph()
874 vin->group->notifier.ops = &rvin_group_notify_ops; in rvin_mc_parse_of_graph()
875 ret = v4l2_async_notifier_register(&vin->v4l2_dev, in rvin_mc_parse_of_graph()
876 &vin->group->notifier); in rvin_mc_parse_of_graph()
878 vin_err(vin, "Notifier registration failed\n"); in rvin_mc_parse_of_graph()
879 v4l2_async_notifier_cleanup(&vin->group->notifier); in rvin_mc_parse_of_graph()
886 static int rvin_mc_init(struct rvin_dev *vin) in rvin_mc_init() argument
890 vin->pad.flags = MEDIA_PAD_FL_SINK; in rvin_mc_init()
891 ret = media_entity_pads_init(&vin->vdev.entity, 1, &vin->pad); in rvin_mc_init()
895 ret = rvin_group_get(vin); in rvin_mc_init()
899 ret = rvin_mc_parse_of_graph(vin); in rvin_mc_init()
901 rvin_group_put(vin); in rvin_mc_init()
903 ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 1); in rvin_mc_init()
907 v4l2_ctrl_new_std(&vin->ctrl_handler, &rvin_ctrl_ops, in rvin_mc_init()
910 if (vin->ctrl_handler.error) { in rvin_mc_init()
911 ret = vin->ctrl_handler.error; in rvin_mc_init()
912 v4l2_ctrl_handler_free(&vin->ctrl_handler); in rvin_mc_init()
916 vin->vdev.ctrl_handler = &vin->ctrl_handler; in rvin_mc_init()
947 { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
948 { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
949 { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) },
950 { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
951 { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) },
952 { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
953 { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
954 { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) },
955 { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
956 { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
957 { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
958 { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
959 { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
960 { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) },
961 { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
962 { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
963 { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
964 { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
965 { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
966 { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) },
967 { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
968 { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
969 { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) },
970 { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
983 { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
984 { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
985 { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) },
986 { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
987 { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) },
988 { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
989 { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
990 { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) },
991 { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
992 { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
993 { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
994 { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
995 { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
996 { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) },
997 { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
998 { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
999 { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1000 { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
1001 { .csi = RVIN_CSI41, .channel = 1, .vin = 4, .mask = BIT(2) },
1002 { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
1003 { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
1004 { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) },
1005 { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
1006 { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) },
1007 { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) },
1008 { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
1009 { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) },
1010 { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
1011 { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) },
1012 { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) },
1013 { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) },
1014 { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
1028 { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1029 { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
1030 { .csi = RVIN_CSI21, .channel = 0, .vin = 0, .mask = BIT(2) | BIT(5) },
1031 { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
1032 { .csi = RVIN_CSI21, .channel = 0, .vin = 1, .mask = BIT(1) },
1033 { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1034 { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) },
1035 { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
1036 { .csi = RVIN_CSI21, .channel = 1, .vin = 1, .mask = BIT(5) },
1037 { .csi = RVIN_CSI21, .channel = 0, .vin = 2, .mask = BIT(0) },
1038 { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1039 { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
1040 { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1041 { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
1042 { .csi = RVIN_CSI21, .channel = 2, .vin = 2, .mask = BIT(5) },
1043 { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1044 { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) },
1045 { .csi = RVIN_CSI21, .channel = 1, .vin = 3, .mask = BIT(2) },
1046 { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1047 { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
1048 { .csi = RVIN_CSI21, .channel = 3, .vin = 3, .mask = BIT(5) },
1049 { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1050 { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
1051 { .csi = RVIN_CSI21, .channel = 0, .vin = 4, .mask = BIT(2) | BIT(5) },
1052 { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
1053 { .csi = RVIN_CSI21, .channel = 0, .vin = 5, .mask = BIT(1) },
1054 { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) },
1055 { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(3) },
1056 { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
1057 { .csi = RVIN_CSI21, .channel = 1, .vin = 5, .mask = BIT(5) },
1058 { .csi = RVIN_CSI21, .channel = 0, .vin = 6, .mask = BIT(0) },
1059 { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) },
1060 { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
1061 { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) },
1062 { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
1063 { .csi = RVIN_CSI21, .channel = 2, .vin = 6, .mask = BIT(5) },
1064 { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) },
1065 { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) },
1066 { .csi = RVIN_CSI21, .channel = 1, .vin = 7, .mask = BIT(2) },
1067 { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) },
1068 { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
1069 { .csi = RVIN_CSI21, .channel = 3, .vin = 7, .mask = BIT(5) },
1082 { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1083 { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
1084 { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
1085 { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1086 { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) },
1087 { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
1088 { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1089 { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
1090 { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1091 { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
1092 { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1093 { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) },
1094 { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1095 { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
1096 { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1097 { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
1098 { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
1099 { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) },
1100 { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(3) },
1101 { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
1102 { .csi = RVIN_CSI40, .channel = 0, .vin = 6, .mask = BIT(1) },
1103 { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
1104 { .csi = RVIN_CSI40, .channel = 2, .vin = 6, .mask = BIT(3) },
1105 { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
1106 { .csi = RVIN_CSI40, .channel = 1, .vin = 7, .mask = BIT(0) },
1107 { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) },
1108 { .csi = RVIN_CSI40, .channel = 3, .vin = 7, .mask = BIT(3) },
1109 { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
1123 { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1124 { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
1125 { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) },
1126 { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
1127 { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) },
1128 { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1129 { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
1130 { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) },
1131 { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1132 { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
1133 { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1134 { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
1135 { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1136 { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) },
1137 { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1138 { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
1139 { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1140 { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
1141 { .csi = RVIN_CSI40, .channel = 1, .vin = 4, .mask = BIT(2) },
1142 { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
1143 { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
1144 { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) },
1145 { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
1146 { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) },
1147 { .csi = RVIN_CSI40, .channel = 0, .vin = 6, .mask = BIT(1) },
1148 { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
1149 { .csi = RVIN_CSI40, .channel = 2, .vin = 6, .mask = BIT(3) },
1150 { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
1151 { .csi = RVIN_CSI40, .channel = 1, .vin = 7, .mask = BIT(0) },
1152 { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) },
1153 { .csi = RVIN_CSI40, .channel = 3, .vin = 7, .mask = BIT(3) },
1154 { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
1168 { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1169 { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1170 { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) },
1171 { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1172 { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1173 { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1174 { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1187 { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1188 { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) },
1189 { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1190 { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) },
1191 { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1192 { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1193 { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1194 { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1195 { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1196 { .csi = RVIN_CSI41, .channel = 1, .vin = 4, .mask = BIT(2) },
1197 { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) },
1198 { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
1199 { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) },
1200 { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) },
1201 { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) },
1202 { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) },
1216 { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1217 { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) },
1218 { .csi = RVIN_CSI40, .channel = 1, .vin = 4, .mask = BIT(2) },
1219 { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
1247 .compatible = "renesas,vin-r8a774a1",
1251 .compatible = "renesas,vin-r8a774b1",
1255 .compatible = "renesas,vin-r8a774c0",
1259 .compatible = "renesas,vin-r8a774e1",
1263 .compatible = "renesas,vin-r8a7778",
1267 .compatible = "renesas,vin-r8a7779",
1271 .compatible = "renesas,vin-r8a7790",
1275 .compatible = "renesas,vin-r8a7791",
1279 .compatible = "renesas,vin-r8a7793",
1283 .compatible = "renesas,vin-r8a7794",
1287 .compatible = "renesas,rcar-gen2-vin",
1291 .compatible = "renesas,vin-r8a7795",
1295 .compatible = "renesas,vin-r8a7796",
1299 .compatible = "renesas,vin-r8a77965",
1303 .compatible = "renesas,vin-r8a77970",
1307 .compatible = "renesas,vin-r8a77980",
1311 .compatible = "renesas,vin-r8a77990",
1315 .compatible = "renesas,vin-r8a77995",
1333 struct rvin_dev *vin; in rcar_vin_probe() local
1336 vin = devm_kzalloc(&pdev->dev, sizeof(*vin), GFP_KERNEL); in rcar_vin_probe()
1337 if (!vin) in rcar_vin_probe()
1340 vin->dev = &pdev->dev; in rcar_vin_probe()
1341 vin->info = of_device_get_match_data(&pdev->dev); in rcar_vin_probe()
1342 vin->alpha = 0xff; in rcar_vin_probe()
1350 vin->info = attr->data; in rcar_vin_probe()
1352 vin->base = devm_platform_ioremap_resource(pdev, 0); in rcar_vin_probe()
1353 if (IS_ERR(vin->base)) in rcar_vin_probe()
1354 return PTR_ERR(vin->base); in rcar_vin_probe()
1360 ret = rvin_dma_register(vin, irq); in rcar_vin_probe()
1364 platform_set_drvdata(pdev, vin); in rcar_vin_probe()
1366 if (vin->info->use_mc) { in rcar_vin_probe()
1367 ret = rvin_mc_init(vin); in rcar_vin_probe()
1372 ret = rvin_parallel_init(vin); in rcar_vin_probe()
1382 v4l2_ctrl_handler_free(&vin->ctrl_handler); in rcar_vin_probe()
1384 if (vin->info->use_mc) { in rcar_vin_probe()
1385 mutex_lock(&vin->group->lock); in rcar_vin_probe()
1386 if (&vin->v4l2_dev == vin->group->notifier.v4l2_dev) { in rcar_vin_probe()
1387 v4l2_async_notifier_unregister(&vin->group->notifier); in rcar_vin_probe()
1388 v4l2_async_notifier_cleanup(&vin->group->notifier); in rcar_vin_probe()
1390 mutex_unlock(&vin->group->lock); in rcar_vin_probe()
1391 rvin_group_put(vin); in rcar_vin_probe()
1395 rvin_dma_unregister(vin); in rcar_vin_probe()
1402 struct rvin_dev *vin = platform_get_drvdata(pdev); in rcar_vin_remove() local
1406 rvin_v4l2_unregister(vin); in rcar_vin_remove()
1408 v4l2_async_notifier_unregister(&vin->notifier); in rcar_vin_remove()
1409 v4l2_async_notifier_cleanup(&vin->notifier); in rcar_vin_remove()
1411 if (vin->info->use_mc) { in rcar_vin_remove()
1412 v4l2_async_notifier_unregister(&vin->group->notifier); in rcar_vin_remove()
1413 v4l2_async_notifier_cleanup(&vin->group->notifier); in rcar_vin_remove()
1414 rvin_group_put(vin); in rcar_vin_remove()
1417 v4l2_ctrl_handler_free(&vin->ctrl_handler); in rcar_vin_remove()
1419 rvin_dma_unregister(vin); in rcar_vin_remove()
1426 .name = "rcar-vin",
1436 MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver");