1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * uvc_video.c -- USB Video Class Gadget driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2009-2010
6*4882a593Smuzhiyun * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/kernel.h>
10*4882a593Smuzhiyun #include <linux/device.h>
11*4882a593Smuzhiyun #include <linux/errno.h>
12*4882a593Smuzhiyun #include <linux/usb/ch9.h>
13*4882a593Smuzhiyun #include <linux/usb/gadget.h>
14*4882a593Smuzhiyun #include <linux/usb/video.h>
15*4882a593Smuzhiyun #include <linux/pm_qos.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <media/v4l2-dev.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include "uvc.h"
20*4882a593Smuzhiyun #include "uvc_queue.h"
21*4882a593Smuzhiyun #include "uvc_video.h"
22*4882a593Smuzhiyun #include "u_uvc.h"
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
uvc_using_zero_copy(struct uvc_video * video)25*4882a593Smuzhiyun static bool uvc_using_zero_copy(struct uvc_video *video)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun struct uvc_device *uvc = container_of(video, struct uvc_device, video);
28*4882a593Smuzhiyun struct f_uvc_opts *opts = fi_to_f_uvc_opts(uvc->func.fi);
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun if (opts && opts->uvc_zero_copy && video->fcc != V4L2_PIX_FMT_YUYV)
31*4882a593Smuzhiyun return true;
32*4882a593Smuzhiyun else
33*4882a593Smuzhiyun return false;
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun
uvc_wait_req_complete(struct uvc_video * video,struct uvc_request * ureq)36*4882a593Smuzhiyun static void uvc_wait_req_complete(struct uvc_video *video, struct uvc_request *ureq)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun unsigned long flags;
39*4882a593Smuzhiyun struct usb_request *req;
40*4882a593Smuzhiyun int ret;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun spin_lock_irqsave(&video->req_lock, flags);
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun list_for_each_entry(req, &video->req_free, list) {
45*4882a593Smuzhiyun if (req == ureq->req)
46*4882a593Smuzhiyun break;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun if (req != ureq->req) {
50*4882a593Smuzhiyun reinit_completion(&ureq->req_done);
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun spin_unlock_irqrestore(&video->req_lock, flags);
53*4882a593Smuzhiyun ret = wait_for_completion_timeout(&ureq->req_done,
54*4882a593Smuzhiyun msecs_to_jiffies(500));
55*4882a593Smuzhiyun if (ret == 0)
56*4882a593Smuzhiyun uvcg_warn(&video->uvc->func,
57*4882a593Smuzhiyun "timed out waiting for req done\n");
58*4882a593Smuzhiyun return;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun spin_unlock_irqrestore(&video->req_lock, flags);
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun #else
uvc_using_zero_copy(struct uvc_video * video)64*4882a593Smuzhiyun static inline bool uvc_using_zero_copy(struct uvc_video *video)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun return false;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
uvc_wait_req_complete(struct uvc_video * video,struct uvc_request * ureq)69*4882a593Smuzhiyun static inline void uvc_wait_req_complete(struct uvc_video *video, struct uvc_request *ureq)
70*4882a593Smuzhiyun { }
71*4882a593Smuzhiyun #endif
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun /* --------------------------------------------------------------------------
74*4882a593Smuzhiyun * Video codecs
75*4882a593Smuzhiyun */
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun static int
uvc_video_encode_header(struct uvc_video * video,struct uvc_buffer * buf,u8 * data,int len)78*4882a593Smuzhiyun uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
79*4882a593Smuzhiyun u8 *data, int len)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun if (uvc_using_zero_copy(video)) {
82*4882a593Smuzhiyun u8 *mem;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun mem = buf->mem + video->queue.buf_used +
85*4882a593Smuzhiyun (video->queue.buf_used / (video->req_size - 2)) * 2;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun mem[0] = 2;
88*4882a593Smuzhiyun mem[1] = UVC_STREAM_EOH | video->fid;
89*4882a593Smuzhiyun if (buf->bytesused - video->queue.buf_used <= len - 2)
90*4882a593Smuzhiyun mem[1] |= UVC_STREAM_EOF;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun return 2;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun data[0] = 2;
96*4882a593Smuzhiyun data[1] = UVC_STREAM_EOH | video->fid;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun if (buf->bytesused - video->queue.buf_used <= len - 2)
99*4882a593Smuzhiyun data[1] |= UVC_STREAM_EOF;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun return 2;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun static int
uvc_video_encode_data(struct uvc_video * video,struct uvc_buffer * buf,u8 * data,int len)105*4882a593Smuzhiyun uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf,
106*4882a593Smuzhiyun u8 *data, int len)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun struct uvc_video_queue *queue = &video->queue;
109*4882a593Smuzhiyun unsigned int nbytes;
110*4882a593Smuzhiyun void *mem;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /* Copy video data to the USB buffer. */
113*4882a593Smuzhiyun mem = buf->mem + queue->buf_used;
114*4882a593Smuzhiyun nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun if (!uvc_using_zero_copy(video))
117*4882a593Smuzhiyun memcpy(data, mem, nbytes);
118*4882a593Smuzhiyun queue->buf_used += nbytes;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun return nbytes;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun static void
uvc_video_encode_bulk(struct usb_request * req,struct uvc_video * video,struct uvc_buffer * buf)124*4882a593Smuzhiyun uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
125*4882a593Smuzhiyun struct uvc_buffer *buf)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun void *mem = req->buf;
128*4882a593Smuzhiyun int len = video->req_size;
129*4882a593Smuzhiyun int ret;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun /* Add a header at the beginning of the payload. */
132*4882a593Smuzhiyun if (video->payload_size == 0) {
133*4882a593Smuzhiyun ret = uvc_video_encode_header(video, buf, mem, len);
134*4882a593Smuzhiyun video->payload_size += ret;
135*4882a593Smuzhiyun mem += ret;
136*4882a593Smuzhiyun len -= ret;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /* Process video data. */
140*4882a593Smuzhiyun len = min((int)(video->max_payload_size - video->payload_size), len);
141*4882a593Smuzhiyun ret = uvc_video_encode_data(video, buf, mem, len);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun video->payload_size += ret;
144*4882a593Smuzhiyun len -= ret;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun req->length = video->req_size - len;
147*4882a593Smuzhiyun req->zero = video->payload_size == video->max_payload_size;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun if (buf->bytesused == video->queue.buf_used) {
150*4882a593Smuzhiyun video->queue.buf_used = 0;
151*4882a593Smuzhiyun buf->state = UVC_BUF_STATE_DONE;
152*4882a593Smuzhiyun uvcg_queue_next_buffer(&video->queue, buf);
153*4882a593Smuzhiyun video->fid ^= UVC_STREAM_FID;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun video->payload_size = 0;
156*4882a593Smuzhiyun req->zero = 1;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun if (video->payload_size == video->max_payload_size ||
160*4882a593Smuzhiyun buf->bytesused == video->queue.buf_used)
161*4882a593Smuzhiyun video->payload_size = 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun static void
uvc_video_encode_isoc(struct usb_request * req,struct uvc_video * video,struct uvc_buffer * buf)165*4882a593Smuzhiyun uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
166*4882a593Smuzhiyun struct uvc_buffer *buf)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun void *mem = req->buf;
169*4882a593Smuzhiyun int len = video->req_size;
170*4882a593Smuzhiyun int ret;
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun if (uvc_using_zero_copy(video))
173*4882a593Smuzhiyun req->buf = buf->mem + video->queue.buf_used +
174*4882a593Smuzhiyun (video->queue.buf_used / (video->req_size - 2)) * 2;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /* Add the header. */
177*4882a593Smuzhiyun ret = uvc_video_encode_header(video, buf, mem, len);
178*4882a593Smuzhiyun mem += ret;
179*4882a593Smuzhiyun len -= ret;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /* Process video data. */
182*4882a593Smuzhiyun ret = uvc_video_encode_data(video, buf, mem, len);
183*4882a593Smuzhiyun len -= ret;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun req->length = video->req_size - len;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun if (buf->bytesused == video->queue.buf_used) {
188*4882a593Smuzhiyun video->queue.buf_used = 0;
189*4882a593Smuzhiyun buf->state = UVC_BUF_STATE_DONE;
190*4882a593Smuzhiyun uvcg_queue_next_buffer(&video->queue, buf);
191*4882a593Smuzhiyun video->fid ^= UVC_STREAM_FID;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun /* --------------------------------------------------------------------------
196*4882a593Smuzhiyun * Request handling
197*4882a593Smuzhiyun */
198*4882a593Smuzhiyun
uvcg_video_ep_queue(struct uvc_video * video,struct usb_request * req)199*4882a593Smuzhiyun static int uvcg_video_ep_queue(struct uvc_video *video, struct usb_request *req)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun int ret;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
204*4882a593Smuzhiyun if (ret < 0) {
205*4882a593Smuzhiyun uvcg_err(&video->uvc->func, "Failed to queue request (%d).\n",
206*4882a593Smuzhiyun ret);
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /* If the endpoint is disabled the descriptor may be NULL. */
209*4882a593Smuzhiyun if (video->ep->desc) {
210*4882a593Smuzhiyun /* Isochronous endpoints can't be halted. */
211*4882a593Smuzhiyun if (usb_endpoint_xfer_bulk(video->ep->desc))
212*4882a593Smuzhiyun usb_ep_set_halt(video->ep);
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun return ret;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun static void
uvc_video_complete(struct usb_ep * ep,struct usb_request * req)220*4882a593Smuzhiyun uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun struct uvc_request *ureq = req->context;
223*4882a593Smuzhiyun struct uvc_video *video = ureq->video;
224*4882a593Smuzhiyun struct uvc_video_queue *queue = &video->queue;
225*4882a593Smuzhiyun struct uvc_device *uvc = video->uvc;
226*4882a593Smuzhiyun unsigned long flags;
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun switch (req->status) {
229*4882a593Smuzhiyun case 0:
230*4882a593Smuzhiyun break;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun case -ESHUTDOWN: /* disconnect from host. */
233*4882a593Smuzhiyun uvcg_dbg(&video->uvc->func, "VS request cancelled.\n");
234*4882a593Smuzhiyun uvcg_queue_cancel(queue, 1);
235*4882a593Smuzhiyun break;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun default:
238*4882a593Smuzhiyun uvcg_warn(&video->uvc->func,
239*4882a593Smuzhiyun "VS request completed with status %d.\n",
240*4882a593Smuzhiyun req->status);
241*4882a593Smuzhiyun uvcg_queue_cancel(queue, 0);
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun spin_lock_irqsave(&video->req_lock, flags);
245*4882a593Smuzhiyun list_add_tail(&req->list, &video->req_free);
246*4882a593Smuzhiyun #if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
247*4882a593Smuzhiyun complete(&ureq->req_done);
248*4882a593Smuzhiyun #endif
249*4882a593Smuzhiyun spin_unlock_irqrestore(&video->req_lock, flags);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun if (uvc->state == UVC_STATE_STREAMING)
252*4882a593Smuzhiyun schedule_work(&video->pump);
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun static int
uvc_video_free_requests(struct uvc_video * video)256*4882a593Smuzhiyun uvc_video_free_requests(struct uvc_video *video)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun unsigned int i;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun if (video->ureq) {
261*4882a593Smuzhiyun for (i = 0; i < video->uvc_num_requests; ++i) {
262*4882a593Smuzhiyun if (video->ureq[i].req) {
263*4882a593Smuzhiyun uvc_wait_req_complete(video, &video->ureq[i]);
264*4882a593Smuzhiyun usb_ep_free_request(video->ep, video->ureq[i].req);
265*4882a593Smuzhiyun video->ureq[i].req = NULL;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun if (video->ureq[i].req_buffer) {
269*4882a593Smuzhiyun kfree(video->ureq[i].req_buffer);
270*4882a593Smuzhiyun video->ureq[i].req_buffer = NULL;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun kfree(video->ureq);
275*4882a593Smuzhiyun video->ureq = NULL;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun INIT_LIST_HEAD(&video->req_free);
279*4882a593Smuzhiyun video->req_size = 0;
280*4882a593Smuzhiyun return 0;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun static int
uvc_video_alloc_requests(struct uvc_video * video)284*4882a593Smuzhiyun uvc_video_alloc_requests(struct uvc_video *video)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun unsigned int req_size;
287*4882a593Smuzhiyun unsigned int i;
288*4882a593Smuzhiyun int ret = -ENOMEM;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun BUG_ON(video->req_size);
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun if (!usb_endpoint_xfer_bulk(video->ep->desc)) {
293*4882a593Smuzhiyun req_size = video->ep->maxpacket
294*4882a593Smuzhiyun * max_t(unsigned int, video->ep->maxburst, 1)
295*4882a593Smuzhiyun * (video->ep->mult);
296*4882a593Smuzhiyun } else {
297*4882a593Smuzhiyun req_size = video->ep->maxpacket
298*4882a593Smuzhiyun * max_t(unsigned int, video->ep->maxburst, 1);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun video->ureq = kcalloc(video->uvc_num_requests, sizeof(struct uvc_request), GFP_KERNEL);
302*4882a593Smuzhiyun if (video->ureq == NULL)
303*4882a593Smuzhiyun return -ENOMEM;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun for (i = 0; i < video->uvc_num_requests; ++i) {
306*4882a593Smuzhiyun video->ureq[i].req_buffer = kmalloc(req_size, GFP_KERNEL);
307*4882a593Smuzhiyun if (video->ureq[i].req_buffer == NULL)
308*4882a593Smuzhiyun goto error;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun video->ureq[i].req = usb_ep_alloc_request(video->ep, GFP_KERNEL);
311*4882a593Smuzhiyun if (video->ureq[i].req == NULL)
312*4882a593Smuzhiyun goto error;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun video->ureq[i].req->buf = video->ureq[i].req_buffer;
315*4882a593Smuzhiyun video->ureq[i].req->length = 0;
316*4882a593Smuzhiyun video->ureq[i].req->complete = uvc_video_complete;
317*4882a593Smuzhiyun video->ureq[i].req->context = &video->ureq[i];
318*4882a593Smuzhiyun video->ureq[i].video = video;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun #if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
321*4882a593Smuzhiyun init_completion(&video->ureq[i].req_done);
322*4882a593Smuzhiyun #endif
323*4882a593Smuzhiyun list_add_tail(&video->ureq[i].req->list, &video->req_free);
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun video->req_size = req_size;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun return 0;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun error:
331*4882a593Smuzhiyun uvc_video_free_requests(video);
332*4882a593Smuzhiyun return ret;
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun /* --------------------------------------------------------------------------
336*4882a593Smuzhiyun * Video streaming
337*4882a593Smuzhiyun */
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun /*
340*4882a593Smuzhiyun * uvcg_video_pump - Pump video data into the USB requests
341*4882a593Smuzhiyun *
342*4882a593Smuzhiyun * This function fills the available USB requests (listed in req_free) with
343*4882a593Smuzhiyun * video data from the queued buffers.
344*4882a593Smuzhiyun */
uvcg_video_pump(struct work_struct * work)345*4882a593Smuzhiyun static void uvcg_video_pump(struct work_struct *work)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun struct uvc_video *video = container_of(work, struct uvc_video, pump);
348*4882a593Smuzhiyun struct uvc_video_queue *queue = &video->queue;
349*4882a593Smuzhiyun struct usb_request *req = NULL;
350*4882a593Smuzhiyun struct uvc_buffer *buf;
351*4882a593Smuzhiyun unsigned long flags;
352*4882a593Smuzhiyun int ret;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun while (video->ep->enabled) {
355*4882a593Smuzhiyun /* Retrieve the first available USB request, protected by the
356*4882a593Smuzhiyun * request lock.
357*4882a593Smuzhiyun */
358*4882a593Smuzhiyun spin_lock_irqsave(&video->req_lock, flags);
359*4882a593Smuzhiyun if (list_empty(&video->req_free)) {
360*4882a593Smuzhiyun spin_unlock_irqrestore(&video->req_lock, flags);
361*4882a593Smuzhiyun return;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun req = list_first_entry(&video->req_free, struct usb_request,
364*4882a593Smuzhiyun list);
365*4882a593Smuzhiyun list_del(&req->list);
366*4882a593Smuzhiyun spin_unlock_irqrestore(&video->req_lock, flags);
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /* Retrieve the first available video buffer and fill the
369*4882a593Smuzhiyun * request, protected by the video queue irqlock.
370*4882a593Smuzhiyun */
371*4882a593Smuzhiyun spin_lock_irqsave(&queue->irqlock, flags);
372*4882a593Smuzhiyun buf = uvcg_queue_head(queue);
373*4882a593Smuzhiyun if (buf == NULL) {
374*4882a593Smuzhiyun spin_unlock_irqrestore(&queue->irqlock, flags);
375*4882a593Smuzhiyun break;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun video->encode(req, video, buf);
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun /* Queue the USB request */
381*4882a593Smuzhiyun ret = uvcg_video_ep_queue(video, req);
382*4882a593Smuzhiyun spin_unlock_irqrestore(&queue->irqlock, flags);
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun if (ret < 0) {
385*4882a593Smuzhiyun uvcg_queue_cancel(queue, 0);
386*4882a593Smuzhiyun break;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun /* Endpoint now owns the request */
390*4882a593Smuzhiyun req = NULL;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun if (!req)
394*4882a593Smuzhiyun return;
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun spin_lock_irqsave(&video->req_lock, flags);
397*4882a593Smuzhiyun list_add_tail(&req->list, &video->req_free);
398*4882a593Smuzhiyun spin_unlock_irqrestore(&video->req_lock, flags);
399*4882a593Smuzhiyun return;
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun /*
403*4882a593Smuzhiyun * Enable or disable the video stream.
404*4882a593Smuzhiyun */
uvcg_video_enable(struct uvc_video * video,int enable)405*4882a593Smuzhiyun int uvcg_video_enable(struct uvc_video *video, int enable)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun unsigned int i;
408*4882a593Smuzhiyun int ret;
409*4882a593Smuzhiyun struct uvc_device *uvc;
410*4882a593Smuzhiyun struct f_uvc_opts *opts;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun if (video->ep == NULL) {
413*4882a593Smuzhiyun uvcg_info(&video->uvc->func,
414*4882a593Smuzhiyun "Video enable failed, device is uninitialized.\n");
415*4882a593Smuzhiyun return -ENODEV;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun uvc = container_of(video, struct uvc_device, video);
419*4882a593Smuzhiyun opts = fi_to_f_uvc_opts(uvc->func.fi);
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun if (!enable) {
422*4882a593Smuzhiyun cancel_work_sync(&video->pump);
423*4882a593Smuzhiyun uvcg_queue_cancel(&video->queue, 0);
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun for (i = 0; i < video->uvc_num_requests; ++i)
426*4882a593Smuzhiyun if (video->ureq && video->ureq[i].req)
427*4882a593Smuzhiyun usb_ep_dequeue(video->ep, video->ureq[i].req);
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun uvc_video_free_requests(video);
430*4882a593Smuzhiyun uvcg_queue_enable(&video->queue, 0);
431*4882a593Smuzhiyun if (cpu_latency_qos_request_active(&uvc->pm_qos))
432*4882a593Smuzhiyun cpu_latency_qos_remove_request(&uvc->pm_qos);
433*4882a593Smuzhiyun return 0;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun cpu_latency_qos_add_request(&uvc->pm_qos, opts->pm_qos_latency);
437*4882a593Smuzhiyun if ((ret = uvcg_queue_enable(&video->queue, 1)) < 0)
438*4882a593Smuzhiyun return ret;
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun if ((ret = uvc_video_alloc_requests(video)) < 0)
441*4882a593Smuzhiyun return ret;
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun if (video->max_payload_size) {
444*4882a593Smuzhiyun video->encode = uvc_video_encode_bulk;
445*4882a593Smuzhiyun video->payload_size = 0;
446*4882a593Smuzhiyun } else
447*4882a593Smuzhiyun video->encode = uvc_video_encode_isoc;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun schedule_work(&video->pump);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun return ret;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun /*
455*4882a593Smuzhiyun * Initialize the UVC video stream.
456*4882a593Smuzhiyun */
uvcg_video_init(struct uvc_video * video,struct uvc_device * uvc)457*4882a593Smuzhiyun int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc)
458*4882a593Smuzhiyun {
459*4882a593Smuzhiyun INIT_LIST_HEAD(&video->req_free);
460*4882a593Smuzhiyun spin_lock_init(&video->req_lock);
461*4882a593Smuzhiyun INIT_WORK(&video->pump, uvcg_video_pump);
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun video->uvc = uvc;
464*4882a593Smuzhiyun video->fcc = V4L2_PIX_FMT_YUYV;
465*4882a593Smuzhiyun video->bpp = 16;
466*4882a593Smuzhiyun video->width = 320;
467*4882a593Smuzhiyun video->height = 240;
468*4882a593Smuzhiyun video->imagesize = 320 * 240 * 2;
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun /* Initialize the video buffers queue. */
471*4882a593Smuzhiyun uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT,
472*4882a593Smuzhiyun &video->mutex);
473*4882a593Smuzhiyun return 0;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
476