1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * uvc_entity.c -- USB Video Class driver
5 * Copyright (C) 2005-2011
6 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
9 #include <linux/kernel.h>
10 #include <linux/list.h>
11 #include <linux/videodev2.h>
13 #include <media/v4l2-common.h>
17 static int uvc_mc_create_links(struct uvc_video_chain
*chain
,
18 struct uvc_entity
*entity
)
20 const u32 flags
= MEDIA_LNK_FL_ENABLED
| MEDIA_LNK_FL_IMMUTABLE
;
21 struct media_entity
*sink
;
25 sink
= (UVC_ENTITY_TYPE(entity
) == UVC_TT_STREAMING
)
26 ? (entity
->vdev
? &entity
->vdev
->entity
: NULL
)
27 : &entity
->subdev
.entity
;
31 for (i
= 0; i
< entity
->num_pads
; ++i
) {
32 struct media_entity
*source
;
33 struct uvc_entity
*remote
;
36 if (!(entity
->pads
[i
].flags
& MEDIA_PAD_FL_SINK
))
39 remote
= uvc_entity_by_id(chain
->dev
, entity
->baSourceID
[i
]);
43 source
= (UVC_ENTITY_TYPE(remote
) == UVC_TT_STREAMING
)
44 ? (remote
->vdev
? &remote
->vdev
->entity
: NULL
)
45 : &remote
->subdev
.entity
;
49 remote_pad
= remote
->num_pads
- 1;
50 ret
= media_create_pad_link(source
, remote_pad
,
59 static const struct v4l2_subdev_ops uvc_subdev_ops
= {
62 void uvc_mc_cleanup_entity(struct uvc_entity
*entity
)
64 if (UVC_ENTITY_TYPE(entity
) != UVC_TT_STREAMING
)
65 media_entity_cleanup(&entity
->subdev
.entity
);
66 else if (entity
->vdev
!= NULL
)
67 media_entity_cleanup(&entity
->vdev
->entity
);
70 static int uvc_mc_init_entity(struct uvc_video_chain
*chain
,
71 struct uvc_entity
*entity
)
75 if (UVC_ENTITY_TYPE(entity
) != UVC_TT_STREAMING
) {
78 v4l2_subdev_init(&entity
->subdev
, &uvc_subdev_ops
);
79 strscpy(entity
->subdev
.name
, entity
->name
,
80 sizeof(entity
->subdev
.name
));
82 switch (UVC_ENTITY_TYPE(entity
)) {
83 case UVC_VC_SELECTOR_UNIT
:
84 function
= MEDIA_ENT_F_VID_MUX
;
86 case UVC_VC_PROCESSING_UNIT
:
87 case UVC_VC_EXTENSION_UNIT
:
88 /* For lack of a better option. */
89 function
= MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER
;
91 case UVC_COMPOSITE_CONNECTOR
:
92 case UVC_COMPONENT_CONNECTOR
:
93 function
= MEDIA_ENT_F_CONN_COMPOSITE
;
95 case UVC_SVIDEO_CONNECTOR
:
96 function
= MEDIA_ENT_F_CONN_SVIDEO
;
99 function
= MEDIA_ENT_F_CAM_SENSOR
;
101 case UVC_TT_VENDOR_SPECIFIC
:
102 case UVC_ITT_VENDOR_SPECIFIC
:
103 case UVC_ITT_MEDIA_TRANSPORT_INPUT
:
104 case UVC_OTT_VENDOR_SPECIFIC
:
105 case UVC_OTT_DISPLAY
:
106 case UVC_OTT_MEDIA_TRANSPORT_OUTPUT
:
107 case UVC_EXTERNAL_VENDOR_SPECIFIC
:
109 function
= MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN
;
113 entity
->subdev
.entity
.function
= function
;
115 ret
= media_entity_pads_init(&entity
->subdev
.entity
,
116 entity
->num_pads
, entity
->pads
);
121 ret
= v4l2_device_register_subdev(&chain
->dev
->vdev
,
123 } else if (entity
->vdev
!= NULL
) {
124 ret
= media_entity_pads_init(&entity
->vdev
->entity
,
125 entity
->num_pads
, entity
->pads
);
126 if (entity
->flags
& UVC_ENTITY_FLAG_DEFAULT
)
127 entity
->vdev
->entity
.flags
|= MEDIA_ENT_FL_DEFAULT
;
134 int uvc_mc_register_entities(struct uvc_video_chain
*chain
)
136 struct uvc_entity
*entity
;
139 list_for_each_entry(entity
, &chain
->entities
, chain
) {
140 ret
= uvc_mc_init_entity(chain
, entity
);
142 uvc_printk(KERN_INFO
, "Failed to initialize entity for "
143 "entity %u\n", entity
->id
);
148 list_for_each_entry(entity
, &chain
->entities
, chain
) {
149 ret
= uvc_mc_create_links(chain
, entity
);
151 uvc_printk(KERN_INFO
, "Failed to create links for "
152 "entity %u\n", entity
->id
);