Commit | Line | Data |
---|---|---|
ec16dae5 JVJ |
1 | /* |
2 | * stk-webcam.c : Driver for Syntek 1125 USB webcam controller | |
3 | * | |
4 | * Copyright (C) 2006 Nicolas VIVIEN | |
5 | * Copyright 2007-2008 Jaime Velasco Juan <jsagarribay@gmail.com> | |
6 | * | |
7 | * Some parts are inspired from cafe_ccic.c | |
8 | * Copyright 2006-2007 Jonathan Corbet | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; either version 2 of the License, or | |
13 | * any later version. | |
14 | * | |
15 | * This program is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * GNU General Public License for more details. | |
ec16dae5 JVJ |
19 | */ |
20 | ||
f1bd9bd6 JP |
21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
22 | ||
ec16dae5 JVJ |
23 | #include <linux/module.h> |
24 | #include <linux/init.h> | |
25 | #include <linux/kernel.h> | |
26 | #include <linux/errno.h> | |
27 | #include <linux/slab.h> | |
ec16dae5 | 28 | |
7a29ee2e | 29 | #include <linux/dmi.h> |
ec16dae5 | 30 | #include <linux/usb.h> |
ef69c8e8 | 31 | #include <linux/mm.h> |
387d4477 | 32 | #include <linux/vmalloc.h> |
ec16dae5 JVJ |
33 | #include <linux/videodev2.h> |
34 | #include <media/v4l2-common.h> | |
35ea11ff | 35 | #include <media/v4l2-ioctl.h> |
89ea4706 | 36 | #include <media/v4l2-event.h> |
ec16dae5 JVJ |
37 | |
38 | #include "stk-webcam.h" | |
39 | ||
40 | ||
7a29ee2e HG |
41 | static int hflip = -1; |
42 | module_param(hflip, int, 0444); | |
4fd466a1 | 43 | MODULE_PARM_DESC(hflip, "Horizontal image flip (mirror). Defaults to 0"); |
ec16dae5 | 44 | |
7a29ee2e HG |
45 | static int vflip = -1; |
46 | module_param(vflip, int, 0444); | |
4fd466a1 | 47 | MODULE_PARM_DESC(vflip, "Vertical image flip. Defaults to 0"); |
ec16dae5 JVJ |
48 | |
49 | static int debug; | |
50 | module_param(debug, int, 0444); | |
51 | MODULE_PARM_DESC(debug, "Debug v4l ioctls. Defaults to 0"); | |
52 | ||
53 | MODULE_LICENSE("GPL"); | |
54 | MODULE_AUTHOR("Jaime Velasco Juan <jsagarribay@gmail.com> and Nicolas VIVIEN"); | |
55 | MODULE_DESCRIPTION("Syntek DC1125 webcam driver"); | |
56 | ||
ec16dae5 | 57 | /* Some cameras have audio interfaces, we aren't interested in those */ |
7fb2e072 | 58 | static const struct usb_device_id stkwebcam_table[] = { |
ec16dae5 JVJ |
59 | { USB_DEVICE_AND_INTERFACE_INFO(0x174f, 0xa311, 0xff, 0xff, 0xff) }, |
60 | { USB_DEVICE_AND_INTERFACE_INFO(0x05e1, 0x0501, 0xff, 0xff, 0xff) }, | |
61 | { } | |
62 | }; | |
63 | MODULE_DEVICE_TABLE(usb, stkwebcam_table); | |
64 | ||
2aeb73e1 HV |
65 | /* |
66 | * The stk webcam laptop module is mounted upside down in some laptops :( | |
67 | * | |
68 | * Some background information (thanks to Hans de Goede for providing this): | |
69 | * | |
70 | * 1) Once upon a time the stkwebcam driver was written | |
71 | * | |
72 | * 2) The webcam in question was used mostly in Asus laptop models, including | |
73 | * the laptop of the original author of the driver, and in these models, in | |
74 | * typical Asus fashion (see the long long list for uvc cams inside v4l-utils), | |
75 | * they mounted the webcam-module the wrong way up. So the hflip and vflip | |
76 | * module options were given a default value of 1 (the correct value for | |
77 | * upside down mounted models) | |
78 | * | |
79 | * 3) Years later I got a bug report from a user with a laptop with stkwebcam, | |
80 | * where the module was actually mounted the right way up, and thus showed | |
81 | * upside down under Linux. So now I was facing the choice of 2 options: | |
82 | * | |
83 | * a) Add a not-upside-down list to stkwebcam, which overrules the default. | |
84 | * | |
85 | * b) Do it like all the other drivers do, and make the default right for | |
86 | * cams mounted the proper way and add an upside-down model list, with | |
87 | * models where we need to flip-by-default. | |
88 | * | |
89 | * Despite knowing that going b) would cause a period of pain where we were | |
90 | * building the table I opted to go for option b), since a) is just too ugly, | |
91 | * and worse different from how every other driver does it leading to | |
92 | * confusion in the long run. This change was made in kernel 3.6. | |
93 | * | |
94 | * So for any user report about upside-down images since kernel 3.6 ask them | |
95 | * to provide the output of 'sudo dmidecode' so the laptop can be added in | |
96 | * the table below. | |
97 | */ | |
7a29ee2e HG |
98 | static const struct dmi_system_id stk_upside_down_dmi_table[] = { |
99 | { | |
100 | .ident = "ASUS G1", | |
101 | .matches = { | |
102 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | |
103 | DMI_MATCH(DMI_PRODUCT_NAME, "G1") | |
104 | } | |
2aeb73e1 HV |
105 | }, { |
106 | .ident = "ASUS F3JC", | |
107 | .matches = { | |
108 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | |
109 | DMI_MATCH(DMI_PRODUCT_NAME, "F3JC") | |
110 | } | |
7a29ee2e | 111 | }, |
08149ecf GJ |
112 | { |
113 | .ident = "T12Rg-H", | |
114 | .matches = { | |
115 | DMI_MATCH(DMI_SYS_VENDOR, "HCL Infosystems Limited"), | |
116 | DMI_MATCH(DMI_PRODUCT_NAME, "T12Rg-H") | |
117 | } | |
118 | }, | |
7a29ee2e HG |
119 | {} |
120 | }; | |
121 | ||
122 | ||
ec16dae5 JVJ |
123 | /* |
124 | * Basic stuff | |
125 | */ | |
126 | int stk_camera_write_reg(struct stk_camera *dev, u16 index, u8 value) | |
127 | { | |
128 | struct usb_device *udev = dev->udev; | |
129 | int ret; | |
130 | ||
131 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | |
132 | 0x01, | |
133 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
134 | value, | |
135 | index, | |
136 | NULL, | |
137 | 0, | |
138 | 500); | |
139 | if (ret < 0) | |
140 | return ret; | |
141 | else | |
142 | return 0; | |
143 | } | |
144 | ||
d08876f5 | 145 | int stk_camera_read_reg(struct stk_camera *dev, u16 index, u8 *value) |
ec16dae5 JVJ |
146 | { |
147 | struct usb_device *udev = dev->udev; | |
b5f93cb5 | 148 | unsigned char *buf; |
ec16dae5 JVJ |
149 | int ret; |
150 | ||
b5f93cb5 MCC |
151 | buf = kmalloc(sizeof(u8), GFP_KERNEL); |
152 | if (!buf) | |
153 | return -ENOMEM; | |
154 | ||
ec16dae5 JVJ |
155 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
156 | 0x00, | |
157 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
158 | 0x00, | |
159 | index, | |
b5f93cb5 | 160 | buf, |
ec16dae5 JVJ |
161 | sizeof(u8), |
162 | 500); | |
b5f93cb5 | 163 | if (ret >= 0) |
d08876f5 | 164 | *value = *buf; |
b5f93cb5 MCC |
165 | |
166 | kfree(buf); | |
167 | return ret; | |
ec16dae5 JVJ |
168 | } |
169 | ||
170 | static int stk_start_stream(struct stk_camera *dev) | |
171 | { | |
d08876f5 | 172 | u8 value; |
ec16dae5 | 173 | int i, ret; |
d08876f5 DC |
174 | u8 value_116, value_117; |
175 | ||
ec16dae5 JVJ |
176 | |
177 | if (!is_present(dev)) | |
178 | return -ENODEV; | |
179 | if (!is_memallocd(dev) || !is_initialised(dev)) { | |
f1bd9bd6 | 180 | pr_err("FIXME: Buffers are not allocated\n"); |
ec16dae5 JVJ |
181 | return -EFAULT; |
182 | } | |
183 | ret = usb_set_interface(dev->udev, 0, 5); | |
184 | ||
185 | if (ret < 0) | |
f1bd9bd6 | 186 | pr_err("usb_set_interface failed !\n"); |
ec16dae5 | 187 | if (stk_sensor_wakeup(dev)) |
f1bd9bd6 | 188 | pr_err("error awaking the sensor\n"); |
ec16dae5 JVJ |
189 | |
190 | stk_camera_read_reg(dev, 0x0116, &value_116); | |
191 | stk_camera_read_reg(dev, 0x0117, &value_117); | |
192 | ||
193 | stk_camera_write_reg(dev, 0x0116, 0x0000); | |
194 | stk_camera_write_reg(dev, 0x0117, 0x0000); | |
195 | ||
196 | stk_camera_read_reg(dev, 0x0100, &value); | |
197 | stk_camera_write_reg(dev, 0x0100, value | 0x80); | |
198 | ||
199 | stk_camera_write_reg(dev, 0x0116, value_116); | |
200 | stk_camera_write_reg(dev, 0x0117, value_117); | |
201 | for (i = 0; i < MAX_ISO_BUFS; i++) { | |
202 | if (dev->isobufs[i].urb) { | |
203 | ret = usb_submit_urb(dev->isobufs[i].urb, GFP_KERNEL); | |
204 | atomic_inc(&dev->urbs_used); | |
205 | if (ret) | |
206 | return ret; | |
207 | } | |
208 | } | |
209 | set_streaming(dev); | |
210 | return 0; | |
211 | } | |
212 | ||
213 | static int stk_stop_stream(struct stk_camera *dev) | |
214 | { | |
d08876f5 | 215 | u8 value; |
ec16dae5 JVJ |
216 | int i; |
217 | if (is_present(dev)) { | |
218 | stk_camera_read_reg(dev, 0x0100, &value); | |
219 | stk_camera_write_reg(dev, 0x0100, value & ~0x80); | |
220 | if (dev->isobufs != NULL) { | |
221 | for (i = 0; i < MAX_ISO_BUFS; i++) { | |
222 | if (dev->isobufs[i].urb) | |
223 | usb_kill_urb(dev->isobufs[i].urb); | |
224 | } | |
225 | } | |
226 | unset_streaming(dev); | |
227 | ||
228 | if (usb_set_interface(dev->udev, 0, 0)) | |
f1bd9bd6 | 229 | pr_err("usb_set_interface failed !\n"); |
ec16dae5 | 230 | if (stk_sensor_sleep(dev)) |
f1bd9bd6 | 231 | pr_err("error suspending the sensor\n"); |
ec16dae5 JVJ |
232 | } |
233 | return 0; | |
234 | } | |
235 | ||
236 | /* | |
237 | * This seems to be the shortest init sequence we | |
238 | * must do in order to find the sensor | |
239 | * Bit 5 of reg. 0x0000 here is important, when reset to 0 the sensor | |
240 | * is also reset. Maybe powers down it? | |
241 | * Rest of values don't make a difference | |
242 | */ | |
243 | ||
244 | static struct regval stk1125_initvals[] = { | |
245 | /*TODO: What means this sequence? */ | |
246 | {0x0000, 0x24}, | |
247 | {0x0100, 0x21}, | |
248 | {0x0002, 0x68}, | |
249 | {0x0003, 0x80}, | |
250 | {0x0005, 0x00}, | |
251 | {0x0007, 0x03}, | |
252 | {0x000d, 0x00}, | |
253 | {0x000f, 0x02}, | |
254 | {0x0300, 0x12}, | |
255 | {0x0350, 0x41}, | |
256 | {0x0351, 0x00}, | |
257 | {0x0352, 0x00}, | |
258 | {0x0353, 0x00}, | |
259 | {0x0018, 0x10}, | |
260 | {0x0019, 0x00}, | |
261 | {0x001b, 0x0e}, | |
262 | {0x001c, 0x46}, | |
263 | {0x0300, 0x80}, | |
264 | {0x001a, 0x04}, | |
265 | {0x0110, 0x00}, | |
266 | {0x0111, 0x00}, | |
267 | {0x0112, 0x00}, | |
268 | {0x0113, 0x00}, | |
269 | ||
270 | {0xffff, 0xff}, | |
271 | }; | |
272 | ||
273 | ||
274 | static int stk_initialise(struct stk_camera *dev) | |
275 | { | |
276 | struct regval *rv; | |
277 | int ret; | |
278 | if (!is_present(dev)) | |
279 | return -ENODEV; | |
280 | if (is_initialised(dev)) | |
281 | return 0; | |
282 | rv = stk1125_initvals; | |
283 | while (rv->reg != 0xffff) { | |
284 | ret = stk_camera_write_reg(dev, rv->reg, rv->val); | |
285 | if (ret) | |
286 | return ret; | |
287 | rv++; | |
288 | } | |
289 | if (stk_sensor_init(dev) == 0) { | |
290 | set_initialised(dev); | |
291 | return 0; | |
292 | } else | |
293 | return -1; | |
294 | } | |
295 | ||
ec16dae5 JVJ |
296 | /* *********************************************** */ |
297 | /* | |
298 | * This function is called as an URB transfert is complete (Isochronous pipe). | |
299 | * So, the traitement is done in interrupt time, so it has be fast, not crash, | |
300 | * and not stall. Neat. | |
301 | */ | |
302 | static void stk_isoc_handler(struct urb *urb) | |
303 | { | |
304 | int i; | |
305 | int ret; | |
306 | int framelen; | |
307 | unsigned long flags; | |
308 | ||
309 | unsigned char *fill = NULL; | |
310 | unsigned char *iso_buf = NULL; | |
311 | ||
312 | struct stk_camera *dev; | |
313 | struct stk_sio_buffer *fb; | |
314 | ||
315 | dev = (struct stk_camera *) urb->context; | |
316 | ||
317 | if (dev == NULL) { | |
f1bd9bd6 | 318 | pr_err("isoc_handler called with NULL device !\n"); |
ec16dae5 JVJ |
319 | return; |
320 | } | |
321 | ||
322 | if (urb->status == -ENOENT || urb->status == -ECONNRESET | |
323 | || urb->status == -ESHUTDOWN) { | |
324 | atomic_dec(&dev->urbs_used); | |
325 | return; | |
326 | } | |
327 | ||
328 | spin_lock_irqsave(&dev->spinlock, flags); | |
329 | ||
330 | if (urb->status != -EINPROGRESS && urb->status != 0) { | |
f1bd9bd6 | 331 | pr_err("isoc_handler: urb->status == %d\n", urb->status); |
ec16dae5 JVJ |
332 | goto resubmit; |
333 | } | |
334 | ||
335 | if (list_empty(&dev->sio_avail)) { | |
336 | /*FIXME Stop streaming after a while */ | |
f1bd9bd6 | 337 | pr_err_ratelimited("isoc_handler without available buffer!\n"); |
ec16dae5 JVJ |
338 | goto resubmit; |
339 | } | |
340 | fb = list_first_entry(&dev->sio_avail, | |
341 | struct stk_sio_buffer, list); | |
342 | fill = fb->buffer + fb->v4lbuf.bytesused; | |
343 | ||
344 | for (i = 0; i < urb->number_of_packets; i++) { | |
345 | if (urb->iso_frame_desc[i].status != 0) { | |
346 | if (urb->iso_frame_desc[i].status != -EXDEV) | |
f1bd9bd6 JP |
347 | pr_err("Frame %d has error %d\n", |
348 | i, urb->iso_frame_desc[i].status); | |
ec16dae5 JVJ |
349 | continue; |
350 | } | |
351 | framelen = urb->iso_frame_desc[i].actual_length; | |
352 | iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset; | |
353 | ||
354 | if (framelen <= 4) | |
355 | continue; /* no data */ | |
356 | ||
357 | /* | |
358 | * we found something informational from there | |
359 | * the isoc frames have to type of headers | |
360 | * type1: 00 xx 00 00 or 20 xx 00 00 | |
361 | * type2: 80 xx 00 00 00 00 00 00 or a0 xx 00 00 00 00 00 00 | |
362 | * xx is a sequencer which has never been seen over 0x3f | |
363 | * imho data written down looks like bayer, i see similarities | |
364 | * after every 640 bytes | |
365 | */ | |
366 | if (*iso_buf & 0x80) { | |
367 | framelen -= 8; | |
368 | iso_buf += 8; | |
369 | /* This marks a new frame */ | |
370 | if (fb->v4lbuf.bytesused != 0 | |
371 | && fb->v4lbuf.bytesused != dev->frame_size) { | |
f1bd9bd6 JP |
372 | pr_err_ratelimited("frame %d, bytesused=%d, skipping\n", |
373 | i, fb->v4lbuf.bytesused); | |
ec16dae5 JVJ |
374 | fb->v4lbuf.bytesused = 0; |
375 | fill = fb->buffer; | |
376 | } else if (fb->v4lbuf.bytesused == dev->frame_size) { | |
b1855907 JVJ |
377 | if (list_is_singular(&dev->sio_avail)) { |
378 | /* Always reuse the last buffer */ | |
379 | fb->v4lbuf.bytesused = 0; | |
380 | fill = fb->buffer; | |
381 | } else { | |
382 | list_move_tail(dev->sio_avail.next, | |
383 | &dev->sio_full); | |
384 | wake_up(&dev->wait_frame); | |
385 | fb = list_first_entry(&dev->sio_avail, | |
386 | struct stk_sio_buffer, list); | |
387 | fb->v4lbuf.bytesused = 0; | |
388 | fill = fb->buffer; | |
ec16dae5 | 389 | } |
ec16dae5 JVJ |
390 | } |
391 | } else { | |
392 | framelen -= 4; | |
393 | iso_buf += 4; | |
394 | } | |
395 | ||
396 | /* Our buffer is full !!! */ | |
397 | if (framelen + fb->v4lbuf.bytesused > dev->frame_size) { | |
f1bd9bd6 | 398 | pr_err_ratelimited("Frame buffer overflow, lost sync\n"); |
ec16dae5 JVJ |
399 | /*FIXME Do something here? */ |
400 | continue; | |
401 | } | |
402 | spin_unlock_irqrestore(&dev->spinlock, flags); | |
403 | memcpy(fill, iso_buf, framelen); | |
404 | spin_lock_irqsave(&dev->spinlock, flags); | |
405 | fill += framelen; | |
406 | ||
407 | /* New size of our buffer */ | |
408 | fb->v4lbuf.bytesused += framelen; | |
409 | } | |
410 | ||
411 | resubmit: | |
412 | spin_unlock_irqrestore(&dev->spinlock, flags); | |
413 | urb->dev = dev->udev; | |
414 | ret = usb_submit_urb(urb, GFP_ATOMIC); | |
415 | if (ret != 0) { | |
f1bd9bd6 JP |
416 | pr_err("Error (%d) re-submitting urb in stk_isoc_handler\n", |
417 | ret); | |
ec16dae5 JVJ |
418 | } |
419 | } | |
420 | ||
421 | /* -------------------------------------------- */ | |
422 | ||
423 | static int stk_prepare_iso(struct stk_camera *dev) | |
424 | { | |
425 | void *kbuf; | |
426 | int i, j; | |
427 | struct urb *urb; | |
428 | struct usb_device *udev; | |
429 | ||
430 | if (dev == NULL) | |
431 | return -ENXIO; | |
432 | udev = dev->udev; | |
433 | ||
434 | if (dev->isobufs) | |
f1bd9bd6 | 435 | pr_err("isobufs already allocated. Bad\n"); |
ec16dae5 | 436 | else |
9884d7be TM |
437 | dev->isobufs = kcalloc(MAX_ISO_BUFS, sizeof(*dev->isobufs), |
438 | GFP_KERNEL); | |
ec16dae5 | 439 | if (dev->isobufs == NULL) { |
f1bd9bd6 | 440 | pr_err("Unable to allocate iso buffers\n"); |
ec16dae5 JVJ |
441 | return -ENOMEM; |
442 | } | |
443 | for (i = 0; i < MAX_ISO_BUFS; i++) { | |
444 | if (dev->isobufs[i].data == NULL) { | |
445 | kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL); | |
446 | if (kbuf == NULL) { | |
f1bd9bd6 | 447 | pr_err("Failed to allocate iso buffer %d\n", i); |
ec16dae5 JVJ |
448 | goto isobufs_out; |
449 | } | |
450 | dev->isobufs[i].data = kbuf; | |
451 | } else | |
f1bd9bd6 | 452 | pr_err("isobuf data already allocated\n"); |
ec16dae5 JVJ |
453 | if (dev->isobufs[i].urb == NULL) { |
454 | urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); | |
2685b1d1 | 455 | if (urb == NULL) |
ec16dae5 | 456 | goto isobufs_out; |
ec16dae5 JVJ |
457 | dev->isobufs[i].urb = urb; |
458 | } else { | |
f1bd9bd6 | 459 | pr_err("Killing URB\n"); |
ec16dae5 JVJ |
460 | usb_kill_urb(dev->isobufs[i].urb); |
461 | urb = dev->isobufs[i].urb; | |
462 | } | |
463 | urb->interval = 1; | |
464 | urb->dev = udev; | |
465 | urb->pipe = usb_rcvisocpipe(udev, dev->isoc_ep); | |
466 | urb->transfer_flags = URB_ISO_ASAP; | |
467 | urb->transfer_buffer = dev->isobufs[i].data; | |
468 | urb->transfer_buffer_length = ISO_BUFFER_SIZE; | |
469 | urb->complete = stk_isoc_handler; | |
470 | urb->context = dev; | |
471 | urb->start_frame = 0; | |
472 | urb->number_of_packets = ISO_FRAMES_PER_DESC; | |
473 | ||
474 | for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { | |
475 | urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; | |
476 | urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE; | |
477 | } | |
478 | } | |
479 | set_memallocd(dev); | |
480 | return 0; | |
481 | ||
482 | isobufs_out: | |
483 | for (i = 0; i < MAX_ISO_BUFS && dev->isobufs[i].data; i++) | |
484 | kfree(dev->isobufs[i].data); | |
485 | for (i = 0; i < MAX_ISO_BUFS && dev->isobufs[i].urb; i++) | |
486 | usb_free_urb(dev->isobufs[i].urb); | |
487 | kfree(dev->isobufs); | |
488 | dev->isobufs = NULL; | |
489 | return -ENOMEM; | |
490 | } | |
491 | ||
492 | static void stk_clean_iso(struct stk_camera *dev) | |
493 | { | |
494 | int i; | |
495 | ||
496 | if (dev == NULL || dev->isobufs == NULL) | |
497 | return; | |
498 | ||
499 | for (i = 0; i < MAX_ISO_BUFS; i++) { | |
500 | struct urb *urb; | |
501 | ||
502 | urb = dev->isobufs[i].urb; | |
503 | if (urb) { | |
f051ae18 | 504 | if (atomic_read(&dev->urbs_used) && is_present(dev)) |
ec16dae5 JVJ |
505 | usb_kill_urb(urb); |
506 | usb_free_urb(urb); | |
507 | } | |
508 | kfree(dev->isobufs[i].data); | |
509 | } | |
510 | kfree(dev->isobufs); | |
511 | dev->isobufs = NULL; | |
512 | unset_memallocd(dev); | |
513 | } | |
514 | ||
515 | static int stk_setup_siobuf(struct stk_camera *dev, int index) | |
516 | { | |
517 | struct stk_sio_buffer *buf = dev->sio_bufs + index; | |
518 | INIT_LIST_HEAD(&buf->list); | |
519 | buf->v4lbuf.length = PAGE_ALIGN(dev->frame_size); | |
520 | buf->buffer = vmalloc_user(buf->v4lbuf.length); | |
521 | if (buf->buffer == NULL) | |
522 | return -ENOMEM; | |
523 | buf->mapcount = 0; | |
524 | buf->dev = dev; | |
525 | buf->v4lbuf.index = index; | |
526 | buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
1b18e7a0 | 527 | buf->v4lbuf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; |
ec16dae5 JVJ |
528 | buf->v4lbuf.field = V4L2_FIELD_NONE; |
529 | buf->v4lbuf.memory = V4L2_MEMORY_MMAP; | |
530 | buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length; | |
531 | return 0; | |
532 | } | |
533 | ||
534 | static int stk_free_sio_buffers(struct stk_camera *dev) | |
535 | { | |
536 | int i; | |
537 | int nbufs; | |
538 | unsigned long flags; | |
539 | if (dev->n_sbufs == 0 || dev->sio_bufs == NULL) | |
540 | return 0; | |
541 | /* | |
542 | * If any buffers are mapped, we cannot free them at all. | |
543 | */ | |
544 | for (i = 0; i < dev->n_sbufs; i++) { | |
545 | if (dev->sio_bufs[i].mapcount > 0) | |
546 | return -EBUSY; | |
547 | } | |
548 | /* | |
549 | * OK, let's do it. | |
550 | */ | |
551 | spin_lock_irqsave(&dev->spinlock, flags); | |
552 | INIT_LIST_HEAD(&dev->sio_avail); | |
553 | INIT_LIST_HEAD(&dev->sio_full); | |
554 | nbufs = dev->n_sbufs; | |
555 | dev->n_sbufs = 0; | |
556 | spin_unlock_irqrestore(&dev->spinlock, flags); | |
704b3f4c ME |
557 | for (i = 0; i < nbufs; i++) |
558 | vfree(dev->sio_bufs[i].buffer); | |
ec16dae5 JVJ |
559 | kfree(dev->sio_bufs); |
560 | dev->sio_bufs = NULL; | |
561 | return 0; | |
562 | } | |
563 | ||
564 | static int stk_prepare_sio_buffers(struct stk_camera *dev, unsigned n_sbufs) | |
565 | { | |
566 | int i; | |
567 | if (dev->sio_bufs != NULL) | |
f1bd9bd6 | 568 | pr_err("sio_bufs already allocated\n"); |
ec16dae5 JVJ |
569 | else { |
570 | dev->sio_bufs = kzalloc(n_sbufs * sizeof(struct stk_sio_buffer), | |
571 | GFP_KERNEL); | |
572 | if (dev->sio_bufs == NULL) | |
573 | return -ENOMEM; | |
574 | for (i = 0; i < n_sbufs; i++) { | |
575 | if (stk_setup_siobuf(dev, i)) | |
b57ce417 | 576 | return (dev->n_sbufs > 1 ? 0 : -ENOMEM); |
ec16dae5 JVJ |
577 | dev->n_sbufs = i+1; |
578 | } | |
579 | } | |
580 | return 0; | |
581 | } | |
582 | ||
583 | static int stk_allocate_buffers(struct stk_camera *dev, unsigned n_sbufs) | |
584 | { | |
585 | int err; | |
586 | err = stk_prepare_iso(dev); | |
587 | if (err) { | |
588 | stk_clean_iso(dev); | |
589 | return err; | |
590 | } | |
591 | err = stk_prepare_sio_buffers(dev, n_sbufs); | |
592 | if (err) { | |
593 | stk_free_sio_buffers(dev); | |
594 | return err; | |
595 | } | |
596 | return 0; | |
597 | } | |
598 | ||
599 | static void stk_free_buffers(struct stk_camera *dev) | |
600 | { | |
601 | stk_clean_iso(dev); | |
602 | stk_free_sio_buffers(dev); | |
603 | } | |
604 | /* -------------------------------------------- */ | |
605 | ||
606 | /* v4l file operations */ | |
607 | ||
bec43661 | 608 | static int v4l_stk_open(struct file *fp) |
ec16dae5 | 609 | { |
10351adc | 610 | struct stk_camera *dev = video_drvdata(fp); |
89ea4706 | 611 | int err; |
ec16dae5 | 612 | |
b57ce417 | 613 | if (dev == NULL || !is_present(dev)) |
ec16dae5 | 614 | return -ENXIO; |
7b1c8f58 | 615 | |
f80daa2d HV |
616 | if (mutex_lock_interruptible(&dev->lock)) |
617 | return -ERESTARTSYS; | |
89ea4706 | 618 | if (!dev->first_init) |
7b1c8f58 AS |
619 | stk_camera_write_reg(dev, 0x0, 0x24); |
620 | else | |
89ea4706 | 621 | dev->first_init = 0; |
ec16dae5 | 622 | |
89ea4706 HV |
623 | err = v4l2_fh_open(fp); |
624 | if (!err) | |
625 | usb_autopm_get_interface(dev->interface); | |
f80daa2d | 626 | mutex_unlock(&dev->lock); |
89ea4706 | 627 | return err; |
ec16dae5 JVJ |
628 | } |
629 | ||
bec43661 | 630 | static int v4l_stk_release(struct file *fp) |
ec16dae5 | 631 | { |
10351adc | 632 | struct stk_camera *dev = video_drvdata(fp); |
ec16dae5 | 633 | |
f80daa2d | 634 | mutex_lock(&dev->lock); |
f051ae18 DE |
635 | if (dev->owner == fp) { |
636 | stk_stop_stream(dev); | |
637 | stk_free_buffers(dev); | |
7b1c8f58 | 638 | stk_camera_write_reg(dev, 0x0, 0x49); /* turn off the LED */ |
47a7e6f8 | 639 | unset_initialised(dev); |
f051ae18 | 640 | dev->owner = NULL; |
ec16dae5 JVJ |
641 | } |
642 | ||
b57ce417 | 643 | if (is_present(dev)) |
f051ae18 | 644 | usb_autopm_put_interface(dev->interface); |
f80daa2d | 645 | mutex_unlock(&dev->lock); |
89ea4706 | 646 | return v4l2_fh_release(fp); |
ec16dae5 JVJ |
647 | } |
648 | ||
f80daa2d | 649 | static ssize_t stk_read(struct file *fp, char __user *buf, |
ec16dae5 JVJ |
650 | size_t count, loff_t *f_pos) |
651 | { | |
652 | int i; | |
653 | int ret; | |
654 | unsigned long flags; | |
ec16dae5 | 655 | struct stk_sio_buffer *sbuf; |
10351adc | 656 | struct stk_camera *dev = video_drvdata(fp); |
ec16dae5 | 657 | |
ec16dae5 JVJ |
658 | if (!is_present(dev)) |
659 | return -EIO; | |
1b499fe5 | 660 | if (dev->owner && (!dev->reading || dev->owner != fp)) |
ec16dae5 JVJ |
661 | return -EBUSY; |
662 | dev->owner = fp; | |
663 | if (!is_streaming(dev)) { | |
664 | if (stk_initialise(dev) | |
665 | || stk_allocate_buffers(dev, 3) | |
666 | || stk_start_stream(dev)) | |
667 | return -ENOMEM; | |
1b499fe5 | 668 | dev->reading = 1; |
ec16dae5 JVJ |
669 | spin_lock_irqsave(&dev->spinlock, flags); |
670 | for (i = 0; i < dev->n_sbufs; i++) { | |
671 | list_add_tail(&dev->sio_bufs[i].list, &dev->sio_avail); | |
672 | dev->sio_bufs[i].v4lbuf.flags = V4L2_BUF_FLAG_QUEUED; | |
673 | } | |
674 | spin_unlock_irqrestore(&dev->spinlock, flags); | |
675 | } | |
676 | if (*f_pos == 0) { | |
677 | if (fp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full)) | |
678 | return -EWOULDBLOCK; | |
679 | ret = wait_event_interruptible(dev->wait_frame, | |
680 | !list_empty(&dev->sio_full) || !is_present(dev)); | |
681 | if (ret) | |
682 | return ret; | |
683 | if (!is_present(dev)) | |
684 | return -EIO; | |
685 | } | |
686 | if (count + *f_pos > dev->frame_size) | |
687 | count = dev->frame_size - *f_pos; | |
688 | spin_lock_irqsave(&dev->spinlock, flags); | |
689 | if (list_empty(&dev->sio_full)) { | |
690 | spin_unlock_irqrestore(&dev->spinlock, flags); | |
f1bd9bd6 | 691 | pr_err("BUG: No siobufs ready\n"); |
ec16dae5 JVJ |
692 | return 0; |
693 | } | |
694 | sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list); | |
695 | spin_unlock_irqrestore(&dev->spinlock, flags); | |
696 | ||
697 | if (copy_to_user(buf, sbuf->buffer + *f_pos, count)) | |
698 | return -EFAULT; | |
699 | ||
700 | *f_pos += count; | |
701 | ||
702 | if (*f_pos >= dev->frame_size) { | |
703 | *f_pos = 0; | |
704 | spin_lock_irqsave(&dev->spinlock, flags); | |
705 | list_move_tail(&sbuf->list, &dev->sio_avail); | |
706 | spin_unlock_irqrestore(&dev->spinlock, flags); | |
707 | } | |
708 | return count; | |
709 | } | |
710 | ||
f80daa2d HV |
711 | static ssize_t v4l_stk_read(struct file *fp, char __user *buf, |
712 | size_t count, loff_t *f_pos) | |
713 | { | |
714 | struct stk_camera *dev = video_drvdata(fp); | |
715 | int ret; | |
716 | ||
717 | if (mutex_lock_interruptible(&dev->lock)) | |
718 | return -ERESTARTSYS; | |
719 | ret = stk_read(fp, buf, count, f_pos); | |
720 | mutex_unlock(&dev->lock); | |
721 | return ret; | |
722 | } | |
723 | ||
c23e0cb8 | 724 | static __poll_t v4l_stk_poll(struct file *fp, poll_table *wait) |
ec16dae5 | 725 | { |
10351adc | 726 | struct stk_camera *dev = video_drvdata(fp); |
c23e0cb8 | 727 | __poll_t res = v4l2_ctrl_poll(fp, wait); |
ec16dae5 | 728 | |
ec16dae5 JVJ |
729 | poll_wait(fp, &dev->wait_frame, wait); |
730 | ||
731 | if (!is_present(dev)) | |
a9a08845 | 732 | return EPOLLERR; |
ec16dae5 JVJ |
733 | |
734 | if (!list_empty(&dev->sio_full)) | |
a9a08845 | 735 | return res | EPOLLIN | EPOLLRDNORM; |
ec16dae5 | 736 | |
89ea4706 | 737 | return res; |
ec16dae5 JVJ |
738 | } |
739 | ||
740 | ||
741 | static void stk_v4l_vm_open(struct vm_area_struct *vma) | |
742 | { | |
743 | struct stk_sio_buffer *sbuf = vma->vm_private_data; | |
744 | sbuf->mapcount++; | |
745 | } | |
746 | static void stk_v4l_vm_close(struct vm_area_struct *vma) | |
747 | { | |
748 | struct stk_sio_buffer *sbuf = vma->vm_private_data; | |
749 | sbuf->mapcount--; | |
750 | if (sbuf->mapcount == 0) | |
751 | sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED; | |
752 | } | |
f0f37e2f | 753 | static const struct vm_operations_struct stk_v4l_vm_ops = { |
ec16dae5 JVJ |
754 | .open = stk_v4l_vm_open, |
755 | .close = stk_v4l_vm_close | |
756 | }; | |
757 | ||
758 | static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma) | |
759 | { | |
760 | unsigned int i; | |
761 | int ret; | |
762 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | |
10351adc | 763 | struct stk_camera *dev = video_drvdata(fp); |
ec16dae5 JVJ |
764 | struct stk_sio_buffer *sbuf = NULL; |
765 | ||
766 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) | |
767 | return -EINVAL; | |
768 | ||
ec16dae5 JVJ |
769 | for (i = 0; i < dev->n_sbufs; i++) { |
770 | if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { | |
771 | sbuf = dev->sio_bufs + i; | |
772 | break; | |
773 | } | |
774 | } | |
775 | if (sbuf == NULL) | |
776 | return -EINVAL; | |
777 | ret = remap_vmalloc_range(vma, sbuf->buffer, 0); | |
778 | if (ret) | |
779 | return ret; | |
780 | vma->vm_flags |= VM_DONTEXPAND; | |
781 | vma->vm_private_data = sbuf; | |
782 | vma->vm_ops = &stk_v4l_vm_ops; | |
783 | sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED; | |
784 | stk_v4l_vm_open(vma); | |
785 | return 0; | |
786 | } | |
787 | ||
788 | /* v4l ioctl handlers */ | |
789 | ||
790 | static int stk_vidioc_querycap(struct file *filp, | |
791 | void *priv, struct v4l2_capability *cap) | |
792 | { | |
b27763f0 HV |
793 | struct stk_camera *dev = video_drvdata(filp); |
794 | ||
ec16dae5 JVJ |
795 | strcpy(cap->driver, "stk"); |
796 | strcpy(cap->card, "stk"); | |
b27763f0 | 797 | usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); |
ec16dae5 | 798 | |
b27763f0 | 799 | cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
ec16dae5 | 800 | | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; |
b27763f0 | 801 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
ec16dae5 JVJ |
802 | return 0; |
803 | } | |
804 | ||
805 | static int stk_vidioc_enum_input(struct file *filp, | |
806 | void *priv, struct v4l2_input *input) | |
807 | { | |
808 | if (input->index != 0) | |
809 | return -EINVAL; | |
810 | ||
811 | strcpy(input->name, "Syntek USB Camera"); | |
812 | input->type = V4L2_INPUT_TYPE_CAMERA; | |
813 | return 0; | |
814 | } | |
815 | ||
816 | ||
817 | static int stk_vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | |
818 | { | |
819 | *i = 0; | |
820 | return 0; | |
821 | } | |
822 | ||
823 | static int stk_vidioc_s_input(struct file *filp, void *priv, unsigned int i) | |
824 | { | |
b27763f0 | 825 | return i ? -EINVAL : 0; |
ec16dae5 JVJ |
826 | } |
827 | ||
dc0fb286 | 828 | static int stk_s_ctrl(struct v4l2_ctrl *ctrl) |
ec16dae5 | 829 | { |
dc0fb286 HV |
830 | struct stk_camera *dev = |
831 | container_of(ctrl->handler, struct stk_camera, hdl); | |
ec16dae5 | 832 | |
dc0fb286 | 833 | switch (ctrl->id) { |
ec16dae5 | 834 | case V4L2_CID_BRIGHTNESS: |
dc0fb286 | 835 | return stk_sensor_set_brightness(dev, ctrl->val); |
0a58d713 | 836 | case V4L2_CID_HFLIP: |
7a29ee2e | 837 | if (dmi_check_system(stk_upside_down_dmi_table)) |
dc0fb286 | 838 | dev->vsettings.hflip = !ctrl->val; |
7a29ee2e | 839 | else |
dc0fb286 | 840 | dev->vsettings.hflip = ctrl->val; |
0a58d713 HV |
841 | return 0; |
842 | case V4L2_CID_VFLIP: | |
7a29ee2e | 843 | if (dmi_check_system(stk_upside_down_dmi_table)) |
dc0fb286 | 844 | dev->vsettings.vflip = !ctrl->val; |
7a29ee2e | 845 | else |
dc0fb286 | 846 | dev->vsettings.vflip = ctrl->val; |
0a58d713 | 847 | return 0; |
ec16dae5 JVJ |
848 | default: |
849 | return -EINVAL; | |
850 | } | |
851 | return 0; | |
852 | } | |
853 | ||
854 | ||
78b526a4 | 855 | static int stk_vidioc_enum_fmt_vid_cap(struct file *filp, |
ec16dae5 JVJ |
856 | void *priv, struct v4l2_fmtdesc *fmtd) |
857 | { | |
ec16dae5 JVJ |
858 | switch (fmtd->index) { |
859 | case 0: | |
860 | fmtd->pixelformat = V4L2_PIX_FMT_RGB565; | |
861 | strcpy(fmtd->description, "r5g6b5"); | |
862 | break; | |
863 | case 1: | |
864 | fmtd->pixelformat = V4L2_PIX_FMT_RGB565X; | |
865 | strcpy(fmtd->description, "r5g6b5BE"); | |
866 | break; | |
867 | case 2: | |
868 | fmtd->pixelformat = V4L2_PIX_FMT_UYVY; | |
869 | strcpy(fmtd->description, "yuv4:2:2"); | |
870 | break; | |
871 | case 3: | |
872 | fmtd->pixelformat = V4L2_PIX_FMT_SBGGR8; | |
873 | strcpy(fmtd->description, "Raw bayer"); | |
874 | break; | |
1112fb68 JVJ |
875 | case 4: |
876 | fmtd->pixelformat = V4L2_PIX_FMT_YUYV; | |
877 | strcpy(fmtd->description, "yuv4:2:2"); | |
878 | break; | |
ec16dae5 JVJ |
879 | default: |
880 | return -EINVAL; | |
881 | } | |
882 | return 0; | |
883 | } | |
884 | ||
885 | static struct stk_size { | |
886 | unsigned w; | |
887 | unsigned h; | |
888 | enum stk_mode m; | |
889 | } stk_sizes[] = { | |
890 | { .w = 1280, .h = 1024, .m = MODE_SXGA, }, | |
891 | { .w = 640, .h = 480, .m = MODE_VGA, }, | |
892 | { .w = 352, .h = 288, .m = MODE_CIF, }, | |
893 | { .w = 320, .h = 240, .m = MODE_QVGA, }, | |
894 | { .w = 176, .h = 144, .m = MODE_QCIF, }, | |
895 | }; | |
896 | ||
78b526a4 | 897 | static int stk_vidioc_g_fmt_vid_cap(struct file *filp, |
ec16dae5 JVJ |
898 | void *priv, struct v4l2_format *f) |
899 | { | |
900 | struct v4l2_pix_format *pix_format = &f->fmt.pix; | |
10351adc | 901 | struct stk_camera *dev = video_drvdata(filp); |
ec16dae5 JVJ |
902 | int i; |
903 | ||
b57ce417 AS |
904 | for (i = 0; i < ARRAY_SIZE(stk_sizes) && |
905 | stk_sizes[i].m != dev->vsettings.mode; i++) | |
906 | ; | |
ec16dae5 | 907 | if (i == ARRAY_SIZE(stk_sizes)) { |
f1bd9bd6 | 908 | pr_err("ERROR: mode invalid\n"); |
ec16dae5 JVJ |
909 | return -EINVAL; |
910 | } | |
911 | pix_format->width = stk_sizes[i].w; | |
912 | pix_format->height = stk_sizes[i].h; | |
913 | pix_format->field = V4L2_FIELD_NONE; | |
914 | pix_format->colorspace = V4L2_COLORSPACE_SRGB; | |
ec16dae5 JVJ |
915 | pix_format->pixelformat = dev->vsettings.palette; |
916 | if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8) | |
917 | pix_format->bytesperline = pix_format->width; | |
918 | else | |
919 | pix_format->bytesperline = 2 * pix_format->width; | |
920 | pix_format->sizeimage = pix_format->bytesperline | |
921 | * pix_format->height; | |
922 | return 0; | |
923 | } | |
924 | ||
8407653f HV |
925 | static int stk_try_fmt_vid_cap(struct file *filp, |
926 | struct v4l2_format *fmtd, int *idx) | |
ec16dae5 JVJ |
927 | { |
928 | int i; | |
929 | switch (fmtd->fmt.pix.pixelformat) { | |
930 | case V4L2_PIX_FMT_RGB565: | |
931 | case V4L2_PIX_FMT_RGB565X: | |
932 | case V4L2_PIX_FMT_UYVY: | |
1112fb68 | 933 | case V4L2_PIX_FMT_YUYV: |
ec16dae5 JVJ |
934 | case V4L2_PIX_FMT_SBGGR8: |
935 | break; | |
936 | default: | |
937 | return -EINVAL; | |
938 | } | |
939 | for (i = 1; i < ARRAY_SIZE(stk_sizes); i++) { | |
940 | if (fmtd->fmt.pix.width > stk_sizes[i].w) | |
941 | break; | |
942 | } | |
943 | if (i == ARRAY_SIZE(stk_sizes) | |
944 | || (abs(fmtd->fmt.pix.width - stk_sizes[i-1].w) | |
945 | < abs(fmtd->fmt.pix.width - stk_sizes[i].w))) { | |
946 | fmtd->fmt.pix.height = stk_sizes[i-1].h; | |
947 | fmtd->fmt.pix.width = stk_sizes[i-1].w; | |
8407653f HV |
948 | if (idx) |
949 | *idx = i - 1; | |
ec16dae5 JVJ |
950 | } else { |
951 | fmtd->fmt.pix.height = stk_sizes[i].h; | |
952 | fmtd->fmt.pix.width = stk_sizes[i].w; | |
8407653f HV |
953 | if (idx) |
954 | *idx = i; | |
ec16dae5 JVJ |
955 | } |
956 | ||
957 | fmtd->fmt.pix.field = V4L2_FIELD_NONE; | |
958 | fmtd->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; | |
959 | if (fmtd->fmt.pix.pixelformat == V4L2_PIX_FMT_SBGGR8) | |
960 | fmtd->fmt.pix.bytesperline = fmtd->fmt.pix.width; | |
961 | else | |
962 | fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width; | |
963 | fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline | |
964 | * fmtd->fmt.pix.height; | |
965 | return 0; | |
966 | } | |
967 | ||
8407653f HV |
968 | static int stk_vidioc_try_fmt_vid_cap(struct file *filp, |
969 | void *priv, struct v4l2_format *fmtd) | |
970 | { | |
971 | return stk_try_fmt_vid_cap(filp, fmtd, NULL); | |
972 | } | |
973 | ||
1fdd61c0 JVJ |
974 | static int stk_setup_format(struct stk_camera *dev) |
975 | { | |
976 | int i = 0; | |
977 | int depth; | |
978 | if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8) | |
979 | depth = 1; | |
980 | else | |
981 | depth = 2; | |
77f2c2db RK |
982 | while (i < ARRAY_SIZE(stk_sizes) && |
983 | stk_sizes[i].m != dev->vsettings.mode) | |
1fdd61c0 JVJ |
984 | i++; |
985 | if (i == ARRAY_SIZE(stk_sizes)) { | |
f1bd9bd6 | 986 | pr_err("Something is broken in %s\n", __func__); |
1fdd61c0 JVJ |
987 | return -EFAULT; |
988 | } | |
989 | /* This registers controls some timings, not sure of what. */ | |
990 | stk_camera_write_reg(dev, 0x001b, 0x0e); | |
991 | if (dev->vsettings.mode == MODE_SXGA) | |
992 | stk_camera_write_reg(dev, 0x001c, 0x0e); | |
993 | else | |
994 | stk_camera_write_reg(dev, 0x001c, 0x46); | |
995 | /* | |
996 | * Registers 0x0115 0x0114 are the size of each line (bytes), | |
997 | * regs 0x0117 0x0116 are the heigth of the image. | |
998 | */ | |
999 | stk_camera_write_reg(dev, 0x0115, | |
1000 | ((stk_sizes[i].w * depth) >> 8) & 0xff); | |
1001 | stk_camera_write_reg(dev, 0x0114, | |
1002 | (stk_sizes[i].w * depth) & 0xff); | |
1003 | stk_camera_write_reg(dev, 0x0117, | |
1004 | (stk_sizes[i].h >> 8) & 0xff); | |
1005 | stk_camera_write_reg(dev, 0x0116, | |
1006 | stk_sizes[i].h & 0xff); | |
1007 | return stk_sensor_configure(dev); | |
1008 | } | |
1009 | ||
78b526a4 | 1010 | static int stk_vidioc_s_fmt_vid_cap(struct file *filp, |
ec16dae5 JVJ |
1011 | void *priv, struct v4l2_format *fmtd) |
1012 | { | |
1013 | int ret; | |
8407653f | 1014 | int idx; |
10351adc | 1015 | struct stk_camera *dev = video_drvdata(filp); |
ec16dae5 JVJ |
1016 | |
1017 | if (dev == NULL) | |
1018 | return -ENODEV; | |
1019 | if (!is_present(dev)) | |
1020 | return -ENODEV; | |
1021 | if (is_streaming(dev)) | |
1022 | return -EBUSY; | |
f81e372a | 1023 | if (dev->owner) |
ec16dae5 | 1024 | return -EBUSY; |
8407653f | 1025 | ret = stk_try_fmt_vid_cap(filp, fmtd, &idx); |
ec16dae5 JVJ |
1026 | if (ret) |
1027 | return ret; | |
1028 | ||
1029 | dev->vsettings.palette = fmtd->fmt.pix.pixelformat; | |
1030 | stk_free_buffers(dev); | |
1031 | dev->frame_size = fmtd->fmt.pix.sizeimage; | |
8407653f | 1032 | dev->vsettings.mode = stk_sizes[idx].m; |
ec16dae5 JVJ |
1033 | |
1034 | stk_initialise(dev); | |
1fdd61c0 | 1035 | return stk_setup_format(dev); |
ec16dae5 JVJ |
1036 | } |
1037 | ||
1038 | static int stk_vidioc_reqbufs(struct file *filp, | |
1039 | void *priv, struct v4l2_requestbuffers *rb) | |
1040 | { | |
10351adc | 1041 | struct stk_camera *dev = video_drvdata(filp); |
ec16dae5 JVJ |
1042 | |
1043 | if (dev == NULL) | |
1044 | return -ENODEV; | |
ec16dae5 JVJ |
1045 | if (rb->memory != V4L2_MEMORY_MMAP) |
1046 | return -EINVAL; | |
1047 | if (is_streaming(dev) | |
1048 | || (dev->owner && dev->owner != filp)) | |
1049 | return -EBUSY; | |
9776e171 HV |
1050 | stk_free_buffers(dev); |
1051 | if (rb->count == 0) { | |
1052 | stk_camera_write_reg(dev, 0x0, 0x49); /* turn off the LED */ | |
1053 | unset_initialised(dev); | |
1054 | dev->owner = NULL; | |
1055 | return 0; | |
1056 | } | |
ec16dae5 JVJ |
1057 | dev->owner = filp; |
1058 | ||
1059 | /*FIXME If they ask for zero, we must stop streaming and free */ | |
1060 | if (rb->count < 3) | |
1061 | rb->count = 3; | |
1062 | /* Arbitrary limit */ | |
1063 | else if (rb->count > 5) | |
1064 | rb->count = 5; | |
1065 | ||
1066 | stk_allocate_buffers(dev, rb->count); | |
1067 | rb->count = dev->n_sbufs; | |
1068 | return 0; | |
1069 | } | |
1070 | ||
1071 | static int stk_vidioc_querybuf(struct file *filp, | |
1072 | void *priv, struct v4l2_buffer *buf) | |
1073 | { | |
10351adc | 1074 | struct stk_camera *dev = video_drvdata(filp); |
ec16dae5 JVJ |
1075 | struct stk_sio_buffer *sbuf; |
1076 | ||
223ffe5f | 1077 | if (buf->index >= dev->n_sbufs) |
ec16dae5 JVJ |
1078 | return -EINVAL; |
1079 | sbuf = dev->sio_bufs + buf->index; | |
1080 | *buf = sbuf->v4lbuf; | |
1081 | return 0; | |
1082 | } | |
1083 | ||
1084 | static int stk_vidioc_qbuf(struct file *filp, | |
1085 | void *priv, struct v4l2_buffer *buf) | |
1086 | { | |
10351adc | 1087 | struct stk_camera *dev = video_drvdata(filp); |
ec16dae5 JVJ |
1088 | struct stk_sio_buffer *sbuf; |
1089 | unsigned long flags; | |
ec16dae5 JVJ |
1090 | |
1091 | if (buf->memory != V4L2_MEMORY_MMAP) | |
1092 | return -EINVAL; | |
1093 | ||
223ffe5f | 1094 | if (buf->index >= dev->n_sbufs) |
ec16dae5 JVJ |
1095 | return -EINVAL; |
1096 | sbuf = dev->sio_bufs + buf->index; | |
1097 | if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) | |
1098 | return 0; | |
1099 | sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED; | |
1100 | sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE; | |
1101 | spin_lock_irqsave(&dev->spinlock, flags); | |
1102 | list_add_tail(&sbuf->list, &dev->sio_avail); | |
1103 | *buf = sbuf->v4lbuf; | |
1104 | spin_unlock_irqrestore(&dev->spinlock, flags); | |
1105 | return 0; | |
1106 | } | |
1107 | ||
1108 | static int stk_vidioc_dqbuf(struct file *filp, | |
1109 | void *priv, struct v4l2_buffer *buf) | |
1110 | { | |
10351adc | 1111 | struct stk_camera *dev = video_drvdata(filp); |
ec16dae5 JVJ |
1112 | struct stk_sio_buffer *sbuf; |
1113 | unsigned long flags; | |
1114 | int ret; | |
1115 | ||
2509e1cb | 1116 | if (!is_streaming(dev)) |
ec16dae5 JVJ |
1117 | return -EINVAL; |
1118 | ||
1119 | if (filp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full)) | |
1120 | return -EWOULDBLOCK; | |
1121 | ret = wait_event_interruptible(dev->wait_frame, | |
1122 | !list_empty(&dev->sio_full) || !is_present(dev)); | |
1123 | if (ret) | |
1124 | return ret; | |
1125 | if (!is_present(dev)) | |
1126 | return -EIO; | |
1127 | ||
1128 | spin_lock_irqsave(&dev->spinlock, flags); | |
1129 | sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list); | |
1130 | list_del_init(&sbuf->list); | |
1131 | spin_unlock_irqrestore(&dev->spinlock, flags); | |
1132 | sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED; | |
1133 | sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE; | |
1134 | sbuf->v4lbuf.sequence = ++dev->sequence; | |
8e6057b5 | 1135 | v4l2_get_timestamp(&sbuf->v4lbuf.timestamp); |
ec16dae5 JVJ |
1136 | |
1137 | *buf = sbuf->v4lbuf; | |
1138 | return 0; | |
1139 | } | |
1140 | ||
1141 | static int stk_vidioc_streamon(struct file *filp, | |
1142 | void *priv, enum v4l2_buf_type type) | |
1143 | { | |
10351adc | 1144 | struct stk_camera *dev = video_drvdata(filp); |
ec16dae5 JVJ |
1145 | if (is_streaming(dev)) |
1146 | return 0; | |
1147 | if (dev->sio_bufs == NULL) | |
1148 | return -EINVAL; | |
1149 | dev->sequence = 0; | |
1150 | return stk_start_stream(dev); | |
1151 | } | |
1152 | ||
1153 | static int stk_vidioc_streamoff(struct file *filp, | |
1154 | void *priv, enum v4l2_buf_type type) | |
1155 | { | |
10351adc | 1156 | struct stk_camera *dev = video_drvdata(filp); |
ec16dae5 JVJ |
1157 | unsigned long flags; |
1158 | int i; | |
1159 | stk_stop_stream(dev); | |
1160 | spin_lock_irqsave(&dev->spinlock, flags); | |
1161 | INIT_LIST_HEAD(&dev->sio_avail); | |
1162 | INIT_LIST_HEAD(&dev->sio_full); | |
1163 | for (i = 0; i < dev->n_sbufs; i++) { | |
1164 | INIT_LIST_HEAD(&dev->sio_bufs[i].list); | |
1165 | dev->sio_bufs[i].v4lbuf.flags = 0; | |
1166 | } | |
1167 | spin_unlock_irqrestore(&dev->spinlock, flags); | |
1168 | return 0; | |
1169 | } | |
1170 | ||
1171 | ||
1172 | static int stk_vidioc_g_parm(struct file *filp, | |
1173 | void *priv, struct v4l2_streamparm *sp) | |
1174 | { | |
ec16dae5 JVJ |
1175 | /*FIXME This is not correct */ |
1176 | sp->parm.capture.timeperframe.numerator = 1; | |
1177 | sp->parm.capture.timeperframe.denominator = 30; | |
1178 | sp->parm.capture.readbuffers = 2; | |
ec16dae5 JVJ |
1179 | return 0; |
1180 | } | |
1181 | ||
126be90f JVJ |
1182 | static int stk_vidioc_enum_framesizes(struct file *filp, |
1183 | void *priv, struct v4l2_frmsizeenum *frms) | |
1184 | { | |
1185 | if (frms->index >= ARRAY_SIZE(stk_sizes)) | |
1186 | return -EINVAL; | |
1187 | switch (frms->pixel_format) { | |
1188 | case V4L2_PIX_FMT_RGB565: | |
1189 | case V4L2_PIX_FMT_RGB565X: | |
1190 | case V4L2_PIX_FMT_UYVY: | |
1191 | case V4L2_PIX_FMT_YUYV: | |
1192 | case V4L2_PIX_FMT_SBGGR8: | |
1193 | frms->type = V4L2_FRMSIZE_TYPE_DISCRETE; | |
1194 | frms->discrete.width = stk_sizes[frms->index].w; | |
1195 | frms->discrete.height = stk_sizes[frms->index].h; | |
1196 | return 0; | |
1197 | default: return -EINVAL; | |
1198 | } | |
1199 | } | |
1200 | ||
dc0fb286 HV |
1201 | static const struct v4l2_ctrl_ops stk_ctrl_ops = { |
1202 | .s_ctrl = stk_s_ctrl, | |
1203 | }; | |
1204 | ||
ff05c984 | 1205 | static const struct v4l2_file_operations v4l_stk_fops = { |
ec16dae5 JVJ |
1206 | .owner = THIS_MODULE, |
1207 | .open = v4l_stk_open, | |
1208 | .release = v4l_stk_release, | |
1209 | .read = v4l_stk_read, | |
1210 | .poll = v4l_stk_poll, | |
1211 | .mmap = v4l_stk_mmap, | |
f80daa2d | 1212 | .unlocked_ioctl = video_ioctl2, |
ec16dae5 JVJ |
1213 | }; |
1214 | ||
a399810c | 1215 | static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = { |
ec16dae5 | 1216 | .vidioc_querycap = stk_vidioc_querycap, |
78b526a4 HV |
1217 | .vidioc_enum_fmt_vid_cap = stk_vidioc_enum_fmt_vid_cap, |
1218 | .vidioc_try_fmt_vid_cap = stk_vidioc_try_fmt_vid_cap, | |
1219 | .vidioc_s_fmt_vid_cap = stk_vidioc_s_fmt_vid_cap, | |
1220 | .vidioc_g_fmt_vid_cap = stk_vidioc_g_fmt_vid_cap, | |
ec16dae5 JVJ |
1221 | .vidioc_enum_input = stk_vidioc_enum_input, |
1222 | .vidioc_s_input = stk_vidioc_s_input, | |
1223 | .vidioc_g_input = stk_vidioc_g_input, | |
ec16dae5 JVJ |
1224 | .vidioc_reqbufs = stk_vidioc_reqbufs, |
1225 | .vidioc_querybuf = stk_vidioc_querybuf, | |
1226 | .vidioc_qbuf = stk_vidioc_qbuf, | |
1227 | .vidioc_dqbuf = stk_vidioc_dqbuf, | |
1228 | .vidioc_streamon = stk_vidioc_streamon, | |
1229 | .vidioc_streamoff = stk_vidioc_streamoff, | |
ec16dae5 | 1230 | .vidioc_g_parm = stk_vidioc_g_parm, |
126be90f | 1231 | .vidioc_enum_framesizes = stk_vidioc_enum_framesizes, |
89ea4706 HV |
1232 | .vidioc_log_status = v4l2_ctrl_log_status, |
1233 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | |
1234 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | |
ec16dae5 JVJ |
1235 | }; |
1236 | ||
a399810c HV |
1237 | static void stk_v4l_dev_release(struct video_device *vd) |
1238 | { | |
4aaec3ea DE |
1239 | struct stk_camera *dev = vdev_to_camera(vd); |
1240 | ||
1241 | if (dev->sio_bufs != NULL || dev->isobufs != NULL) | |
f1bd9bd6 | 1242 | pr_err("We are leaking memory\n"); |
4aaec3ea | 1243 | usb_put_intf(dev->interface); |
a399810c HV |
1244 | } |
1245 | ||
86844942 | 1246 | static const struct video_device stk_v4l_data = { |
a399810c | 1247 | .name = "stkwebcam", |
a399810c HV |
1248 | .fops = &v4l_stk_fops, |
1249 | .ioctl_ops = &v4l_stk_ioctl_ops, | |
1250 | .release = stk_v4l_dev_release, | |
1251 | }; | |
1252 | ||
ec16dae5 JVJ |
1253 | |
1254 | static int stk_register_video_device(struct stk_camera *dev) | |
1255 | { | |
1256 | int err; | |
1257 | ||
1258 | dev->vdev = stk_v4l_data; | |
f80daa2d | 1259 | dev->vdev.lock = &dev->lock; |
968c60f6 | 1260 | dev->vdev.v4l2_dev = &dev->v4l2_dev; |
10351adc | 1261 | video_set_drvdata(&dev->vdev, dev); |
ec16dae5 JVJ |
1262 | err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); |
1263 | if (err) | |
f1bd9bd6 | 1264 | pr_err("v4l registration failed\n"); |
ec16dae5 | 1265 | else |
f1bd9bd6 JP |
1266 | pr_info("Syntek USB2.0 Camera is now controlling device %s\n", |
1267 | video_device_node_name(&dev->vdev)); | |
ec16dae5 JVJ |
1268 | return err; |
1269 | } | |
1270 | ||
1271 | ||
1272 | /* USB Stuff */ | |
1273 | ||
1274 | static int stk_camera_probe(struct usb_interface *interface, | |
1275 | const struct usb_device_id *id) | |
1276 | { | |
dc0fb286 | 1277 | struct v4l2_ctrl_handler *hdl; |
4aaec3ea | 1278 | int err = 0; |
dc0fb286 | 1279 | int i; |
ec16dae5 JVJ |
1280 | |
1281 | struct stk_camera *dev = NULL; | |
1282 | struct usb_device *udev = interface_to_usbdev(interface); | |
1283 | struct usb_host_interface *iface_desc; | |
1284 | struct usb_endpoint_descriptor *endpoint; | |
1285 | ||
1286 | dev = kzalloc(sizeof(struct stk_camera), GFP_KERNEL); | |
1287 | if (dev == NULL) { | |
f1bd9bd6 | 1288 | pr_err("Out of memory !\n"); |
ec16dae5 JVJ |
1289 | return -ENOMEM; |
1290 | } | |
968c60f6 HV |
1291 | err = v4l2_device_register(&interface->dev, &dev->v4l2_dev); |
1292 | if (err < 0) { | |
1293 | dev_err(&udev->dev, "couldn't register v4l2_device\n"); | |
1294 | kfree(dev); | |
1295 | return err; | |
1296 | } | |
dc0fb286 HV |
1297 | hdl = &dev->hdl; |
1298 | v4l2_ctrl_handler_init(hdl, 3); | |
1299 | v4l2_ctrl_new_std(hdl, &stk_ctrl_ops, | |
1300 | V4L2_CID_BRIGHTNESS, 0, 0xff, 0x1, 0x60); | |
1301 | v4l2_ctrl_new_std(hdl, &stk_ctrl_ops, | |
1302 | V4L2_CID_HFLIP, 0, 1, 1, 1); | |
1303 | v4l2_ctrl_new_std(hdl, &stk_ctrl_ops, | |
1304 | V4L2_CID_VFLIP, 0, 1, 1, 1); | |
1305 | if (hdl->error) { | |
1306 | err = hdl->error; | |
1307 | dev_err(&udev->dev, "couldn't register control\n"); | |
1308 | goto error; | |
1309 | } | |
1310 | dev->v4l2_dev.ctrl_handler = hdl; | |
ec16dae5 | 1311 | |
ec16dae5 | 1312 | spin_lock_init(&dev->spinlock); |
f80daa2d | 1313 | mutex_init(&dev->lock); |
ec16dae5 | 1314 | init_waitqueue_head(&dev->wait_frame); |
89ea4706 | 1315 | dev->first_init = 1; /* webcam LED management */ |
ec16dae5 JVJ |
1316 | |
1317 | dev->udev = udev; | |
1318 | dev->interface = interface; | |
1319 | usb_get_intf(interface); | |
1320 | ||
7a29ee2e HG |
1321 | if (hflip != -1) |
1322 | dev->vsettings.hflip = hflip; | |
1323 | else if (dmi_check_system(stk_upside_down_dmi_table)) | |
1324 | dev->vsettings.hflip = 1; | |
1325 | else | |
1326 | dev->vsettings.hflip = 0; | |
1327 | if (vflip != -1) | |
1328 | dev->vsettings.vflip = vflip; | |
1329 | else if (dmi_check_system(stk_upside_down_dmi_table)) | |
1330 | dev->vsettings.vflip = 1; | |
1331 | else | |
1332 | dev->vsettings.vflip = 0; | |
ec16dae5 JVJ |
1333 | dev->n_sbufs = 0; |
1334 | set_present(dev); | |
1335 | ||
1336 | /* Set up the endpoint information | |
1337 | * use only the first isoc-in endpoint | |
1338 | * for the current alternate setting */ | |
1339 | iface_desc = interface->cur_altsetting; | |
1340 | ||
1341 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | |
1342 | endpoint = &iface_desc->endpoint[i].desc; | |
1343 | ||
1344 | if (!dev->isoc_ep | |
13417982 | 1345 | && usb_endpoint_is_isoc_in(endpoint)) { |
ec16dae5 | 1346 | /* we found an isoc in endpoint */ |
13417982 | 1347 | dev->isoc_ep = usb_endpoint_num(endpoint); |
ec16dae5 JVJ |
1348 | break; |
1349 | } | |
1350 | } | |
1351 | if (!dev->isoc_ep) { | |
f1bd9bd6 | 1352 | pr_err("Could not find isoc-in endpoint\n"); |
4aaec3ea DE |
1353 | err = -ENODEV; |
1354 | goto error; | |
ec16dae5 | 1355 | } |
ec16dae5 JVJ |
1356 | dev->vsettings.palette = V4L2_PIX_FMT_RGB565; |
1357 | dev->vsettings.mode = MODE_VGA; | |
1112fb68 | 1358 | dev->frame_size = 640 * 480 * 2; |
ec16dae5 JVJ |
1359 | |
1360 | INIT_LIST_HEAD(&dev->sio_avail); | |
1361 | INIT_LIST_HEAD(&dev->sio_full); | |
1362 | ||
1363 | usb_set_intfdata(interface, dev); | |
1364 | ||
1365 | err = stk_register_video_device(dev); | |
b57ce417 | 1366 | if (err) |
4aaec3ea | 1367 | goto error; |
ec16dae5 | 1368 | |
ec16dae5 | 1369 | return 0; |
4aaec3ea DE |
1370 | |
1371 | error: | |
dc0fb286 | 1372 | v4l2_ctrl_handler_free(hdl); |
968c60f6 | 1373 | v4l2_device_unregister(&dev->v4l2_dev); |
4aaec3ea DE |
1374 | kfree(dev); |
1375 | return err; | |
ec16dae5 JVJ |
1376 | } |
1377 | ||
1378 | static void stk_camera_disconnect(struct usb_interface *interface) | |
1379 | { | |
1380 | struct stk_camera *dev = usb_get_intfdata(interface); | |
1381 | ||
1382 | usb_set_intfdata(interface, NULL); | |
1383 | unset_present(dev); | |
1384 | ||
1385 | wake_up_interruptible(&dev->wait_frame); | |
ec16dae5 | 1386 | |
f1bd9bd6 JP |
1387 | pr_info("Syntek USB2.0 Camera release resources device %s\n", |
1388 | video_device_node_name(&dev->vdev)); | |
4aaec3ea DE |
1389 | |
1390 | video_unregister_device(&dev->vdev); | |
dc0fb286 | 1391 | v4l2_ctrl_handler_free(&dev->hdl); |
968c60f6 | 1392 | v4l2_device_unregister(&dev->v4l2_dev); |
6e298d58 | 1393 | kfree(dev); |
ec16dae5 JVJ |
1394 | } |
1395 | ||
1fdd61c0 | 1396 | #ifdef CONFIG_PM |
4d34dccd | 1397 | static int stk_camera_suspend(struct usb_interface *intf, pm_message_t message) |
1fdd61c0 JVJ |
1398 | { |
1399 | struct stk_camera *dev = usb_get_intfdata(intf); | |
1400 | if (is_streaming(dev)) { | |
1401 | stk_stop_stream(dev); | |
1402 | /* yes, this is ugly */ | |
1403 | set_streaming(dev); | |
1404 | } | |
1405 | return 0; | |
1406 | } | |
1407 | ||
4d34dccd | 1408 | static int stk_camera_resume(struct usb_interface *intf) |
1fdd61c0 JVJ |
1409 | { |
1410 | struct stk_camera *dev = usb_get_intfdata(intf); | |
1411 | if (!is_initialised(dev)) | |
1412 | return 0; | |
1413 | unset_initialised(dev); | |
1414 | stk_initialise(dev); | |
7b1c8f58 | 1415 | stk_camera_write_reg(dev, 0x0, 0x49); |
1fdd61c0 JVJ |
1416 | stk_setup_format(dev); |
1417 | if (is_streaming(dev)) | |
1418 | stk_start_stream(dev); | |
1419 | return 0; | |
1420 | } | |
1421 | #endif | |
1422 | ||
ec16dae5 JVJ |
1423 | static struct usb_driver stk_camera_driver = { |
1424 | .name = "stkwebcam", | |
1425 | .probe = stk_camera_probe, | |
1426 | .disconnect = stk_camera_disconnect, | |
1427 | .id_table = stkwebcam_table, | |
1fdd61c0 JVJ |
1428 | #ifdef CONFIG_PM |
1429 | .suspend = stk_camera_suspend, | |
1430 | .resume = stk_camera_resume, | |
1431 | #endif | |
ec16dae5 JVJ |
1432 | }; |
1433 | ||
ecb3b2b3 | 1434 | module_usb_driver(stk_camera_driver); |