Lines Matching +full:spartan +full:- +full:6

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * uvc_driver.c -- USB Video Class driver
5 * Copyright (C) 2005-2010
24 #include <media/v4l2-common.h>
25 #include <media/v4l2-ioctl.h>
36 static unsigned int uvc_quirks_param = -1;
40 /* ------------------------------------------------------------------------
50 for (i = 0; i < alts->desc.bNumEndpoints; ++i) { in uvc_find_endpoint()
51 ep = &alts->endpoint[i]; in uvc_find_endpoint()
52 if (ep->desc.bEndpointAddress == epaddr) in uvc_find_endpoint()
89 V4L2_XFER_FUNC_709, /* Substitution for BT.470-2 M */ in uvc_xfer_func()
90 V4L2_XFER_FUNC_709, /* Substitution for BT.470-2 B, G */ in uvc_xfer_func()
119 V4L2_YCBCR_ENC_601, /* Substitution for BT.470-2 B, G */ in uvc_ycbcr_enc()
130 /* ------------------------------------------------------------------------
138 list_for_each_entry(entity, &dev->entities, list) { in uvc_entity_by_id()
139 if (entity->id == id) in uvc_entity_by_id()
152 entity = list_entry(&dev->entities, struct uvc_entity, list); in uvc_entity_by_reference()
154 list_for_each_entry_continue(entity, &dev->entities, list) { in uvc_entity_by_reference()
155 for (i = 0; i < entity->bNrInPins; ++i) in uvc_entity_by_reference()
156 if (entity->baSourceID[i] == id) in uvc_entity_by_reference()
167 list_for_each_entry(stream, &dev->streams, list) { in uvc_stream_by_id()
168 if (stream->header.bTerminalLink == id) in uvc_stream_by_id()
175 /* ------------------------------------------------------------------------
181 if (stream->async_wq) in uvc_stream_delete()
182 destroy_workqueue(stream->async_wq); in uvc_stream_delete()
184 mutex_destroy(&stream->mutex); in uvc_stream_delete()
186 usb_put_intf(stream->intf); in uvc_stream_delete()
188 kfree(stream->formats); in uvc_stream_delete()
189 kfree(stream->header.bmaControls); in uvc_stream_delete()
202 mutex_init(&stream->mutex); in uvc_stream_new()
204 stream->dev = dev; in uvc_stream_new()
205 stream->intf = usb_get_intf(intf); in uvc_stream_new()
206 stream->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; in uvc_stream_new()
209 stream->async_wq = alloc_workqueue("uvcvideo", WQ_UNBOUND | WQ_HIGHPRI, in uvc_stream_new()
211 if (!stream->async_wq) { in uvc_stream_new()
219 /* ------------------------------------------------------------------------
229 struct usb_host_interface *alts = streaming->intf->cur_altsetting; in uvc_parse_frame()
244 dev->udev->devnum, alts->desc.bInterfaceNumber); in uvc_parse_frame()
245 return -EINVAL; in uvc_parse_frame()
248 frame->bFrameIndex = buffer[3]; in uvc_parse_frame()
249 frame->bmCapabilities = buffer[4]; in uvc_parse_frame()
250 frame->wWidth = get_unaligned_le16(&buffer[5]) * width_multiplier; in uvc_parse_frame()
251 frame->wHeight = get_unaligned_le16(&buffer[7]); in uvc_parse_frame()
252 frame->dwMinBitRate = get_unaligned_le32(&buffer[9]); in uvc_parse_frame()
253 frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]); in uvc_parse_frame()
255 frame->dwMaxVideoFrameBufferSize = in uvc_parse_frame()
257 frame->dwDefaultFrameInterval = in uvc_parse_frame()
259 frame->bFrameIntervalType = buffer[25]; in uvc_parse_frame()
261 frame->dwMaxVideoFrameBufferSize = 0; in uvc_parse_frame()
262 frame->dwDefaultFrameInterval = in uvc_parse_frame()
264 frame->bFrameIntervalType = buffer[21]; in uvc_parse_frame()
275 frame->dwFrameInterval = *intervals; in uvc_parse_frame()
295 if (!(format->flags & UVC_FMT_FLAG_COMPRESSED)) in uvc_parse_frame()
296 frame->dwMaxVideoFrameBufferSize = format->bpp * frame->wWidth in uvc_parse_frame()
297 * frame->wHeight / 8; in uvc_parse_frame()
305 maxIntervalIndex = frame->bFrameIntervalType ? n - 1 : 1; in uvc_parse_frame()
306 frame->dwDefaultFrameInterval = in uvc_parse_frame()
307 clamp(frame->dwDefaultFrameInterval, in uvc_parse_frame()
308 frame->dwFrameInterval[0], in uvc_parse_frame()
309 frame->dwFrameInterval[maxIntervalIndex]); in uvc_parse_frame()
316 if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) { in uvc_parse_frame()
317 frame->bFrameIntervalType = 1; in uvc_parse_frame()
318 (*intervals)[0] = frame->dwDefaultFrameInterval; in uvc_parse_frame()
321 uvc_dbg(dev, DESCR, "- %ux%u (%u.%u fps)\n", in uvc_parse_frame()
322 frame->wWidth, frame->wHeight, in uvc_parse_frame()
323 10000000 / frame->dwDefaultFrameInterval, in uvc_parse_frame()
324 (100000000 / frame->dwDefaultFrameInterval) % 10); in uvc_parse_frame()
336 struct usb_host_interface *alts = streaming->intf->cur_altsetting; in uvc_parse_format()
345 format->type = buffer[2]; in uvc_parse_format()
346 format->index = buffer[3]; in uvc_parse_format()
347 format->frames = frames; in uvc_parse_format()
356 dev->udev->devnum, in uvc_parse_format()
357 alts->desc.bInterfaceNumber); in uvc_parse_format()
358 return -EINVAL; in uvc_parse_format()
369 dev_info(&streaming->intf->dev, in uvc_parse_format()
374 format->fcc = fmtdesc->fcc; in uvc_parse_format()
375 format->bpp = buffer[21]; in uvc_parse_format()
381 if (dev->quirks & UVC_QUIRK_FORCE_Y8) { in uvc_parse_format()
382 if (format->fcc == V4L2_PIX_FMT_YUYV) { in uvc_parse_format()
383 format->fcc = V4L2_PIX_FMT_GREY; in uvc_parse_format()
384 format->bpp = 8; in uvc_parse_format()
390 if (dev->quirks & UVC_QUIRK_FORCE_BPP) { in uvc_parse_format()
392 v4l2_format_info(format->fcc); in uvc_parse_format()
395 unsigned int div = info->hdiv * info->vdiv; in uvc_parse_format()
397 n = info->bpp[0] * div; in uvc_parse_format()
398 for (i = 1; i < info->comp_planes; i++) in uvc_parse_format()
399 n += info->bpp[i]; in uvc_parse_format()
401 format->bpp = DIV_ROUND_UP(8 * n, div); in uvc_parse_format()
410 format->flags = UVC_FMT_FLAG_COMPRESSED; in uvc_parse_format()
418 dev->udev->devnum, in uvc_parse_format()
419 alts->desc.bInterfaceNumber); in uvc_parse_format()
420 return -EINVAL; in uvc_parse_format()
423 format->fcc = V4L2_PIX_FMT_MJPEG; in uvc_parse_format()
424 format->flags = UVC_FMT_FLAG_COMPRESSED; in uvc_parse_format()
425 format->bpp = 0; in uvc_parse_format()
433 dev->udev->devnum, in uvc_parse_format()
434 alts->desc.bInterfaceNumber); in uvc_parse_format()
435 return -EINVAL; in uvc_parse_format()
441 dev->udev->devnum, in uvc_parse_format()
442 alts->desc.bInterfaceNumber, buffer[8]); in uvc_parse_format()
443 return -EINVAL; in uvc_parse_format()
446 format->fcc = V4L2_PIX_FMT_DV; in uvc_parse_format()
447 format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM; in uvc_parse_format()
448 format->bpp = 0; in uvc_parse_format()
454 frame->bFrameIntervalType = 1; in uvc_parse_format()
455 frame->dwDefaultFrameInterval = 1; in uvc_parse_format()
456 frame->dwFrameInterval = *intervals; in uvc_parse_format()
458 format->nframes = 1; in uvc_parse_format()
467 dev->udev->devnum, alts->desc.bInterfaceNumber, in uvc_parse_format()
469 return -EINVAL; in uvc_parse_format()
472 uvc_dbg(dev, DESCR, "Found format %p4cc", &format->fcc); in uvc_parse_format()
474 buflen -= buffer[0]; in uvc_parse_format()
484 frame = &frames[format->nframes]; in uvc_parse_format()
490 format->nframes++; in uvc_parse_format()
491 buflen -= ret; in uvc_parse_format()
498 buflen -= buffer[0]; in uvc_parse_format()
504 if (buflen < 6) { in uvc_parse_format()
507 dev->udev->devnum, in uvc_parse_format()
508 alts->desc.bInterfaceNumber); in uvc_parse_format()
509 return -EINVAL; in uvc_parse_format()
512 format->colorspace = uvc_colorspace(buffer[3]); in uvc_parse_format()
513 format->xfer_func = uvc_xfer_func(buffer[4]); in uvc_parse_format()
514 format->ycbcr_enc = uvc_ycbcr_enc(buffer[5]); in uvc_parse_format()
516 buflen -= buffer[0]; in uvc_parse_format()
519 format->colorspace = V4L2_COLORSPACE_SRGB; in uvc_parse_format()
522 return buffer - start; in uvc_parse_format()
531 struct usb_host_interface *alts = &intf->altsetting[0]; in uvc_parse_streaming()
532 const unsigned char *_buffer, *buffer = alts->extra; in uvc_parse_streaming()
533 int _buflen, buflen = alts->extralen; in uvc_parse_streaming()
538 int ret = -EINVAL; in uvc_parse_streaming()
540 if (intf->cur_altsetting->desc.bInterfaceSubClass in uvc_parse_streaming()
544 dev->udev->devnum, in uvc_parse_streaming()
545 intf->altsetting[0].desc.bInterfaceNumber); in uvc_parse_streaming()
546 return -EINVAL; in uvc_parse_streaming()
552 dev->udev->devnum, in uvc_parse_streaming()
553 intf->altsetting[0].desc.bInterfaceNumber); in uvc_parse_streaming()
554 return -EINVAL; in uvc_parse_streaming()
560 return -ENOMEM; in uvc_parse_streaming()
564 * The Pico iMage webcam has its class-specific interface descriptors in uvc_parse_streaming()
568 for (i = 0; i < alts->desc.bNumEndpoints; ++i) { in uvc_parse_streaming()
569 struct usb_host_endpoint *ep = &alts->endpoint[i]; in uvc_parse_streaming()
571 if (ep->extralen == 0) in uvc_parse_streaming()
574 if (ep->extralen > 2 && in uvc_parse_streaming()
575 ep->extra[1] == USB_DT_CS_INTERFACE) { in uvc_parse_streaming()
579 buffer = alts->endpoint[i].extra; in uvc_parse_streaming()
580 buflen = alts->endpoint[i].extralen; in uvc_parse_streaming()
588 buflen -= buffer[0]; in uvc_parse_streaming()
594 "no class-specific streaming interface descriptors found\n"); in uvc_parse_streaming()
601 streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; in uvc_parse_streaming()
606 streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; in uvc_parse_streaming()
613 dev->udev->devnum, alts->desc.bInterfaceNumber); in uvc_parse_streaming()
618 n = buflen >= size ? buffer[size-1] : 0; in uvc_parse_streaming()
623 dev->udev->devnum, alts->desc.bInterfaceNumber); in uvc_parse_streaming()
627 streaming->header.bNumFormats = p; in uvc_parse_streaming()
628 streaming->header.bEndpointAddress = buffer[6]; in uvc_parse_streaming()
630 streaming->header.bmInfo = buffer[7]; in uvc_parse_streaming()
631 streaming->header.bTerminalLink = buffer[8]; in uvc_parse_streaming()
632 streaming->header.bStillCaptureMethod = buffer[9]; in uvc_parse_streaming()
633 streaming->header.bTriggerSupport = buffer[10]; in uvc_parse_streaming()
634 streaming->header.bTriggerUsage = buffer[11]; in uvc_parse_streaming()
636 streaming->header.bTerminalLink = buffer[7]; in uvc_parse_streaming()
638 streaming->header.bControlSize = n; in uvc_parse_streaming()
640 streaming->header.bmaControls = kmemdup(&buffer[size], p * n, in uvc_parse_streaming()
642 if (streaming->header.bmaControls == NULL) { in uvc_parse_streaming()
643 ret = -ENOMEM; in uvc_parse_streaming()
647 buflen -= buffer[0]; in uvc_parse_streaming()
676 dev->udev->devnum, in uvc_parse_streaming()
677 alts->desc.bInterfaceNumber, _buffer[2]); in uvc_parse_streaming()
694 _buflen -= _buffer[0]; in uvc_parse_streaming()
701 dev->udev->devnum, alts->desc.bInterfaceNumber); in uvc_parse_streaming()
717 ret = -ENOMEM; in uvc_parse_streaming()
726 streaming->formats = format; in uvc_parse_streaming()
727 streaming->nformats = 0; in uvc_parse_streaming()
743 streaming->nformats++; in uvc_parse_streaming()
744 frame += format->nframes; in uvc_parse_streaming()
747 buflen -= ret; in uvc_parse_streaming()
755 buflen -= buffer[0]; in uvc_parse_streaming()
762 dev->udev->devnum, alts->desc.bInterfaceNumber, buflen); in uvc_parse_streaming()
765 for (i = 0; i < intf->num_altsetting; ++i) { in uvc_parse_streaming()
768 alts = &intf->altsetting[i]; in uvc_parse_streaming()
770 streaming->header.bEndpointAddress); in uvc_parse_streaming()
773 psize = uvc_endpoint_max_bpi(dev->udev, ep); in uvc_parse_streaming()
774 if (psize > streaming->maxpsize) in uvc_parse_streaming()
775 streaming->maxpsize = psize; in uvc_parse_streaming()
778 list_add_tail(&streaming->list, &dev->streams); in uvc_parse_streaming()
801 extra_size = roundup(extra_size, sizeof(*entity->pads)); in uvc_alloc_entity()
803 num_inputs = type & UVC_TERM_OUTPUT ? num_pads : num_pads - 1; in uvc_alloc_entity()
806 size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads in uvc_alloc_entity()
812 entity->id = id; in uvc_alloc_entity()
813 entity->type = type; in uvc_alloc_entity()
821 memcpy(entity->guid, uvc_gpio_guid, 16); in uvc_alloc_entity()
824 memcpy(entity->guid, uvc_camera_guid, 16); in uvc_alloc_entity()
827 memcpy(entity->guid, uvc_media_transport_input_guid, 16); in uvc_alloc_entity()
830 memcpy(entity->guid, uvc_processing_guid, 16); in uvc_alloc_entity()
834 entity->num_links = 0; in uvc_alloc_entity()
835 entity->num_pads = num_pads; in uvc_alloc_entity()
836 entity->pads = ((void *)(entity + 1)) + extra_size; in uvc_alloc_entity()
839 entity->pads[i].flags = MEDIA_PAD_FL_SINK; in uvc_alloc_entity()
841 entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE; in uvc_alloc_entity()
843 entity->bNrInPins = num_inputs; in uvc_alloc_entity()
844 entity->baSourceID = (u8 *)(&entity->pads[num_pads]); in uvc_alloc_entity()
861 ret = usb_string(dev->udev, string_id, entity->name, in uvc_entity_set_name()
862 sizeof(entity->name)); in uvc_entity_set_name()
867 sprintf(entity->name, "%s %u", type_name, entity->id); in uvc_entity_set_name()
870 /* Parse vendor-specific extensions. */
874 struct usb_device *udev = dev->udev; in uvc_parse_vendor_control()
875 struct usb_host_interface *alts = dev->intf->cur_altsetting; in uvc_parse_vendor_control()
880 switch (le16_to_cpu(dev->udev->descriptor.idVendor)) { in uvc_parse_vendor_control()
894 * ---------------------------------------------------------- in uvc_parse_vendor_control()
897 * ---------------------------------------------------------- in uvc_parse_vendor_control()
904 * ---------------------------------------------------------- in uvc_parse_vendor_control()
906 * ---------------------------------------------------------- in uvc_parse_vendor_control()
910 * ---------------------------------------------------------- in uvc_parse_vendor_control()
918 udev->devnum, alts->desc.bInterfaceNumber); in uvc_parse_vendor_control()
925 return -ENOMEM; in uvc_parse_vendor_control()
927 memcpy(unit->guid, &buffer[4], 16); in uvc_parse_vendor_control()
928 unit->extension.bNumControls = buffer[20]; in uvc_parse_vendor_control()
929 memcpy(unit->baSourceID, &buffer[22], p); in uvc_parse_vendor_control()
930 unit->extension.bControlSize = buffer[22+p]; in uvc_parse_vendor_control()
931 unit->extension.bmControls = (u8 *)unit + sizeof(*unit); in uvc_parse_vendor_control()
932 unit->extension.bmControlsType = (u8 *)unit + sizeof(*unit) in uvc_parse_vendor_control()
934 memcpy(unit->extension.bmControls, &buffer[23+p], 2*n); in uvc_parse_vendor_control()
938 list_add_tail(&unit->list, &dev->entities); in uvc_parse_vendor_control()
949 struct usb_device *udev = dev->udev; in uvc_parse_standard_control()
952 struct usb_host_interface *alts = dev->intf->cur_altsetting; in uvc_parse_standard_control()
964 udev->devnum, alts->desc.bInterfaceNumber); in uvc_parse_standard_control()
965 return -EINVAL; in uvc_parse_standard_control()
968 dev->uvc_version = get_unaligned_le16(&buffer[3]); in uvc_parse_standard_control()
969 dev->clock_frequency = get_unaligned_le32(&buffer[7]); in uvc_parse_standard_control()
977 udev->devnum, i); in uvc_parse_standard_control()
989 udev->devnum, alts->desc.bInterfaceNumber); in uvc_parse_standard_control()
990 return -EINVAL; in uvc_parse_standard_control()
996 * - The high byte must be non-zero, otherwise it would be in uvc_parse_standard_control()
999 * - Bit 15 must be 0, as we use it internally as a terminal in uvc_parse_standard_control()
1008 udev->devnum, alts->desc.bInterfaceNumber, in uvc_parse_standard_control()
1030 udev->devnum, alts->desc.bInterfaceNumber); in uvc_parse_standard_control()
1031 return -EINVAL; in uvc_parse_standard_control()
1037 return -ENOMEM; in uvc_parse_standard_control()
1040 term->camera.bControlSize = n; in uvc_parse_standard_control()
1041 term->camera.bmControls = (u8 *)term + sizeof(*term); in uvc_parse_standard_control()
1042 term->camera.wObjectiveFocalLengthMin = in uvc_parse_standard_control()
1044 term->camera.wObjectiveFocalLengthMax = in uvc_parse_standard_control()
1046 term->camera.wOcularFocalLength = in uvc_parse_standard_control()
1048 memcpy(term->camera.bmControls, &buffer[15], n); in uvc_parse_standard_control()
1051 term->media.bControlSize = n; in uvc_parse_standard_control()
1052 term->media.bmControls = (u8 *)term + sizeof(*term); in uvc_parse_standard_control()
1053 term->media.bTransportModeSize = p; in uvc_parse_standard_control()
1054 term->media.bmTransportModes = (u8 *)term in uvc_parse_standard_control()
1056 memcpy(term->media.bmControls, &buffer[9], n); in uvc_parse_standard_control()
1057 memcpy(term->media.bmTransportModes, &buffer[10+n], p); in uvc_parse_standard_control()
1069 list_add_tail(&term->list, &dev->entities); in uvc_parse_standard_control()
1076 udev->devnum, alts->desc.bInterfaceNumber); in uvc_parse_standard_control()
1077 return -EINVAL; in uvc_parse_standard_control()
1088 udev->devnum, alts->desc.bInterfaceNumber, in uvc_parse_standard_control()
1096 return -ENOMEM; in uvc_parse_standard_control()
1098 memcpy(term->baSourceID, &buffer[7], 1); in uvc_parse_standard_control()
1102 list_add_tail(&term->list, &dev->entities); in uvc_parse_standard_control()
1108 if (buflen < 5 || buflen < 6 + p) { in uvc_parse_standard_control()
1111 udev->devnum, alts->desc.bInterfaceNumber); in uvc_parse_standard_control()
1112 return -EINVAL; in uvc_parse_standard_control()
1117 return -ENOMEM; in uvc_parse_standard_control()
1119 memcpy(unit->baSourceID, &buffer[5], p); in uvc_parse_standard_control()
1123 list_add_tail(&unit->list, &dev->entities); in uvc_parse_standard_control()
1128 p = dev->uvc_version >= 0x0110 ? 10 : 9; in uvc_parse_standard_control()
1133 udev->devnum, alts->desc.bInterfaceNumber); in uvc_parse_standard_control()
1134 return -EINVAL; in uvc_parse_standard_control()
1139 return -ENOMEM; in uvc_parse_standard_control()
1141 memcpy(unit->baSourceID, &buffer[4], 1); in uvc_parse_standard_control()
1142 unit->processing.wMaxMultiplier = in uvc_parse_standard_control()
1144 unit->processing.bControlSize = buffer[7]; in uvc_parse_standard_control()
1145 unit->processing.bmControls = (u8 *)unit + sizeof(*unit); in uvc_parse_standard_control()
1146 memcpy(unit->processing.bmControls, &buffer[8], n); in uvc_parse_standard_control()
1147 if (dev->uvc_version >= 0x0110) in uvc_parse_standard_control()
1148 unit->processing.bmVideoStandards = buffer[9+n]; in uvc_parse_standard_control()
1152 list_add_tail(&unit->list, &dev->entities); in uvc_parse_standard_control()
1162 udev->devnum, alts->desc.bInterfaceNumber); in uvc_parse_standard_control()
1163 return -EINVAL; in uvc_parse_standard_control()
1168 return -ENOMEM; in uvc_parse_standard_control()
1170 memcpy(unit->guid, &buffer[4], 16); in uvc_parse_standard_control()
1171 unit->extension.bNumControls = buffer[20]; in uvc_parse_standard_control()
1172 memcpy(unit->baSourceID, &buffer[22], p); in uvc_parse_standard_control()
1173 unit->extension.bControlSize = buffer[22+p]; in uvc_parse_standard_control()
1174 unit->extension.bmControls = (u8 *)unit + sizeof(*unit); in uvc_parse_standard_control()
1175 memcpy(unit->extension.bmControls, &buffer[23+p], n); in uvc_parse_standard_control()
1179 list_add_tail(&unit->list, &dev->entities); in uvc_parse_standard_control()
1194 struct usb_host_interface *alts = dev->intf->cur_altsetting; in uvc_parse_control()
1195 const unsigned char *buffer = alts->extra; in uvc_parse_control()
1196 int buflen = alts->extralen; in uvc_parse_control()
1215 buflen -= buffer[0]; in uvc_parse_control()
1220 * Check if the optional status endpoint is present. Built-in iSight in uvc_parse_control()
1225 if (alts->desc.bNumEndpoints == 1 && in uvc_parse_control()
1226 !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) { in uvc_parse_control()
1227 struct usb_host_endpoint *ep = &alts->endpoint[0]; in uvc_parse_control()
1228 struct usb_endpoint_descriptor *desc = &ep->desc; in uvc_parse_control()
1231 le16_to_cpu(desc->wMaxPacketSize) >= 8 && in uvc_parse_control()
1232 desc->bInterval != 0) { in uvc_parse_control()
1235 desc->bEndpointAddress); in uvc_parse_control()
1236 dev->int_ep = ep; in uvc_parse_control()
1243 /* -----------------------------------------------------------------------------
1249 struct uvc_entity *unit = dev->gpio_unit; in uvc_gpio_event()
1256 new_val = gpiod_get_value_cansleep(unit->gpio.gpio_privacy); in uvc_gpio_event()
1259 chain = list_first_entry(&dev->chains, struct uvc_video_chain, list); in uvc_gpio_event()
1260 uvc_ctrl_status_event(chain, unit->controls, &new_val); in uvc_gpio_event()
1267 return -EINVAL; in uvc_gpio_get_cur()
1269 *(u8 *)data = gpiod_get_value_cansleep(entity->gpio.gpio_privacy); in uvc_gpio_get_cur()
1278 return -EINVAL; in uvc_gpio_get_info()
1298 gpio_privacy = devm_gpiod_get_optional(&dev->intf->dev, "privacy", in uvc_gpio_parse()
1305 return dev_err_probe(&dev->intf->dev, irq, in uvc_gpio_parse()
1310 return -ENOMEM; in uvc_gpio_parse()
1312 unit->gpio.gpio_privacy = gpio_privacy; in uvc_gpio_parse()
1313 unit->gpio.irq = irq; in uvc_gpio_parse()
1314 unit->gpio.bControlSize = 1; in uvc_gpio_parse()
1315 unit->gpio.bmControls = (u8 *)unit + sizeof(*unit); in uvc_gpio_parse()
1316 unit->gpio.bmControls[0] = 1; in uvc_gpio_parse()
1317 unit->get_cur = uvc_gpio_get_cur; in uvc_gpio_parse()
1318 unit->get_info = uvc_gpio_get_info; in uvc_gpio_parse()
1319 strscpy(unit->name, "GPIO", sizeof(unit->name)); in uvc_gpio_parse()
1321 list_add_tail(&unit->list, &dev->entities); in uvc_gpio_parse()
1323 dev->gpio_unit = unit; in uvc_gpio_parse()
1330 struct uvc_entity *unit = dev->gpio_unit; in uvc_gpio_init_irq()
1333 if (!unit || unit->gpio.irq < 0) in uvc_gpio_init_irq()
1336 ret = request_threaded_irq(unit->gpio.irq, NULL, uvc_gpio_irq, in uvc_gpio_init_irq()
1341 unit->gpio.initialized = !ret; in uvc_gpio_init_irq()
1348 if (!dev->gpio_unit || !dev->gpio_unit->gpio.initialized) in uvc_gpio_deinit()
1351 free_irq(dev->gpio_unit->gpio.irq, dev); in uvc_gpio_deinit()
1354 /* ------------------------------------------------------------------------
1362 * - one or more Output Terminals (USB Streaming or Display)
1363 * - zero or one Processing Unit
1364 * - zero, one or more single-input Selector Units
1365 * - zero or one multiple-input Selector Units, provided all inputs are
1367 * - zero, one or mode single-input Extension Units
1368 * - one or more Input Terminals (Camera, External or USB Streaming)
1372 * ITT_*(0) -> +---------+ +---------+ +---------+ -> TT_STREAMING(0)
1373 * ... | SU{0,1} | -> | PU{0,1} | -> | XU{0,n} | ...
1374 * ITT_*(n) -> +---------+ +---------+ +---------+ -> TT_STREAMING(n)
1376 * +---------+ +---------+ -> OTT_*(0)
1377 * TT_STREAMING -> | PU{0,1} | -> | XU{0,n} | ...
1378 * +---------+ +---------+ -> OTT_*(n)
1381 * Extension Units connected to the main chain as single-unit branches are
1382 * also supported. Single-input Selector Units are ignored.
1389 uvc_dbg_cont(PROBE, " <- XU %d", entity->id); in uvc_scan_chain_entity()
1391 if (entity->bNrInPins != 1) { in uvc_scan_chain_entity()
1392 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain_entity()
1394 entity->id); in uvc_scan_chain_entity()
1395 return -1; in uvc_scan_chain_entity()
1401 uvc_dbg_cont(PROBE, " <- PU %d", entity->id); in uvc_scan_chain_entity()
1403 if (chain->processing != NULL) { in uvc_scan_chain_entity()
1404 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain_entity()
1406 return -1; in uvc_scan_chain_entity()
1409 chain->processing = entity; in uvc_scan_chain_entity()
1413 uvc_dbg_cont(PROBE, " <- SU %d", entity->id); in uvc_scan_chain_entity()
1415 /* Single-input selector units are ignored. */ in uvc_scan_chain_entity()
1416 if (entity->bNrInPins == 1) in uvc_scan_chain_entity()
1419 if (chain->selector != NULL) { in uvc_scan_chain_entity()
1420 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain_entity()
1422 return -1; in uvc_scan_chain_entity()
1425 chain->selector = entity; in uvc_scan_chain_entity()
1431 uvc_dbg_cont(PROBE, " <- IT %d\n", entity->id); in uvc_scan_chain_entity()
1438 uvc_dbg_cont(PROBE, " OT %d", entity->id); in uvc_scan_chain_entity()
1444 uvc_dbg_cont(PROBE, " <- IT %d\n", entity->id); in uvc_scan_chain_entity()
1446 uvc_dbg_cont(PROBE, " OT %d", entity->id); in uvc_scan_chain_entity()
1451 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain_entity()
1454 return -1; in uvc_scan_chain_entity()
1457 list_add_tail(&entity->chain, &chain->entities); in uvc_scan_chain_entity()
1472 forward = uvc_entity_by_reference(chain->dev, entity->id, in uvc_scan_chain_forward()
1478 if (forward->chain.next || forward->chain.prev) { in uvc_scan_chain_forward()
1479 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain_forward()
1481 forward->id); in uvc_scan_chain_forward()
1482 return -EINVAL; in uvc_scan_chain_forward()
1487 if (forward->bNrInPins != 1) { in uvc_scan_chain_forward()
1488 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain_forward()
1490 forward->id); in uvc_scan_chain_forward()
1491 return -EINVAL; in uvc_scan_chain_forward()
1507 source = uvc_entity_by_id(chain->dev, in uvc_scan_chain_forward()
1508 entity->baSourceID[0]); in uvc_scan_chain_forward()
1510 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain_forward()
1512 forward->id); in uvc_scan_chain_forward()
1516 forward->baSourceID[0] = source->id; in uvc_scan_chain_forward()
1519 list_add_tail(&forward->chain, &chain->entities); in uvc_scan_chain_forward()
1521 uvc_dbg_cont(PROBE, " (->"); in uvc_scan_chain_forward()
1523 uvc_dbg_cont(PROBE, " XU %d", forward->id); in uvc_scan_chain_forward()
1532 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain_forward()
1534 forward->id); in uvc_scan_chain_forward()
1535 return -EINVAL; in uvc_scan_chain_forward()
1539 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain_forward()
1541 entity->id, forward->id); in uvc_scan_chain_forward()
1545 list_add_tail(&forward->chain, &chain->entities); in uvc_scan_chain_forward()
1547 uvc_dbg_cont(PROBE, " (->"); in uvc_scan_chain_forward()
1549 uvc_dbg_cont(PROBE, " OT %d", forward->id); in uvc_scan_chain_forward()
1565 int id = -EINVAL, i; in uvc_scan_chain_backward()
1570 id = entity->baSourceID[0]; in uvc_scan_chain_backward()
1574 /* Single-input selector units are ignored. */ in uvc_scan_chain_backward()
1575 if (entity->bNrInPins == 1) { in uvc_scan_chain_backward()
1576 id = entity->baSourceID[0]; in uvc_scan_chain_backward()
1580 uvc_dbg_cont(PROBE, " <- IT"); in uvc_scan_chain_backward()
1582 chain->selector = entity; in uvc_scan_chain_backward()
1583 for (i = 0; i < entity->bNrInPins; ++i) { in uvc_scan_chain_backward()
1584 id = entity->baSourceID[i]; in uvc_scan_chain_backward()
1585 term = uvc_entity_by_id(chain->dev, id); in uvc_scan_chain_backward()
1587 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain_backward()
1589 entity->id, i); in uvc_scan_chain_backward()
1590 return -1; in uvc_scan_chain_backward()
1593 if (term->chain.next || term->chain.prev) { in uvc_scan_chain_backward()
1594 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain_backward()
1596 term->id); in uvc_scan_chain_backward()
1597 return -EINVAL; in uvc_scan_chain_backward()
1600 uvc_dbg_cont(PROBE, " %d", term->id); in uvc_scan_chain_backward()
1602 list_add_tail(&term->chain, &chain->entities); in uvc_scan_chain_backward()
1618 id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0; in uvc_scan_chain_backward()
1627 entity = uvc_entity_by_id(chain->dev, id); in uvc_scan_chain_backward()
1629 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain_backward()
1631 return -EINVAL; in uvc_scan_chain_backward()
1643 uvc_dbg(chain->dev, PROBE, "Scanning UVC chain:"); in uvc_scan_chain()
1650 if (entity->chain.next || entity->chain.prev) { in uvc_scan_chain()
1651 uvc_dbg(chain->dev, DESCR, in uvc_scan_chain()
1653 entity->id); in uvc_scan_chain()
1654 return -EINVAL; in uvc_scan_chain()
1659 return -EINVAL; in uvc_scan_chain()
1663 return -EINVAL; in uvc_scan_chain()
1668 return -EINVAL; in uvc_scan_chain()
1692 p += sprintf(p, "%u", term->id); in uvc_print_terms()
1695 return p - buffer; in uvc_print_terms()
1703 p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p); in uvc_print_chain()
1704 p += sprintf(p, " -> "); in uvc_print_chain()
1705 uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p); in uvc_print_chain()
1718 INIT_LIST_HEAD(&chain->entities); in uvc_alloc_chain()
1719 mutex_init(&chain->ctrl_mutex); in uvc_alloc_chain()
1720 chain->dev = dev; in uvc_alloc_chain()
1721 v4l2_prio_init(&chain->prio); in uvc_alloc_chain()
1736 * - Acer Integrated Camera (5986:055a)
1737 * - Realtek rtl157a7 (0bda:57a7)
1751 list_for_each_entry(entity, &dev->entities, list) { in uvc_scan_fallback()
1754 return -EINVAL; in uvc_scan_fallback()
1760 return -EINVAL; in uvc_scan_fallback()
1766 return -EINVAL; in uvc_scan_fallback()
1771 return -ENOMEM; in uvc_scan_fallback()
1785 list_for_each_entry_reverse(entity, &dev->entities, list) { in uvc_scan_fallback()
1786 if (entity->type != UVC_VC_PROCESSING_UNIT && in uvc_scan_fallback()
1787 entity->type != UVC_VC_EXTENSION_UNIT) in uvc_scan_fallback()
1790 if (entity->num_pads != 2) in uvc_scan_fallback()
1796 prev->baSourceID[0] = entity->id; in uvc_scan_fallback()
1803 prev->baSourceID[0] = iterm->id; in uvc_scan_fallback()
1805 list_add_tail(&chain->list, &dev->chains); in uvc_scan_fallback()
1814 return -EINVAL; in uvc_scan_fallback()
1827 list_for_each_entry(term, &dev->entities, list) { in uvc_scan_device()
1837 if (term->chain.next || term->chain.prev) in uvc_scan_device()
1842 return -ENOMEM; in uvc_scan_device()
1844 term->flags |= UVC_ENTITY_FLAG_DEFAULT; in uvc_scan_device()
1854 list_add_tail(&chain->list, &dev->chains); in uvc_scan_device()
1857 if (list_empty(&dev->chains)) in uvc_scan_device()
1860 if (list_empty(&dev->chains)) { in uvc_scan_device()
1861 dev_info(&dev->udev->dev, "No valid video chain found.\n"); in uvc_scan_device()
1862 return -1; in uvc_scan_device()
1866 if (dev->gpio_unit) { in uvc_scan_device()
1867 chain = list_first_entry(&dev->chains, in uvc_scan_device()
1869 list_add_tail(&dev->gpio_unit->chain, &chain->entities); in uvc_scan_device()
1875 /* ------------------------------------------------------------------------
1897 usb_put_intf(dev->intf); in uvc_delete()
1898 usb_put_dev(dev->udev); in uvc_delete()
1901 media_device_cleanup(&dev->mdev); in uvc_delete()
1904 list_for_each_safe(p, n, &dev->chains) { in uvc_delete()
1911 list_for_each_safe(p, n, &dev->entities) { in uvc_delete()
1921 list_for_each_safe(p, n, &dev->streams) { in uvc_delete()
1926 streaming->intf); in uvc_delete()
1936 struct uvc_device *dev = stream->dev; in uvc_release()
1938 kref_put(&dev->ref, uvc_delete); in uvc_release()
1950 list_for_each_entry(stream, &dev->streams, list) { in uvc_unregister_video()
1952 if (!video_is_registered(&stream->vdev)) in uvc_unregister_video()
1956 * For stream->vdev we follow the same logic as: in uvc_unregister_video()
1961 get_device(&stream->vdev.dev); in uvc_unregister_video()
1964 video_unregister_device(&stream->vdev); in uvc_unregister_video()
1967 mutex_lock(&stream->mutex); in uvc_unregister_video()
1970 uvc_queue_release(&stream->queue); in uvc_unregister_video()
1972 mutex_unlock(&stream->mutex); in uvc_unregister_video()
1974 put_device(&stream->vdev.dev); in uvc_unregister_video()
1977 * For stream->meta.vdev we can directly call: in uvc_unregister_video()
1980 vb2_video_unregister_device(&stream->meta.vdev); in uvc_unregister_video()
1984 * return -ENODEV. in uvc_unregister_video()
1992 if (dev->vdev.dev) in uvc_unregister_video()
1993 v4l2_device_unregister(&dev->vdev); in uvc_unregister_video()
1995 if (media_devnode_is_registered(dev->mdev.devnode)) in uvc_unregister_video()
1996 media_device_unregister(&dev->mdev); in uvc_unregister_video()
2018 * We already hold a reference to dev->udev. The video device will be in uvc_register_video_device()
2022 vdev->v4l2_dev = &dev->vdev; in uvc_register_video_device()
2023 vdev->fops = fops; in uvc_register_video_device()
2024 vdev->ioctl_ops = ioctl_ops; in uvc_register_video_device()
2025 vdev->release = uvc_release; in uvc_register_video_device()
2026 vdev->prio = &stream->chain->prio; in uvc_register_video_device()
2028 vdev->vfl_dir = VFL_DIR_TX; in uvc_register_video_device()
2030 vdev->vfl_dir = VFL_DIR_RX; in uvc_register_video_device()
2035 vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; in uvc_register_video_device()
2038 vdev->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; in uvc_register_video_device()
2041 vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING; in uvc_register_video_device()
2045 strscpy(vdev->name, dev->name, sizeof(vdev->name)); in uvc_register_video_device()
2053 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); in uvc_register_video_device()
2055 dev_err(&stream->intf->dev, in uvc_register_video_device()
2061 kref_get(&dev->ref); in uvc_register_video_device()
2073 dev_err(&stream->intf->dev, in uvc_register_video()
2078 if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) in uvc_register_video()
2079 stream->chain->caps |= V4L2_CAP_VIDEO_CAPTURE in uvc_register_video()
2082 stream->chain->caps |= V4L2_CAP_VIDEO_OUTPUT; in uvc_register_video()
2087 return uvc_register_video_device(dev, stream, &stream->vdev, in uvc_register_video()
2088 &stream->queue, stream->type, in uvc_register_video()
2102 list_for_each_entry(term, &chain->entities, chain) { in uvc_register_terms()
2106 stream = uvc_stream_by_id(dev, term->id); in uvc_register_terms()
2108 dev_info(&dev->udev->dev, in uvc_register_terms()
2110 term->id); in uvc_register_terms()
2114 stream->chain = chain; in uvc_register_terms()
2125 term->vdev = &stream->vdev; in uvc_register_terms()
2136 list_for_each_entry(chain, &dev->chains, list) { in uvc_register_chains()
2144 dev_info(&dev->udev->dev, in uvc_register_chains()
2152 /* ------------------------------------------------------------------------
2164 (const struct uvc_device_info *)id->driver_info; in uvc_probe()
2171 return -ENOMEM; in uvc_probe()
2173 INIT_LIST_HEAD(&dev->entities); in uvc_probe()
2174 INIT_LIST_HEAD(&dev->chains); in uvc_probe()
2175 INIT_LIST_HEAD(&dev->streams); in uvc_probe()
2176 kref_init(&dev->ref); in uvc_probe()
2177 atomic_set(&dev->nmappings, 0); in uvc_probe()
2179 dev->udev = usb_get_dev(udev); in uvc_probe()
2180 dev->intf = usb_get_intf(intf); in uvc_probe()
2181 dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; in uvc_probe()
2182 dev->info = info ? info : &uvc_quirk_none; in uvc_probe()
2183 dev->quirks = uvc_quirks_param == -1 in uvc_probe()
2184 ? dev->info->quirks : uvc_quirks_param; in uvc_probe()
2186 if (id->idVendor && id->idProduct) in uvc_probe()
2188 udev->devpath, id->idVendor, id->idProduct); in uvc_probe()
2191 udev->devpath); in uvc_probe()
2193 if (udev->product != NULL) in uvc_probe()
2194 strscpy(dev->name, udev->product, sizeof(dev->name)); in uvc_probe()
2196 snprintf(dev->name, sizeof(dev->name), in uvc_probe()
2198 le16_to_cpu(udev->descriptor.idVendor), in uvc_probe()
2199 le16_to_cpu(udev->descriptor.idProduct)); in uvc_probe()
2206 if (intf->intf_assoc && intf->intf_assoc->iFunction != 0) in uvc_probe()
2207 function = intf->intf_assoc->iFunction; in uvc_probe()
2209 function = intf->cur_altsetting->desc.iInterface; in uvc_probe()
2213 strlcat(dev->name, ": ", sizeof(dev->name)); in uvc_probe()
2214 len = strlen(dev->name); in uvc_probe()
2215 usb_string(udev, function, dev->name + len, in uvc_probe()
2216 sizeof(dev->name) - len); in uvc_probe()
2221 dev->mdev.dev = &intf->dev; in uvc_probe()
2222 strscpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); in uvc_probe()
2223 if (udev->serial) in uvc_probe()
2224 strscpy(dev->mdev.serial, udev->serial, in uvc_probe()
2225 sizeof(dev->mdev.serial)); in uvc_probe()
2226 usb_make_path(udev, dev->mdev.bus_info, sizeof(dev->mdev.bus_info)); in uvc_probe()
2227 dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); in uvc_probe()
2228 media_device_init(&dev->mdev); in uvc_probe()
2230 dev->vdev.mdev = &dev->mdev; in uvc_probe()
2245 dev_info(&dev->udev->dev, "Found UVC %u.%02x device %s (%04x:%04x)\n", in uvc_probe()
2246 dev->uvc_version >> 8, dev->uvc_version & 0xff, in uvc_probe()
2247 udev->product ? udev->product : "<unnamed>", in uvc_probe()
2248 le16_to_cpu(udev->descriptor.idVendor), in uvc_probe()
2249 le16_to_cpu(udev->descriptor.idProduct)); in uvc_probe()
2251 if (dev->quirks != dev->info->quirks) { in uvc_probe()
2252 dev_info(&dev->udev->dev, in uvc_probe()
2254 dev->quirks); in uvc_probe()
2255 dev_info(&dev->udev->dev, in uvc_probe()
2256 "Please report required quirks to the linux-media mailing list.\n"); in uvc_probe()
2259 if (dev->info->uvc_version) { in uvc_probe()
2260 dev->uvc_version = dev->info->uvc_version; in uvc_probe()
2261 dev_info(&dev->udev->dev, "Forcing UVC version to %u.%02x\n", in uvc_probe()
2262 dev->uvc_version >> 8, dev->uvc_version & 0xff); in uvc_probe()
2266 if (v4l2_device_register(&intf->dev, &dev->vdev) < 0) in uvc_probe()
2283 if (media_device_register(&dev->mdev) < 0) in uvc_probe()
2292 dev_info(&dev->udev->dev, in uvc_probe()
2299 dev_err(&dev->udev->dev, in uvc_probe()
2304 if (dev->quirks & UVC_QUIRK_NO_RESET_RESUME) in uvc_probe()
2305 udev->quirks &= ~USB_QUIRK_RESET_RESUME; in uvc_probe()
2307 if (!(dev->quirks & UVC_QUIRK_DISABLE_AUTOSUSPEND)) in uvc_probe()
2316 kref_put(&dev->ref, uvc_delete); in uvc_probe()
2317 return -ENODEV; in uvc_probe()
2330 if (intf->cur_altsetting->desc.bInterfaceSubClass == in uvc_disconnect()
2335 kref_put(&dev->ref, uvc_delete); in uvc_disconnect()
2344 intf->cur_altsetting->desc.bInterfaceNumber); in uvc_suspend()
2347 if (intf->cur_altsetting->desc.bInterfaceSubClass == in uvc_suspend()
2353 list_for_each_entry(stream, &dev->streams, list) { in uvc_suspend()
2354 if (stream->intf == intf) in uvc_suspend()
2360 return -EINVAL; in uvc_suspend()
2370 intf->cur_altsetting->desc.bInterfaceNumber); in __uvc_resume()
2372 if (intf->cur_altsetting->desc.bInterfaceSubClass == in __uvc_resume()
2383 list_for_each_entry(stream, &dev->streams, list) { in __uvc_resume()
2384 if (stream->intf == intf) { in __uvc_resume()
2387 uvc_queue_streamoff(&stream->queue, in __uvc_resume()
2388 stream->queue.queue.type); in __uvc_resume()
2395 return -EINVAL; in __uvc_resume()
2408 /* ------------------------------------------------------------------------
2430 return -EINVAL; in uvc_clock_param_set()
2466 /* ------------------------------------------------------------------------
2542 /* Microsoft Lifecam NX-6000 */
2551 /* Microsoft Lifecam NX-3000 */
2560 /* Microsoft Lifecam VX-7000 */
2744 /* Apple Built-In iSight */
2754 /* Apple FaceTime HD Camera (Built-In) */
2763 /* Apple Built-In iSight via iBridge */
2808 /* ViMicro - Minoru3D */
2817 /* ViMicro Venus - Minoru3D */
2826 /* Ophir Optronics - SPCAM 620U */
2835 /* Sonix Technology Co. Ltd. - 292A IPC AR0330 */
2881 /* Syntek (HP Spartan) */
2980 /* Manta MM-353 Plako */
3065 /* Actions Microelectronics Co. Display capture-UVC05 */