Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *      uvc_entity.c  --  USB Video Class driver
0004  *
0005  *      Copyright (C) 2005-2011
0006  *          Laurent Pinchart (laurent.pinchart@ideasonboard.com)
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             /* For lack of a better option. */
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 }