0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/list.h>
0011 #include <linux/videodev2.h>
0012
0013 #include <media/v4l2-common.h>
0014
0015 #include "uvcvideo.h"
0016
0017 static int uvc_mc_create_links(struct uvc_video_chain *chain,
0018 struct uvc_entity *entity)
0019 {
0020 const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE;
0021 struct media_entity *sink;
0022 unsigned int i;
0023 int ret;
0024
0025 sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
0026 ? (entity->vdev ? &entity->vdev->entity : NULL)
0027 : &entity->subdev.entity;
0028 if (sink == NULL)
0029 return 0;
0030
0031 for (i = 0; i < entity->num_pads; ++i) {
0032 struct media_entity *source;
0033 struct uvc_entity *remote;
0034 u8 remote_pad;
0035
0036 if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK))
0037 continue;
0038
0039 remote = uvc_entity_by_id(chain->dev, entity->baSourceID[i]);
0040 if (remote == NULL)
0041 return -EINVAL;
0042
0043 source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING)
0044 ? (remote->vdev ? &remote->vdev->entity : NULL)
0045 : &remote->subdev.entity;
0046 if (source == NULL)
0047 continue;
0048
0049 remote_pad = remote->num_pads - 1;
0050 ret = media_create_pad_link(source, remote_pad,
0051 sink, i, flags);
0052 if (ret < 0)
0053 return ret;
0054 }
0055
0056 return 0;
0057 }
0058
0059 static const struct v4l2_subdev_ops uvc_subdev_ops = {
0060 };
0061
0062 void uvc_mc_cleanup_entity(struct uvc_entity *entity)
0063 {
0064 if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING)
0065 media_entity_cleanup(&entity->subdev.entity);
0066 else if (entity->vdev != NULL)
0067 media_entity_cleanup(&entity->vdev->entity);
0068 }
0069
0070 static int uvc_mc_init_entity(struct uvc_video_chain *chain,
0071 struct uvc_entity *entity)
0072 {
0073 int ret;
0074
0075 if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) {
0076 u32 function;
0077
0078 v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops);
0079 strscpy(entity->subdev.name, entity->name,
0080 sizeof(entity->subdev.name));
0081
0082 switch (UVC_ENTITY_TYPE(entity)) {
0083 case UVC_VC_SELECTOR_UNIT:
0084 function = MEDIA_ENT_F_VID_MUX;
0085 break;
0086 case UVC_VC_PROCESSING_UNIT:
0087 case UVC_VC_EXTENSION_UNIT:
0088
0089 function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
0090 break;
0091 case UVC_COMPOSITE_CONNECTOR:
0092 case UVC_COMPONENT_CONNECTOR:
0093 function = MEDIA_ENT_F_CONN_COMPOSITE;
0094 break;
0095 case UVC_SVIDEO_CONNECTOR:
0096 function = MEDIA_ENT_F_CONN_SVIDEO;
0097 break;
0098 case UVC_ITT_CAMERA:
0099 function = MEDIA_ENT_F_CAM_SENSOR;
0100 break;
0101 case UVC_TT_VENDOR_SPECIFIC:
0102 case UVC_ITT_VENDOR_SPECIFIC:
0103 case UVC_ITT_MEDIA_TRANSPORT_INPUT:
0104 case UVC_OTT_VENDOR_SPECIFIC:
0105 case UVC_OTT_DISPLAY:
0106 case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
0107 case UVC_EXTERNAL_VENDOR_SPECIFIC:
0108 case UVC_EXT_GPIO_UNIT:
0109 default:
0110 function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
0111 break;
0112 }
0113
0114 entity->subdev.entity.function = function;
0115
0116 ret = media_entity_pads_init(&entity->subdev.entity,
0117 entity->num_pads, entity->pads);
0118
0119 if (ret < 0)
0120 return ret;
0121
0122 ret = v4l2_device_register_subdev(&chain->dev->vdev,
0123 &entity->subdev);
0124 } else if (entity->vdev != NULL) {
0125 ret = media_entity_pads_init(&entity->vdev->entity,
0126 entity->num_pads, entity->pads);
0127 if (entity->flags & UVC_ENTITY_FLAG_DEFAULT)
0128 entity->vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT;
0129 } else
0130 ret = 0;
0131
0132 return ret;
0133 }
0134
0135 int uvc_mc_register_entities(struct uvc_video_chain *chain)
0136 {
0137 struct uvc_entity *entity;
0138 int ret;
0139
0140 list_for_each_entry(entity, &chain->entities, chain) {
0141 ret = uvc_mc_init_entity(chain, entity);
0142 if (ret < 0) {
0143 dev_info(&chain->dev->udev->dev,
0144 "Failed to initialize entity for entity %u\n",
0145 entity->id);
0146 return ret;
0147 }
0148 }
0149
0150 list_for_each_entry(entity, &chain->entities, chain) {
0151 ret = uvc_mc_create_links(chain, entity);
0152 if (ret < 0) {
0153 dev_info(&chain->dev->udev->dev,
0154 "Failed to create links for entity %u\n",
0155 entity->id);
0156 return ret;
0157 }
0158 }
0159
0160 return 0;
0161 }