forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-16 8d2a02b24d66aa359e83eebc1ed3c0f85367a1cb
kernel/drivers/usb/gadget/function/uvc_video.c
....@@ -21,6 +21,55 @@
2121 #include "uvc_video.h"
2222 #include "u_uvc.h"
2323
24
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
25
+static bool uvc_using_zero_copy(struct uvc_video *video)
26
+{
27
+ struct uvc_device *uvc = container_of(video, struct uvc_device, video);
28
+ struct f_uvc_opts *opts = fi_to_f_uvc_opts(uvc->func.fi);
29
+
30
+ if (opts && opts->uvc_zero_copy && video->fcc != V4L2_PIX_FMT_YUYV)
31
+ return true;
32
+ else
33
+ return false;
34
+}
35
+
36
+static void uvc_wait_req_complete(struct uvc_video *video, struct uvc_request *ureq)
37
+{
38
+ unsigned long flags;
39
+ struct usb_request *req;
40
+ int ret;
41
+
42
+ spin_lock_irqsave(&video->req_lock, flags);
43
+
44
+ list_for_each_entry(req, &video->req_free, list) {
45
+ if (req == ureq->req)
46
+ break;
47
+ }
48
+
49
+ if (req != ureq->req) {
50
+ reinit_completion(&ureq->req_done);
51
+
52
+ spin_unlock_irqrestore(&video->req_lock, flags);
53
+ ret = wait_for_completion_timeout(&ureq->req_done,
54
+ msecs_to_jiffies(500));
55
+ if (ret == 0)
56
+ uvcg_warn(&video->uvc->func,
57
+ "timed out waiting for req done\n");
58
+ return;
59
+ }
60
+
61
+ spin_unlock_irqrestore(&video->req_lock, flags);
62
+}
63
+#else
64
+static inline bool uvc_using_zero_copy(struct uvc_video *video)
65
+{
66
+ return false;
67
+}
68
+
69
+static inline void uvc_wait_req_complete(struct uvc_video *video, struct uvc_request *ureq)
70
+{ }
71
+#endif
72
+
2473 /* --------------------------------------------------------------------------
2574 * Video codecs
2675 */
....@@ -29,6 +78,20 @@
2978 uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
3079 u8 *data, int len)
3180 {
81
+ if (uvc_using_zero_copy(video)) {
82
+ u8 *mem;
83
+
84
+ mem = buf->mem + video->queue.buf_used +
85
+ (video->queue.buf_used / (video->req_size - 2)) * 2;
86
+
87
+ mem[0] = 2;
88
+ mem[1] = UVC_STREAM_EOH | video->fid;
89
+ if (buf->bytesused - video->queue.buf_used <= len - 2)
90
+ mem[1] |= UVC_STREAM_EOF;
91
+
92
+ return 2;
93
+ }
94
+
3295 data[0] = 2;
3396 data[1] = UVC_STREAM_EOH | video->fid;
3497
....@@ -50,7 +113,8 @@
50113 mem = buf->mem + queue->buf_used;
51114 nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
52115
53
- memcpy(data, mem, nbytes);
116
+ if (!uvc_using_zero_copy(video))
117
+ memcpy(data, mem, nbytes);
54118 queue->buf_used += nbytes;
55119
56120 return nbytes;
....@@ -105,6 +169,10 @@
105169 int len = video->req_size;
106170 int ret;
107171
172
+ if (uvc_using_zero_copy(video))
173
+ req->buf = buf->mem + video->queue.buf_used +
174
+ (video->queue.buf_used / (video->req_size - 2)) * 2;
175
+
108176 /* Add the header. */
109177 ret = uvc_video_encode_header(video, buf, mem, len);
110178 mem += ret;
....@@ -134,10 +202,15 @@
134202
135203 ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
136204 if (ret < 0) {
137
- printk(KERN_INFO "Failed to queue request (%d).\n", ret);
138
- /* Isochronous endpoints can't be halted. */
139
- if (video->ep->desc && usb_endpoint_xfer_bulk(video->ep->desc))
140
- usb_ep_set_halt(video->ep);
205
+ uvcg_err(&video->uvc->func, "Failed to queue request (%d).\n",
206
+ ret);
207
+
208
+ /* If the endpoint is disabled the descriptor may be NULL. */
209
+ if (video->ep->desc) {
210
+ /* Isochronous endpoints can't be halted. */
211
+ if (usb_endpoint_xfer_bulk(video->ep->desc))
212
+ usb_ep_set_halt(video->ep);
213
+ }
141214 }
142215
143216 return ret;
....@@ -146,8 +219,10 @@
146219 static void
147220 uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
148221 {
149
- struct uvc_video *video = req->context;
222
+ struct uvc_request *ureq = req->context;
223
+ struct uvc_video *video = ureq->video;
150224 struct uvc_video_queue *queue = &video->queue;
225
+ struct uvc_device *uvc = video->uvc;
151226 unsigned long flags;
152227
153228 switch (req->status) {
....@@ -155,44 +230,49 @@
155230 break;
156231
157232 case -ESHUTDOWN: /* disconnect from host. */
158
- printk(KERN_DEBUG "VS request cancelled.\n");
233
+ uvcg_dbg(&video->uvc->func, "VS request cancelled.\n");
159234 uvcg_queue_cancel(queue, 1);
160235 break;
161236
162237 default:
163
- printk(KERN_INFO "VS request completed with status %d.\n",
164
- req->status);
238
+ uvcg_warn(&video->uvc->func,
239
+ "VS request completed with status %d.\n",
240
+ req->status);
165241 uvcg_queue_cancel(queue, 0);
166
- break;
167242 }
168243
169244 spin_lock_irqsave(&video->req_lock, flags);
170245 list_add_tail(&req->list, &video->req_free);
246
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
247
+ complete(&ureq->req_done);
248
+#endif
171249 spin_unlock_irqrestore(&video->req_lock, flags);
172250
173
- queue_work(video->async_wq, &video->pump);
251
+ if (uvc->state == UVC_STATE_STREAMING)
252
+ queue_work(video->async_wq, &video->pump);
174253 }
175254
176255 static int
177256 uvc_video_free_requests(struct uvc_video *video)
178257 {
179258 unsigned int i;
180
- struct uvc_device *uvc;
181
- struct f_uvc_opts *opts;
182259
183
- uvc = container_of(video, struct uvc_device, video);
184
- opts = fi_to_f_uvc_opts(uvc->func.fi);
260
+ if (video->ureq) {
261
+ for (i = 0; i < video->uvc_num_requests; ++i) {
262
+ if (video->ureq[i].req) {
263
+ uvc_wait_req_complete(video, &video->ureq[i]);
264
+ usb_ep_free_request(video->ep, video->ureq[i].req);
265
+ video->ureq[i].req = NULL;
266
+ }
185267
186
- for (i = 0; i < opts->uvc_num_request; ++i) {
187
- if (video->req[i]) {
188
- usb_ep_free_request(video->ep, video->req[i]);
189
- video->req[i] = NULL;
268
+ if (video->ureq[i].req_buffer) {
269
+ kfree(video->ureq[i].req_buffer);
270
+ video->ureq[i].req_buffer = NULL;
271
+ }
190272 }
191273
192
- if (video->req_buffer[i]) {
193
- kfree(video->req_buffer[i]);
194
- video->req_buffer[i] = NULL;
195
- }
274
+ kfree(video->ureq);
275
+ video->ureq = NULL;
196276 }
197277
198278 INIT_LIST_HEAD(&video->req_free);
....@@ -206,11 +286,6 @@
206286 unsigned int req_size;
207287 unsigned int i;
208288 int ret = -ENOMEM;
209
- struct uvc_device *uvc;
210
- struct f_uvc_opts *opts;
211
-
212
- uvc = container_of(video, struct uvc_device, video);
213
- opts = fi_to_f_uvc_opts(uvc->func.fi);
214289
215290 BUG_ON(video->req_size);
216291
....@@ -223,21 +298,29 @@
223298 * max_t(unsigned int, video->ep->maxburst, 1);
224299 }
225300
226
- for (i = 0; i < opts->uvc_num_request; ++i) {
227
- video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
228
- if (video->req_buffer[i] == NULL)
301
+ video->ureq = kcalloc(video->uvc_num_requests, sizeof(struct uvc_request), GFP_KERNEL);
302
+ if (video->ureq == NULL)
303
+ return -ENOMEM;
304
+
305
+ for (i = 0; i < video->uvc_num_requests; ++i) {
306
+ video->ureq[i].req_buffer = kmalloc(req_size, GFP_KERNEL);
307
+ if (video->ureq[i].req_buffer == NULL)
229308 goto error;
230309
231
- video->req[i] = usb_ep_alloc_request(video->ep, GFP_KERNEL);
232
- if (video->req[i] == NULL)
310
+ video->ureq[i].req = usb_ep_alloc_request(video->ep, GFP_KERNEL);
311
+ if (video->ureq[i].req == NULL)
233312 goto error;
234313
235
- video->req[i]->buf = video->req_buffer[i];
236
- video->req[i]->length = 0;
237
- video->req[i]->complete = uvc_video_complete;
238
- video->req[i]->context = video;
314
+ video->ureq[i].req->buf = video->ureq[i].req_buffer;
315
+ video->ureq[i].req->length = 0;
316
+ video->ureq[i].req->complete = uvc_video_complete;
317
+ video->ureq[i].req->context = &video->ureq[i];
318
+ video->ureq[i].video = video;
239319
240
- list_add_tail(&video->req[i]->list, &video->req_free);
320
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
321
+ init_completion(&video->ureq[i].req_done);
322
+#endif
323
+ list_add_tail(&video->ureq[i].req->list, &video->req_free);
241324 }
242325
243326 video->req_size = req_size;
....@@ -263,12 +346,12 @@
263346 {
264347 struct uvc_video *video = container_of(work, struct uvc_video, pump);
265348 struct uvc_video_queue *queue = &video->queue;
266
- struct usb_request *req;
349
+ struct usb_request *req = NULL;
267350 struct uvc_buffer *buf;
268351 unsigned long flags;
269352 int ret;
270353
271
- while (1) {
354
+ while (video->ep->enabled) {
272355 /* Retrieve the first available USB request, protected by the
273356 * request lock.
274357 */
....@@ -302,7 +385,13 @@
302385 uvcg_queue_cancel(queue, 0);
303386 break;
304387 }
388
+
389
+ /* Endpoint now owns the request */
390
+ req = NULL;
305391 }
392
+
393
+ if (!req)
394
+ return;
306395
307396 spin_lock_irqsave(&video->req_lock, flags);
308397 list_add_tail(&req->list, &video->req_free);
....@@ -321,8 +410,8 @@
321410 struct f_uvc_opts *opts;
322411
323412 if (video->ep == NULL) {
324
- printk(KERN_INFO "Video enable failed, device is "
325
- "uninitialized.\n");
413
+ uvcg_info(&video->uvc->func,
414
+ "Video enable failed, device is uninitialized.\n");
326415 return -ENODEV;
327416 }
328417
....@@ -332,19 +421,19 @@
332421 if (!enable) {
333422 cancel_work_sync(&video->pump);
334423 uvcg_queue_cancel(&video->queue, 0);
335
- for (i = 0; i < opts->uvc_num_request; ++i)
336
- if (video->req[i])
337
- usb_ep_dequeue(video->ep, video->req[i]);
424
+
425
+ for (i = 0; i < video->uvc_num_requests; ++i)
426
+ if (video->ureq && video->ureq[i].req)
427
+ usb_ep_dequeue(video->ep, video->ureq[i].req);
338428
339429 uvc_video_free_requests(video);
340430 uvcg_queue_enable(&video->queue, 0);
341
- if (pm_qos_request_active(&uvc->pm_qos))
342
- pm_qos_remove_request(&uvc->pm_qos);
431
+ if (cpu_latency_qos_request_active(&uvc->pm_qos))
432
+ cpu_latency_qos_remove_request(&uvc->pm_qos);
343433 return 0;
344434 }
345435
346
- pm_qos_add_request(&uvc->pm_qos, PM_QOS_CPU_DMA_LATENCY,
347
- opts->pm_qos_latency);
436
+ cpu_latency_qos_add_request(&uvc->pm_qos, opts->pm_qos_latency);
348437 if ((ret = uvcg_queue_enable(&video->queue, 1)) < 0)
349438 return ret;
350439
....@@ -365,12 +454,18 @@
365454 /*
366455 * Initialize the UVC video stream.
367456 */
368
-int uvcg_video_init(struct uvc_video *video)
457
+int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc)
369458 {
370459 INIT_LIST_HEAD(&video->req_free);
371460 spin_lock_init(&video->req_lock);
372461 INIT_WORK(&video->pump, uvcg_video_pump);
373462
463
+ /* Allocate a work queue for asynchronous video pump handler. */
464
+ video->async_wq = alloc_workqueue("uvcgadget", WQ_UNBOUND | WQ_HIGHPRI, 0);
465
+ if (!video->async_wq)
466
+ return -EINVAL;
467
+
468
+ video->uvc = uvc;
374469 video->fcc = V4L2_PIX_FMT_YUYV;
375470 video->bpp = 16;
376471 video->width = 320;