forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/media/usb/uvc/uvc_video.c
....@@ -1,14 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * uvc_video.c -- USB Video Class driver - Video handling
34 *
45 * Copyright (C) 2005-2010
56 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
127 */
138
149 #include <linux/kernel.h>
....@@ -25,6 +20,7 @@
2520 #include <media/v4l2-common.h>
2621
2722 #include "uvcvideo.h"
23
+#include <soc/rockchip/rockchip-system-status.h>
2824
2925 /* ------------------------------------------------------------------------
3026 * UVC Controls
....@@ -659,7 +655,7 @@
659655 * to avoid losing precision in the division. Similarly, the host timestamp is
660656 * computed with
661657 *
662
- * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1) (2)
658
+ * TS = ((TS2 - TS1) * SOF + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1) (2)
663659 *
664660 * SOF values are coded on 11 bits by USB. We extend their precision with 16
665661 * decimal bits, leading to a 11.16 coding.
....@@ -802,9 +798,9 @@
802798 unsigned int header_size;
803799 bool has_pts = false;
804800 bool has_scr = false;
805
- u16 uninitialized_var(scr_sof);
806
- u32 uninitialized_var(scr_stc);
807
- u32 uninitialized_var(pts);
801
+ u16 scr_sof;
802
+ u32 scr_stc;
803
+ u32 pts;
808804
809805 if (stream->stats.stream.nb_frames == 0 &&
810806 stream->stats.frame.nb_packets == 0)
....@@ -1313,7 +1309,9 @@
13131309 if (has_scr)
13141310 memcpy(stream->clock.last_scr, scr, 6);
13151311
1316
- memcpy(&meta->length, mem, length);
1312
+ meta->length = mem[0];
1313
+ meta->flags = mem[1];
1314
+ memcpy(meta->buf, &mem[2], length - 2);
13171315 meta_buf->bytesused += length + sizeof(meta->ns) + sizeof(meta->sof);
13181316
13191317 uvc_trace(UVC_TRACE_FRAME,
....@@ -1546,11 +1544,11 @@
15461544 default:
15471545 uvc_printk(KERN_WARNING, "Non-zero status (%d) in video "
15481546 "completion handler.\n", urb->status);
1549
- /* fall through */
1547
+ fallthrough;
15501548 case -ENOENT: /* usb_poison_urb() called. */
15511549 if (stream->frozen)
15521550 return;
1553
- /* fall through */
1551
+ fallthrough;
15541552 case -ECONNRESET: /* usb_unlink_urb() called. */
15551553 case -ESHUTDOWN: /* The endpoint is being disabled. */
15561554 uvc_queue_cancel(queue, urb->status == -ESHUTDOWN);
....@@ -1596,20 +1594,19 @@
15961594 */
15971595 static void uvc_free_urb_buffers(struct uvc_streaming *stream)
15981596 {
1599
- unsigned int i;
1597
+ struct uvc_urb *uvc_urb;
16001598
1601
- for (i = 0; i < UVC_URBS; ++i) {
1602
- struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
1599
+ for_each_uvc_urb(uvc_urb, stream) {
1600
+ if (!uvc_urb->buffer)
1601
+ continue;
16031602
1604
- if (uvc_urb->buffer) {
16051603 #ifndef CONFIG_DMA_NONCOHERENT
1606
- usb_free_coherent(stream->dev->udev, stream->urb_size,
1607
- uvc_urb->buffer, uvc_urb->dma);
1604
+ usb_free_coherent(stream->dev->udev, stream->urb_size,
1605
+ uvc_urb->buffer, uvc_urb->dma);
16081606 #else
1609
- kfree(uvc_urb->buffer);
1607
+ kfree(uvc_urb->buffer);
16101608 #endif
1611
- uvc_urb->buffer = NULL;
1612
- }
1609
+ uvc_urb->buffer = NULL;
16131610 }
16141611
16151612 stream->urb_size = 0;
....@@ -1681,7 +1678,8 @@
16811678 /*
16821679 * Uninitialize isochronous/bulk URBs and free transfer buffers.
16831680 */
1684
-static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
1681
+static void uvc_video_stop_transfer(struct uvc_streaming *stream,
1682
+ int free_buffers)
16851683 {
16861684 struct uvc_urb *uvc_urb;
16871685
....@@ -1740,7 +1738,8 @@
17401738 struct usb_host_endpoint *ep, gfp_t gfp_flags)
17411739 {
17421740 struct urb *urb;
1743
- unsigned int npackets, i, j;
1741
+ struct uvc_urb *uvc_urb;
1742
+ unsigned int npackets, i;
17441743 u16 psize;
17451744 u32 size;
17461745
....@@ -1753,12 +1752,10 @@
17531752
17541753 size = npackets * psize;
17551754
1756
- for (i = 0; i < UVC_URBS; ++i) {
1757
- struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
1758
-
1755
+ for_each_uvc_urb(uvc_urb, stream) {
17591756 urb = usb_alloc_urb(npackets, gfp_flags);
17601757 if (urb == NULL) {
1761
- uvc_uninit_video(stream, 1);
1758
+ uvc_video_stop_transfer(stream, 1);
17621759 return -ENOMEM;
17631760 }
17641761
....@@ -1778,9 +1775,9 @@
17781775 urb->number_of_packets = npackets;
17791776 urb->transfer_buffer_length = size;
17801777
1781
- for (j = 0; j < npackets; ++j) {
1782
- urb->iso_frame_desc[j].offset = j * psize;
1783
- urb->iso_frame_desc[j].length = psize;
1778
+ for (i = 0; i < npackets; ++i) {
1779
+ urb->iso_frame_desc[i].offset = i * psize;
1780
+ urb->iso_frame_desc[i].length = psize;
17841781 }
17851782
17861783 uvc_urb->urb = urb;
....@@ -1797,7 +1794,8 @@
17971794 struct usb_host_endpoint *ep, gfp_t gfp_flags)
17981795 {
17991796 struct urb *urb;
1800
- unsigned int npackets, pipe, i;
1797
+ struct uvc_urb *uvc_urb;
1798
+ unsigned int npackets, pipe;
18011799 u16 psize;
18021800 u32 size;
18031801
....@@ -1821,12 +1819,10 @@
18211819 if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
18221820 size = 0;
18231821
1824
- for (i = 0; i < UVC_URBS; ++i) {
1825
- struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
1826
-
1822
+ for_each_uvc_urb(uvc_urb, stream) {
18271823 urb = usb_alloc_urb(0, gfp_flags);
18281824 if (urb == NULL) {
1829
- uvc_uninit_video(stream, 1);
1825
+ uvc_video_stop_transfer(stream, 1);
18301826 return -ENOMEM;
18311827 }
18321828
....@@ -1846,10 +1842,12 @@
18461842 /*
18471843 * Initialize isochronous/bulk URBs and allocate transfer buffers.
18481844 */
1849
-static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
1845
+static int uvc_video_start_transfer(struct uvc_streaming *stream,
1846
+ gfp_t gfp_flags)
18501847 {
18511848 struct usb_interface *intf = stream->intf;
18521849 struct usb_host_endpoint *ep;
1850
+ struct uvc_urb *uvc_urb;
18531851 unsigned int i;
18541852 int ret;
18551853
....@@ -1865,7 +1863,7 @@
18651863 struct usb_host_endpoint *best_ep = NULL;
18661864 unsigned int best_psize = UINT_MAX;
18671865 unsigned int bandwidth;
1868
- unsigned int uninitialized_var(altsetting);
1866
+ unsigned int altsetting;
18691867 int intfnum = stream->intfnum;
18701868
18711869 /* Isochronous endpoint, select the alternate setting. */
....@@ -1908,6 +1906,17 @@
19081906 uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u "
19091907 "(%u B/frame bandwidth).\n", altsetting, best_psize);
19101908
1909
+ /*
1910
+ * Some devices, namely the Logitech C910 and B910, are unable
1911
+ * to recover from a USB autosuspend, unless the alternate
1912
+ * setting of the streaming interface is toggled.
1913
+ */
1914
+ if (stream->dev->quirks & UVC_QUIRK_WAKE_AUTOSUSPEND) {
1915
+ usb_set_interface(stream->dev->udev, intfnum,
1916
+ altsetting);
1917
+ usb_set_interface(stream->dev->udev, intfnum, 0);
1918
+ }
1919
+
19111920 ret = usb_set_interface(stream->dev->udev, intfnum, altsetting);
19121921 if (ret < 0)
19131922 return ret;
....@@ -1931,14 +1940,12 @@
19311940 return ret;
19321941
19331942 /* Submit the URBs. */
1934
- for (i = 0; i < UVC_URBS; ++i) {
1935
- struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
1936
-
1943
+ for_each_uvc_urb(uvc_urb, stream) {
19371944 ret = usb_submit_urb(uvc_urb->urb, gfp_flags);
19381945 if (ret < 0) {
1939
- uvc_printk(KERN_ERR, "Failed to submit URB %u "
1940
- "(%d).\n", i, ret);
1941
- uvc_uninit_video(stream, 1);
1946
+ uvc_printk(KERN_ERR, "Failed to submit URB %u (%d).\n",
1947
+ uvc_urb_index(uvc_urb), ret);
1948
+ uvc_video_stop_transfer(stream, 1);
19421949 return ret;
19431950 }
19441951 }
....@@ -1969,7 +1976,7 @@
19691976 return 0;
19701977
19711978 stream->frozen = 1;
1972
- uvc_uninit_video(stream, 0);
1979
+ uvc_video_stop_transfer(stream, 0);
19731980 usb_set_interface(stream->dev->udev, stream->intfnum, 0);
19741981 return 0;
19751982 }
....@@ -2005,7 +2012,7 @@
20052012 if (ret < 0)
20062013 return ret;
20072014
2008
- return uvc_init_video(stream, GFP_NOIO);
2015
+ return uvc_video_start_transfer(stream, GFP_NOIO);
20092016 }
20102017
20112018 /* ------------------------------------------------------------------------
....@@ -2046,7 +2053,7 @@
20462053 usb_set_interface(stream->dev->udev, stream->intfnum, 0);
20472054
20482055 /* Set the streaming probe control with default streaming parameters
2049
- * retrieved from the device. Webcams that don't suport GET_DEF
2056
+ * retrieved from the device. Webcams that don't support GET_DEF
20502057 * requests on the probe control will just keep their current streaming
20512058 * parameters.
20522059 */
....@@ -2120,37 +2127,9 @@
21202127 return 0;
21212128 }
21222129
2123
-/*
2124
- * Enable or disable the video stream.
2125
- */
2126
-int uvc_video_enable(struct uvc_streaming *stream, int enable)
2130
+int uvc_video_start_streaming(struct uvc_streaming *stream)
21272131 {
21282132 int ret;
2129
-
2130
- if (!enable) {
2131
- uvc_uninit_video(stream, 1);
2132
- if (stream->intf->num_altsetting > 1) {
2133
- usb_set_interface(stream->dev->udev,
2134
- stream->intfnum, 0);
2135
- } else {
2136
- /* UVC doesn't specify how to inform a bulk-based device
2137
- * when the video stream is stopped. Windows sends a
2138
- * CLEAR_FEATURE(HALT) request to the video streaming
2139
- * bulk endpoint, mimic the same behaviour.
2140
- */
2141
- unsigned int epnum = stream->header.bEndpointAddress
2142
- & USB_ENDPOINT_NUMBER_MASK;
2143
- unsigned int dir = stream->header.bEndpointAddress
2144
- & USB_ENDPOINT_DIR_MASK;
2145
- unsigned int pipe;
2146
-
2147
- pipe = usb_sndbulkpipe(stream->dev->udev, epnum) | dir;
2148
- usb_clear_halt(stream->dev->udev, pipe);
2149
- }
2150
-
2151
- uvc_video_clock_cleanup(stream);
2152
- return 0;
2153
- }
21542133
21552134 ret = uvc_video_clock_init(stream);
21562135 if (ret < 0)
....@@ -2161,16 +2140,45 @@
21612140 if (ret < 0)
21622141 goto error_commit;
21632142
2164
- ret = uvc_init_video(stream, GFP_KERNEL);
2143
+ rockchip_set_system_status(SYS_STATUS_PERFORMANCE);
2144
+
2145
+ ret = uvc_video_start_transfer(stream, GFP_KERNEL);
21652146 if (ret < 0)
21662147 goto error_video;
21672148
21682149 return 0;
21692150
21702151 error_video:
2152
+ rockchip_clear_system_status(SYS_STATUS_PERFORMANCE);
21712153 usb_set_interface(stream->dev->udev, stream->intfnum, 0);
21722154 error_commit:
21732155 uvc_video_clock_cleanup(stream);
21742156
21752157 return ret;
21762158 }
2159
+
2160
+void uvc_video_stop_streaming(struct uvc_streaming *stream)
2161
+{
2162
+ uvc_video_stop_transfer(stream, 1);
2163
+
2164
+ if (stream->intf->num_altsetting > 1) {
2165
+ usb_set_interface(stream->dev->udev, stream->intfnum, 0);
2166
+ } else {
2167
+ /* UVC doesn't specify how to inform a bulk-based device
2168
+ * when the video stream is stopped. Windows sends a
2169
+ * CLEAR_FEATURE(HALT) request to the video streaming
2170
+ * bulk endpoint, mimic the same behaviour.
2171
+ */
2172
+ unsigned int epnum = stream->header.bEndpointAddress
2173
+ & USB_ENDPOINT_NUMBER_MASK;
2174
+ unsigned int dir = stream->header.bEndpointAddress
2175
+ & USB_ENDPOINT_DIR_MASK;
2176
+ unsigned int pipe;
2177
+
2178
+ pipe = usb_sndbulkpipe(stream->dev->udev, epnum) | dir;
2179
+ usb_clear_halt(stream->dev->udev, pipe);
2180
+ }
2181
+
2182
+ uvc_video_clock_cleanup(stream);
2183
+ rockchip_clear_system_status(SYS_STATUS_PERFORMANCE);
2184
+}