blob: 6049a2278190c3fc62ce1ed64ee5adfcf67a1a31 [file] [log] [blame]
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001/*
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -08002 em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08003
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -08004 Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
5 Markus Rechberger <mrechberger@gmail.com>
Mauro Carvalho Chehab2e7c6dc2006-04-03 07:53:40 -03006 Mauro Carvalho Chehab <mchehab@infradead.org>
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -08007 Sascha Sommer <saschasommer@freenet.de>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08008
Mauro Carvalho Chehab439090d2006-01-23 17:10:54 -02009 Some parts based on SN9C10x PC Camera Controllers GPL driver made
10 by Luca Risolia <luca.risolia@studio.unibo.it>
11
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080012 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#include <linux/init.h>
28#include <linux/list.h>
29#include <linux/module.h>
30#include <linux/kernel.h>
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020031#include <linux/bitmap.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080032#include <linux/usb.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080033#include <linux/i2c.h>
Mauro Carvalho Chehabb296fc62005-11-08 21:38:37 -080034#include <linux/version.h>
Trent Piepho6d35c8f2007-11-01 01:16:09 -030035#include <linux/mm.h>
Ingo Molnar1e4baed2006-01-15 07:52:23 -020036#include <linux/mutex.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080037
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080038#include "em28xx.h"
Mauro Carvalho Chehabc0477ad2006-01-09 15:25:14 -020039#include <media/v4l2-common.h>
Hans Verkuil2474ed42006-03-19 12:35:57 -030040#include <media/msp3400.h>
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -030041#include <media/tuner.h>
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080042
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080043#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
44 "Markus Rechberger <mrechberger@gmail.com>, " \
Mauro Carvalho Chehab2e7c6dc2006-04-03 07:53:40 -030045 "Mauro Carvalho Chehab <mchehab@infradead.org>, " \
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080046 "Sascha Sommer <saschasommer@freenet.de>"
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080047
Mauro Carvalho Chehabf7abcd32005-11-08 21:38:25 -080048#define DRIVER_NAME "em28xx"
49#define DRIVER_DESC "Empia em28xx based USB video device driver"
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -030050#define EM28XX_VERSION_CODE KERNEL_VERSION(0, 1, 0)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080051
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080052#define em28xx_videodbg(fmt, arg...) do {\
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -080053 if (video_debug) \
54 printk(KERN_INFO "%s %s :"fmt, \
Harvey Harrisond80e1342008-04-08 23:20:00 -030055 dev->name, __func__ , ##arg); } while (0)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080056
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -030057static unsigned int isoc_debug;
58module_param(isoc_debug,int,0644);
59MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]");
60
61#define em28xx_isocdbg(fmt, arg...) do {\
62 if (isoc_debug) \
63 printk(KERN_INFO "%s %s :"fmt, \
64 dev->name, __FUNCTION__ , ##arg); } while (0)
65
66#define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
67
68/* Limits minimum and default number of buffers */
69#define EM28XX_MIN_BUF 4
70#define EM28XX_DEF_BUF 8
71
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080072MODULE_AUTHOR(DRIVER_AUTHOR);
73MODULE_DESCRIPTION(DRIVER_DESC);
74MODULE_LICENSE("GPL");
75
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -080076static LIST_HEAD(em28xx_devlist);
Markus Rechberger9c755412005-11-08 21:37:52 -080077
Mauro Carvalho Chehab9d4d9c02005-11-08 21:38:52 -080078static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020079static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030080static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
81static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
82
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080083module_param_array(card, int, NULL, 0444);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020084module_param_array(video_nr, int, NULL, 0444);
85module_param_array(vbi_nr, int, NULL, 0444);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -030086module_param_array(radio_nr, int, NULL, 0444);
87MODULE_PARM_DESC(card, "card type");
88MODULE_PARM_DESC(video_nr, "video device numbers");
89MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
90MODULE_PARM_DESC(radio_nr, "radio device numbers");
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -080091
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030092static unsigned int video_debug;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080093module_param(video_debug,int,0644);
94MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
95
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -020096/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
97static unsigned long em28xx_devused;
98
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -080099/* supported controls */
Mauro Carvalho Chehabc0477ad2006-01-09 15:25:14 -0200100/* Common to all boards */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800101static struct v4l2_queryctrl em28xx_qctrl[] = {
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800102 {
Mauro Carvalho Chehabc0477ad2006-01-09 15:25:14 -0200103 .id = V4L2_CID_AUDIO_VOLUME,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Volume",
106 .minimum = 0x0,
107 .maximum = 0x1f,
108 .step = 0x1,
109 .default_value = 0x1f,
110 .flags = 0,
111 },{
112 .id = V4L2_CID_AUDIO_MUTE,
113 .type = V4L2_CTRL_TYPE_BOOLEAN,
114 .name = "Mute",
115 .minimum = 0,
116 .maximum = 1,
117 .step = 1,
118 .default_value = 1,
119 .flags = 0,
120 }
121};
122
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800123static struct usb_driver em28xx_usb_driver;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800124
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300125/* ------------------------------------------------------------------
126 DMA and thread functions
127 ------------------------------------------------------------------*/
128
129/*
130 * Announces that a buffer were filled and request the next
131 */
132static void inline buffer_filled (struct em28xx *dev,
133 struct em28xx_dmaqueue *dma_q,
134 struct em28xx_buffer *buf)
135{
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300136 mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
137
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300138 /* Nobody is waiting something to be done, just return */
139 if (!waitqueue_active(&buf->vb.done)) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300140 printk(KERN_ERR "em28xx: buffer underrun at %ld\n",
141 jiffies);
142
143 return;
144 }
145
146 /* Advice that buffer was filled */
147 em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
148 buf->vb.state = VIDEOBUF_DONE;
149 buf->vb.field_count++;
150 do_gettimeofday(&buf->vb.ts);
151
152 list_del(&buf->vb.queue);
153 wake_up(&buf->vb.done);
154}
155
156/*
157 * Identify the buffer header type and properly handles
158 */
159static void em28xx_copy_video(struct em28xx *dev,
160 struct em28xx_dmaqueue *dma_q,
161 struct em28xx_buffer *buf,
162 unsigned char *p,
163 unsigned char *outp, unsigned long len)
164{
165 void *fieldstart, *startwrite, *startread;
166 int linesdone, currlinedone, offset, lencopy,remain;
167
168 if(dev->frame_size != buf->vb.size){
169 em28xx_errdev("size %i and buf.length %lu are different!\n",
170 dev->frame_size, buf->vb.size);
171 return;
172 }
173
174 if (dma_q->pos + len > buf->vb.size)
175 len = buf->vb.size - dma_q->pos;
176
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300177 if (p[0] != 0x88 && p[0] != 0x22) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300178 em28xx_isocdbg("frame is not complete\n");
179 len += 4;
180 } else
181 p +=4;
182
183 startread = p;
184 remain = len;
185
186 /* Interlaces frame */
187 if (buf->top_field)
188 fieldstart = outp;
189 else
190 fieldstart = outp + dev->bytesperline;
191
192 linesdone = dma_q->pos / dev->bytesperline;
193 currlinedone = dma_q->pos % dev->bytesperline;
194 offset = linesdone * dev->bytesperline * 2 + currlinedone;
195 startwrite = fieldstart + offset;
196 lencopy = dev->bytesperline - currlinedone;
197 lencopy = lencopy > remain ? remain : lencopy;
198
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300199 if((char*)startwrite + lencopy > (char*)outp + buf->vb.size) {
Mauro Carvalho Chehabea8df7e2008-04-13 14:39:29 -0300200 em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300201 ((char*)startwrite + lencopy) - ((char*)outp + buf->vb.size));
202 lencopy = remain = (char*)outp + buf->vb.size - (char*)startwrite;
203 }
204 BUG_ON(lencopy <= 0);
205 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300206
207 remain -= lencopy;
208
209 while (remain > 0) {
210 startwrite += lencopy + dev->bytesperline;
211 startread += lencopy;
212 if (dev->bytesperline > remain)
213 lencopy = remain;
214 else
215 lencopy = dev->bytesperline;
216
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300217 BUG_ON(lencopy <= 0);
218
219 if((char*)startwrite + lencopy > (char*)outp + buf->vb.size) {
Mauro Carvalho Chehabea8df7e2008-04-13 14:39:29 -0300220 em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n",
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300221 ((char*)startwrite + lencopy) - ((char*)outp + buf->vb.size));
222 lencopy = remain = (char*)outp + buf->vb.size - (char*)startwrite;
223 }
224 if(lencopy <= 0) break;
225
226 memcpy(startwrite, startread, lencopy);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300227
228 remain -= lencopy;
229 }
230
231 dma_q->pos += len;
232}
233
234static void inline print_err_status (struct em28xx *dev,
235 int packet, int status)
236{
237 char *errmsg = "Unknown";
238
239 switch(status) {
240 case -ENOENT:
241 errmsg = "unlinked synchronuously";
242 break;
243 case -ECONNRESET:
244 errmsg = "unlinked asynchronuously";
245 break;
246 case -ENOSR:
247 errmsg = "Buffer error (overrun)";
248 break;
249 case -EPIPE:
250 errmsg = "Stalled (device not responding)";
251 break;
252 case -EOVERFLOW:
253 errmsg = "Babble (bad cable?)";
254 break;
255 case -EPROTO:
256 errmsg = "Bit-stuff error (bad cable?)";
257 break;
258 case -EILSEQ:
259 errmsg = "CRC/Timeout (could be anything)";
260 break;
261 case -ETIME:
262 errmsg = "Device does not respond";
263 break;
264 }
265 if (packet<0) {
266 em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
267 } else {
268 em28xx_isocdbg("URB packet %d, status %d [%s].\n",
269 packet, status, errmsg);
270 }
271}
272
273/*
274 * video-buf generic routine to get the next available buffer
275 */
276static int inline get_next_buf (struct em28xx_dmaqueue *dma_q,
277 struct em28xx_buffer **buf)
278{
279 struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
280
281 if (list_empty(&dma_q->active)) {
282 em28xx_isocdbg("No active queue to serve\n");
283 return 0;
284 }
285
286 *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
287
288 return 1;
289}
290
291/*
292 * Controls the isoc copy of each urb packet
293 */
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300294static inline int em28xx_isoc_copy(struct urb *urb)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300295{
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300296 struct em28xx_buffer *buf;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300297 struct em28xx_dmaqueue *dma_q = urb->context;
298 struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300299 unsigned char *outp;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300300 int i, len = 0, rc = 1;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300301 unsigned char *p;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300302
303 if (!dev)
304 return 0;
305
306 if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
307 return 0;
308
309 if (urb->status<0) {
310 print_err_status (dev,-1,urb->status);
311 if (urb->status == -ENOENT)
312 return 0;
313 }
314
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300315 buf=dev->isoc_ctl.buf;
316
317 if (!buf) {
318 rc=get_next_buf (dma_q, &buf);
319 if (rc<=0)
320 return rc;
321 }
322
323 outp = videobuf_to_vmalloc (&buf->vb);
324
325
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300326 for (i = 0; i < urb->number_of_packets; i++) {
327 int status = urb->iso_frame_desc[i].status;
328
329 if (status<0) {
330 print_err_status (dev,i,status);
331 if (urb->iso_frame_desc[i].status != -EPROTO)
332 continue;
333 }
334
335 len=urb->iso_frame_desc[i].actual_length - 4;
336
337 if (urb->iso_frame_desc[i].actual_length <= 0) {
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300338 /* em28xx_isocdbg("packet %d is empty",i); - spammy */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300339 continue;
340 }
341 if (urb->iso_frame_desc[i].actual_length >
342 dev->max_pkt_size) {
343 em28xx_isocdbg("packet bigger than packet size");
344 continue;
345 }
346
347 p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300348
349 /* FIXME: incomplete buffer checks where removed to make
350 logic simpler. Impacts of those changes should be evaluated
351 */
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300352 if (p[0] == 0x22 && p[1] == 0x5a) {
353 /* FIXME - are the fields the right way around? */
354 em28xx_isocdbg("Video frame, length=%i, %s\n", len,
355 (p[2] & 1)? "top" : "bottom");
356 em28xx_isocdbg("Current buffer is: outp = 0x%p, len = %i\n", outp, (int)buf->vb.size);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300357
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300358 if (p[2] & 1) {
359 if (buf->receiving) {
360 buffer_filled (dev, dma_q, buf);
361 rc=get_next_buf (dma_q, &buf);
362 if (rc<=0)
363 return rc;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300364
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300365 outp = videobuf_to_vmalloc (&buf->vb);
366 }
367
368 buf->top_field = 1;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300369 } else {
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300370 buf->top_field = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300371 }
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300372 buf->receiving = 1;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300373 dma_q->pos = 0;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300374 } else if (p[0]==0x33 && p[1]==0x95 && p[2]==0x00) {
375 em28xx_isocdbg("VBI HEADER!!!\n");
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300376 }
377
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300378 em28xx_copy_video(dev, dma_q, buf, p, outp, len);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300379
380 /* FIXME: Should add vbi copy */
381 }
382 return rc;
383}
384
385/* ------------------------------------------------------------------
386 URB control
387 ------------------------------------------------------------------*/
388
389/*
390 * IRQ callback, called by URB callback
391 */
392static void em28xx_irq_callback(struct urb *urb)
393{
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300394 struct em28xx_dmaqueue *dma_q = urb->context;
395 struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
396 int rc,i;
397 unsigned long flags;
398
399 spin_lock_irqsave(&dev->slock,flags);
400
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300401 /* Copy data from URB */
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300402 rc=em28xx_isoc_copy(urb);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300403
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300404 /* Reset urb buffers */
405 for (i = 0; i < urb->number_of_packets; i++) {
406 urb->iso_frame_desc[i].status = 0;
407 urb->iso_frame_desc[i].actual_length = 0;
408 }
409 urb->status = 0;
410
411 if ((urb->status = usb_submit_urb(urb, GFP_ATOMIC))) {
412 em28xx_err("urb resubmit failed (error=%i)\n",
413 urb->status);
414 }
415
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300416#if 0 /* Bad idea. There are problems that cause a load of valid, but
417 empty, data packets. Don't reset the timeout unless we've actually
418 got a frame. I've had xawtv hang in free_buffer due to this! */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300419 if (rc >= 0)
420 mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300421#endif
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300422 spin_unlock_irqrestore(&dev->slock,flags);
423}
424
425/*
426 * Stop and Deallocate URBs
427 */
428static void em28xx_uninit_isoc(struct em28xx *dev)
429{
430 struct urb *urb;
431 int i;
432
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300433 em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n");
434
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300435 dev->isoc_ctl.nfields=-1;
436 dev->isoc_ctl.buf=NULL;
437 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
438 urb=dev->isoc_ctl.urb[i];
439 if (urb) {
440 usb_kill_urb(urb);
441 usb_unlink_urb(urb);
442 if (dev->isoc_ctl.transfer_buffer[i]) {
443 usb_buffer_free(dev->udev,
444 urb->transfer_buffer_length,
445 dev->isoc_ctl.transfer_buffer[i],
446 urb->transfer_dma);
447 }
448 usb_free_urb(urb);
449 dev->isoc_ctl.urb[i] = NULL;
450 }
451 dev->isoc_ctl.transfer_buffer[i] = NULL;
452 }
453
454 kfree (dev->isoc_ctl.urb);
455 kfree (dev->isoc_ctl.transfer_buffer);
456 dev->isoc_ctl.urb=NULL;
457 dev->isoc_ctl.transfer_buffer=NULL;
458
459 dev->isoc_ctl.num_bufs=0;
460
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300461 // em28xx_capture_start(dev, 0); - FIXME - how could I restart it?
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300462}
463
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300464
465/*
466 * Allocate URBs and start IRQ
467 */
468static int em28xx_prepare_isoc(struct em28xx *dev, int max_packets,
469 int num_bufs)
470{
471 struct em28xx_dmaqueue *dma_q = &dev->vidq;
472 int i;
473 int sb_size, pipe;
474 struct urb *urb;
475 int j, k;
476
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300477 em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n");
478
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300479 /* De-allocates all pending stuff */
480 em28xx_uninit_isoc(dev);
481
482 dev->isoc_ctl.num_bufs = num_bufs;
483
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300484 dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300485 if (!dev->isoc_ctl.urb) {
486 em28xx_errdev("cannot alloc memory for usb buffers\n");
487 return -ENOMEM;
488 }
489
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300490 dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300491 GFP_KERNEL);
492 if (!dev->isoc_ctl.urb) {
493 em28xx_errdev("cannot allocate memory for usbtransfer\n");
494 kfree(dev->isoc_ctl.urb);
495 return -ENOMEM;
496 }
497
498 dev->isoc_ctl.max_pkt_size = dev->max_pkt_size;
499
500 sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
501
502 /* allocate urbs and transfer buffers */
503 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
504 urb = usb_alloc_urb(max_packets, GFP_KERNEL);
505 if (!urb) {
506 em28xx_err("cannot alloc isoc_ctl.urb %i\n", i);
507 em28xx_uninit_isoc(dev);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300508 return -ENOMEM;
509 }
510 dev->isoc_ctl.urb[i] = urb;
511
512 dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev,
513 sb_size, GFP_KERNEL, &urb->transfer_dma);
514 if (!dev->isoc_ctl.transfer_buffer[i]) {
515 em28xx_err ("unable to allocate %i bytes for transfer"
516 " buffer %i%s\n",
517 sb_size, i,
518 in_interrupt()?" while in int":"");
519 em28xx_uninit_isoc(dev);
520 return -ENOMEM;
521 }
522 memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
523
524 /* FIXME: this is a hack - should be
525 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK'
526 should also be using 'desc.bInterval'
527 */
528 pipe=usb_rcvisocpipe(dev->udev, 0x82);
529 usb_fill_int_urb(urb, dev->udev, pipe,
530 dev->isoc_ctl.transfer_buffer[i], sb_size,
531 em28xx_irq_callback, dma_q, 1);
532
533 urb->number_of_packets = max_packets;
534 urb->transfer_flags = URB_ISO_ASAP;
535
536 k = 0;
537 for (j = 0; j < max_packets; j++) {
538 urb->iso_frame_desc[j].offset = k;
539 urb->iso_frame_desc[j].length =
540 dev->isoc_ctl.max_pkt_size;
541 k += dev->isoc_ctl.max_pkt_size;
542 }
543 }
544
545 return 0;
546}
547
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300548static int em28xx_start_thread( struct em28xx_dmaqueue *dma_q)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300549{
550 struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300551 int i,rc = 0;
552
553 em28xx_videodbg("Called em28xx_start_thread\n");
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300554
555 init_waitqueue_head(&dma_q->wq);
556
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300557 /* submit urbs and enables IRQ */
558 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
559 rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
560 if (rc) {
561 em28xx_err("submit of urb %i failed (error=%i)\n", i,
562 rc);
563 em28xx_uninit_isoc(dev);
564 return rc;
565 }
566 }
567
568 if (rc<0)
569 return rc;
570
571 return 0;
572}
573
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300574
575static void em28xx_vid_timeout(unsigned long data)
576{
577 struct em28xx *dev = (struct em28xx*)data;
578 struct em28xx_dmaqueue *vidq = &dev->vidq;
579 struct em28xx_buffer *buf;
580 unsigned long flags;
581
582 spin_lock_irqsave(&dev->slock,flags);
583 while (!list_empty(&vidq->active)) {
584 buf = list_entry(vidq->active.next, struct em28xx_buffer,
585 vb.queue);
586 list_del(&buf->vb.queue);
587 buf->vb.state = VIDEOBUF_ERROR;
588 wake_up(&buf->vb.done);
589 em28xx_videodbg("em28xx/0: [%p/%d] timeout\n",
590 buf, buf->vb.i);
591 }
592
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300593 /* restart_video_queue(vidq); */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300594 spin_unlock_irqrestore(&dev->slock,flags);
595}
596
597/* ------------------------------------------------------------------
598 Videobuf operations
599 ------------------------------------------------------------------*/
600
601static int
602buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
603{
604 struct em28xx_fh *fh = vq->priv_data;
605
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300606 *size = 16 * fh->dev->width * fh->dev->height >> 3;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300607 if (0 == *count)
608 *count = EM28XX_DEF_BUF;
609
610 if (*count < EM28XX_MIN_BUF) {
611 *count=EM28XX_MIN_BUF;
612 }
613
614 return 0;
615}
616
617static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
618{
619 if (in_interrupt())
620 BUG();
621
622 videobuf_waiton(&buf->vb, 0, 0);
623 videobuf_vmalloc_free(&buf->vb);
624 buf->vb.state = VIDEOBUF_NEEDS_INIT;
625}
626
627static int
628buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
629 enum v4l2_field field)
630{
631 struct em28xx_fh *fh = vq->priv_data;
632 struct em28xx_buffer *buf = container_of(vb,struct em28xx_buffer,vb);
633 struct em28xx *dev = fh->dev;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300634 struct em28xx_dmaqueue *vidq = &dev->vidq;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300635 int rc = 0, urb_init = 0;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300636
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300637 /* BUG_ON(NULL == fh->fmt); */
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300638
639 /* FIXME: It assumes depth = 16 */
640 /* The only currently supported format is 16 bits/pixel */
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300641 buf->vb.size = 16 * dev->width * dev->height >> 3;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300642
643 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
644 return -EINVAL;
645
646 if (buf->fmt != fh->fmt ||
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300647 buf->vb.width != dev->width ||
648 buf->vb.height != dev->height ||
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300649 buf->vb.field != field) {
650 buf->fmt = fh->fmt;
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300651 buf->vb.width = dev->width;
652 buf->vb.height = dev->height;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300653 buf->vb.field = field;
654 buf->vb.state = VIDEOBUF_NEEDS_INIT;
655 }
656
657 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300658 rc = videobuf_iolock(vq, &buf->vb, NULL);
659 if (rc < 0)
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300660 goto fail;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300661 }
662
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300663 if (!dev->isoc_ctl.num_bufs)
664 urb_init=1;
665
666 if (urb_init) {
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300667 rc = em28xx_prepare_isoc(dev, EM28XX_NUM_PACKETS, EM28XX_NUM_BUFS);
668 if (rc<0)
669 goto fail;
670
671 /* FIXME - should probably be done in response to STREAMON */
672 rc = em28xx_start_thread(vidq);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300673 if (rc<0)
674 goto fail;
675 }
676
677 buf->vb.state = VIDEOBUF_PREPARED;
678 return 0;
679
680fail:
681 free_buffer(vq,buf);
682 return rc;
683}
684
685static void
686buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
687{
688 struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
689 struct em28xx_fh *fh = vq->priv_data;
690 struct em28xx *dev = fh->dev;
691 struct em28xx_dmaqueue *vidq = &dev->vidq;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300692
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300693 buf->vb.state = VIDEOBUF_QUEUED;
694 list_add_tail(&buf->vb.queue, &vidq->active);
695
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300696}
697
698static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb)
699{
700 struct em28xx_buffer *buf = container_of(vb,struct em28xx_buffer,vb);
701 struct em28xx_fh *fh = vq->priv_data;
702 struct em28xx *dev = (struct em28xx*)fh->dev;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300703
Aidan Thorntond7aa8022008-04-13 14:38:47 -0300704 em28xx_isocdbg("em28xx: called buffer_release\n");
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300705
706 free_buffer(vq,buf);
707}
708
709static struct videobuf_queue_ops em28xx_video_qops = {
710 .buf_setup = buffer_setup,
711 .buf_prepare = buffer_prepare,
712 .buf_queue = buffer_queue,
713 .buf_release = buffer_release,
714};
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800715
716/********************* v4l2 interface ******************************************/
717
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800718/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800719 * em28xx_config()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800720 * inits registers with sane defaults
721 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800722static int em28xx_config(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800723{
724
725 /* Sets I2C speed to 100 KHz */
Sascha Sommer2b2c93a2007-11-03 16:48:01 -0300726 if (!dev->is_em2800)
727 em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800728
729 /* enable vbi capturing */
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -0200730
Markus Rechberger9475fb12006-02-27 00:07:34 -0300731/* em28xx_write_regs_req(dev,0x00,0x0e,"\xC0",1); audio register */
732/* em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -0200733 em28xx_write_regs_req(dev,0x00,0x11,"\x51",1);
734
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800735 dev->mute = 1; /* maybe not the right place... */
736 dev->volume = 0x1f;
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -0300737
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800738 em28xx_outfmt_set_yuv422(dev);
739 em28xx_colorlevels_set_default(dev);
740 em28xx_compression_disable(dev);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800741
742 return 0;
743}
744
745/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -0800746 * em28xx_config_i2c()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800747 * configure i2c attached devices
748 */
Adrian Bunk943a4902005-12-01 00:51:35 -0800749static void em28xx_config_i2c(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800750{
Hans Verkuilc7c0b342006-04-02 13:35:00 -0300751 struct v4l2_routing route;
752
753 route.input = INPUT(dev->ctl_input)->vmux;
754 route.output = 0;
Al Viro663d1ba2006-10-10 22:48:37 +0100755 em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL);
Hans Verkuilc7c0b342006-04-02 13:35:00 -0300756 em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300757 em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800758}
759
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -0800760static void video_mux(struct em28xx *dev, int index)
761{
Hans Verkuilc7c0b342006-04-02 13:35:00 -0300762 struct v4l2_routing route;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -0800763
Hans Verkuilc7c0b342006-04-02 13:35:00 -0300764 route.input = INPUT(index)->vmux;
765 route.output = 0;
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -0800766 dev->ctl_input = index;
767 dev->ctl_ainput = INPUT(index)->amux;
768
Hans Verkuilc7c0b342006-04-02 13:35:00 -0300769 em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -0800770
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -0800771 if (dev->has_msp34xx) {
Mauro Carvalho Chehab9bb13a62006-01-09 15:25:37 -0200772 if (dev->i2s_speed)
773 em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
Hans Verkuil2474ed42006-03-19 12:35:57 -0300774 route.input = dev->ctl_ainput;
Hans Verkuil07151722006-04-01 18:03:23 -0300775 route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
Hans Verkuil2474ed42006-03-19 12:35:57 -0300776 /* Note: this is msp3400 specific */
777 em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -0800778 }
Mauro Carvalho Chehab539c96d2008-01-05 09:53:54 -0300779
Mauro Carvalho Chehab00b87302008-02-06 18:34:13 -0300780 em28xx_audio_analog_set(dev);
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -0800781}
782
Mauro Carvalho Chehaba2254522007-11-11 01:08:26 -0300783/* Usage lock check functions */
784static int res_get(struct em28xx_fh *fh)
785{
786 struct em28xx *dev = fh->dev;
787 int rc = 0;
788
789 /* This instance already has stream_on */
790 if (fh->stream_on)
791 return rc;
792
793 mutex_lock(&dev->lock);
794
795 if (dev->stream_on)
796 rc = -EINVAL;
797 else {
798 dev->stream_on = 1;
799 fh->stream_on = 1;
800 }
801
802 mutex_unlock(&dev->lock);
803 return rc;
804}
805
806static int res_check(struct em28xx_fh *fh)
807{
808 return (fh->stream_on);
809}
810
811static void res_free(struct em28xx_fh *fh)
812{
813 struct em28xx *dev = fh->dev;
814
815 mutex_lock(&dev->lock);
816 fh->stream_on = 0;
817 dev->stream_on = 0;
818 mutex_unlock(&dev->lock);
819}
820
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -0800821/*
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -0300822 * em28xx_get_ctrl()
823 * return the current saturation, brightness or contrast, mute state
824 */
825static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
826{
827 switch (ctrl->id) {
828 case V4L2_CID_AUDIO_MUTE:
829 ctrl->value = dev->mute;
830 return 0;
831 case V4L2_CID_AUDIO_VOLUME:
832 ctrl->value = dev->volume;
833 return 0;
834 default:
835 return -EINVAL;
836 }
837}
838
839/*
840 * em28xx_set_ctrl()
841 * mute or set new saturation, brightness or contrast
842 */
843static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
844{
845 switch (ctrl->id) {
846 case V4L2_CID_AUDIO_MUTE:
847 if (ctrl->value != dev->mute) {
848 dev->mute = ctrl->value;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -0300849 return em28xx_audio_analog_set(dev);
850 }
851 return 0;
852 case V4L2_CID_AUDIO_VOLUME:
853 dev->volume = ctrl->value;
854 return em28xx_audio_analog_set(dev);
855 default:
856 return -EINVAL;
857 }
858}
859
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -0300860static int check_dev(struct em28xx *dev)
861{
862 if (dev->state & DEV_DISCONNECTED) {
863 em28xx_errdev("v4l2 ioctl: device not present\n");
864 return -ENODEV;
865 }
866
867 if (dev->state & DEV_MISCONFIGURED) {
868 em28xx_errdev("v4l2 ioctl: device is misconfigured; "
869 "close and open it again\n");
870 return -EIO;
871 }
872 return 0;
873}
874
875static void get_scale(struct em28xx *dev,
876 unsigned int width, unsigned int height,
877 unsigned int *hscale, unsigned int *vscale)
878{
879 unsigned int maxw = norm_maxw(dev);
880 unsigned int maxh = norm_maxh(dev);
881
882 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
883 if (*hscale >= 0x4000)
884 *hscale = 0x3fff;
885
886 *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
887 if (*vscale >= 0x4000)
888 *vscale = 0x3fff;
889}
890
891/* ------------------------------------------------------------------
892 IOCTL vidioc handling
893 ------------------------------------------------------------------*/
894
895static int vidioc_g_fmt_cap(struct file *file, void *priv,
896 struct v4l2_format *f)
897{
898 struct em28xx_fh *fh = priv;
899 struct em28xx *dev = fh->dev;
900
901 mutex_lock(&dev->lock);
902
903 f->fmt.pix.width = dev->width;
904 f->fmt.pix.height = dev->height;
905 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
906 f->fmt.pix.bytesperline = dev->bytesperline;
907 f->fmt.pix.sizeimage = dev->frame_size;
908 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
909
910 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
911 f->fmt.pix.field = dev->interlaced ?
912 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
913
914 mutex_unlock(&dev->lock);
915 return 0;
916}
917
918static int vidioc_try_fmt_cap(struct file *file, void *priv,
919 struct v4l2_format *f)
920{
921 struct em28xx_fh *fh = priv;
922 struct em28xx *dev = fh->dev;
923 int width = f->fmt.pix.width;
924 int height = f->fmt.pix.height;
925 unsigned int maxw = norm_maxw(dev);
926 unsigned int maxh = norm_maxh(dev);
927 unsigned int hscale, vscale;
928
929 /* width must even because of the YUYV format
930 height must be even because of interlacing */
931 height &= 0xfffe;
932 width &= 0xfffe;
933
934 if (height < 32)
935 height = 32;
936 if (height > maxh)
937 height = maxh;
938 if (width < 48)
939 width = 48;
940 if (width > maxw)
941 width = maxw;
942
943 mutex_lock(&dev->lock);
944
945 if (dev->is_em2800) {
946 /* the em2800 can only scale down to 50% */
947 if (height % (maxh / 2))
948 height = maxh;
949 if (width % (maxw / 2))
950 width = maxw;
951 /* according to empiatech support */
952 /* the MaxPacketSize is to small to support */
953 /* framesizes larger than 640x480 @ 30 fps */
954 /* or 640x576 @ 25 fps. As this would cut */
955 /* of a part of the image we prefer */
956 /* 360x576 or 360x480 for now */
957 if (width == maxw && height == maxh)
958 width /= 2;
959 }
960
961 get_scale(dev, width, height, &hscale, &vscale);
962
963 width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
964 height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
965
966 f->fmt.pix.width = width;
967 f->fmt.pix.height = height;
968 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
969 f->fmt.pix.bytesperline = width * 2;
970 f->fmt.pix.sizeimage = width * 2 * height;
971 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
972 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
973
974 mutex_unlock(&dev->lock);
975 return 0;
976}
977
978static int vidioc_s_fmt_cap(struct file *file, void *priv,
979 struct v4l2_format *f)
980{
981 struct em28xx_fh *fh = priv;
982 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -0300983 int rc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -0300984
985 rc = check_dev(dev);
986 if (rc < 0)
987 return rc;
988
989 vidioc_try_fmt_cap(file, priv, f);
990
991 mutex_lock(&dev->lock);
992
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -0300993 /* set new image size */
994 dev->width = f->fmt.pix.width;
995 dev->height = f->fmt.pix.height;
996 dev->frame_size = dev->width * dev->height * 2;
997 dev->field_size = dev->frame_size >> 1;
998 dev->bytesperline = dev->width * 2;
999 get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
1000
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001001 em28xx_set_alternate(dev);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001002 em28xx_capture_start(dev, 1); /* ??? */
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001003 em28xx_resolution_set(dev);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001004
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001005 mutex_unlock(&dev->lock);
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001006 return 0;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001007}
1008
1009static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
1010{
1011 struct em28xx_fh *fh = priv;
1012 struct em28xx *dev = fh->dev;
1013 struct v4l2_format f;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001014 int rc;
1015
1016 rc = check_dev(dev);
1017 if (rc < 0)
1018 return rc;
1019
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001020 mutex_lock(&dev->lock);
Mauro Carvalho Chehab7d497f82007-11-11 14:15:34 -03001021 dev->norm = *norm;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001022 mutex_unlock(&dev->lock);
1023
1024 /* Adjusts width/height, if needed */
1025 f.fmt.pix.width = dev->width;
1026 f.fmt.pix.height = dev->height;
1027 vidioc_try_fmt_cap(file, priv, &f);
1028
1029 mutex_lock(&dev->lock);
1030
1031 /* set new image size */
1032 dev->width = f.fmt.pix.width;
1033 dev->height = f.fmt.pix.height;
1034 dev->frame_size = dev->width * dev->height * 2;
1035 dev->field_size = dev->frame_size >> 1;
1036 dev->bytesperline = dev->width * 2;
1037 get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
1038
1039 em28xx_resolution_set(dev);
Mauro Carvalho Chehab7d497f82007-11-11 14:15:34 -03001040 em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->norm);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001041
1042 mutex_unlock(&dev->lock);
1043 return 0;
1044}
1045
1046static const char *iname[] = {
1047 [EM28XX_VMUX_COMPOSITE1] = "Composite1",
1048 [EM28XX_VMUX_COMPOSITE2] = "Composite2",
1049 [EM28XX_VMUX_COMPOSITE3] = "Composite3",
1050 [EM28XX_VMUX_COMPOSITE4] = "Composite4",
1051 [EM28XX_VMUX_SVIDEO] = "S-Video",
1052 [EM28XX_VMUX_TELEVISION] = "Television",
1053 [EM28XX_VMUX_CABLE] = "Cable TV",
1054 [EM28XX_VMUX_DVB] = "DVB",
1055 [EM28XX_VMUX_DEBUG] = "for debug only",
1056};
1057
1058static int vidioc_enum_input(struct file *file, void *priv,
1059 struct v4l2_input *i)
1060{
1061 struct em28xx_fh *fh = priv;
1062 struct em28xx *dev = fh->dev;
1063 unsigned int n;
1064
1065 n = i->index;
1066 if (n >= MAX_EM28XX_INPUT)
1067 return -EINVAL;
1068 if (0 == INPUT(n)->type)
1069 return -EINVAL;
1070
1071 i->index = n;
1072 i->type = V4L2_INPUT_TYPE_CAMERA;
1073
1074 strcpy(i->name, iname[INPUT(n)->type]);
1075
1076 if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
1077 (EM28XX_VMUX_CABLE == INPUT(n)->type))
1078 i->type = V4L2_INPUT_TYPE_TUNER;
1079
Mauro Carvalho Chehab7d497f82007-11-11 14:15:34 -03001080 i->std = dev->vdev->tvnorms;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001081
1082 return 0;
1083}
1084
1085static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1086{
1087 struct em28xx_fh *fh = priv;
1088 struct em28xx *dev = fh->dev;
1089
1090 *i = dev->ctl_input;
1091
1092 return 0;
1093}
1094
1095static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1096{
1097 struct em28xx_fh *fh = priv;
1098 struct em28xx *dev = fh->dev;
1099 int rc;
1100
1101 rc = check_dev(dev);
1102 if (rc < 0)
1103 return rc;
1104
1105 if (i >= MAX_EM28XX_INPUT)
1106 return -EINVAL;
1107 if (0 == INPUT(i)->type)
1108 return -EINVAL;
1109
1110 mutex_lock(&dev->lock);
1111
1112 video_mux(dev, i);
1113
1114 mutex_unlock(&dev->lock);
1115 return 0;
1116}
1117
1118static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1119{
1120 struct em28xx_fh *fh = priv;
1121 struct em28xx *dev = fh->dev;
1122 unsigned int index = a->index;
1123
1124 if (a->index > 1)
1125 return -EINVAL;
1126
1127 index = dev->ctl_ainput;
1128
1129 if (index == 0) {
1130 strcpy(a->name, "Television");
1131 } else {
1132 strcpy(a->name, "Line In");
1133 }
1134 a->capability = V4L2_AUDCAP_STEREO;
1135 a->index = index;
1136
1137 return 0;
1138}
1139
1140static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
1141{
1142 struct em28xx_fh *fh = priv;
1143 struct em28xx *dev = fh->dev;
1144
1145 if (a->index != dev->ctl_ainput)
1146 return -EINVAL;
1147
1148 return 0;
1149}
1150
1151static int vidioc_queryctrl(struct file *file, void *priv,
1152 struct v4l2_queryctrl *qc)
1153{
1154 struct em28xx_fh *fh = priv;
1155 struct em28xx *dev = fh->dev;
1156 int id = qc->id;
1157 int i;
1158 int rc;
1159
1160 rc = check_dev(dev);
1161 if (rc < 0)
1162 return rc;
1163
1164 memset(qc, 0, sizeof(*qc));
1165
1166 qc->id = id;
1167
1168 if (!dev->has_msp34xx) {
1169 for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
1170 if (qc->id && qc->id == em28xx_qctrl[i].id) {
1171 memcpy(qc, &(em28xx_qctrl[i]), sizeof(*qc));
1172 return 0;
1173 }
1174 }
1175 }
1176 mutex_lock(&dev->lock);
1177 em28xx_i2c_call_clients(dev, VIDIOC_QUERYCTRL, qc);
1178 mutex_unlock(&dev->lock);
1179
1180 if (qc->type)
1181 return 0;
1182 else
1183 return -EINVAL;
1184}
1185
1186static int vidioc_g_ctrl(struct file *file, void *priv,
1187 struct v4l2_control *ctrl)
1188{
1189 struct em28xx_fh *fh = priv;
1190 struct em28xx *dev = fh->dev;
1191 int rc;
1192
1193 rc = check_dev(dev);
1194 if (rc < 0)
1195 return rc;
1196 mutex_lock(&dev->lock);
1197
1198 if (!dev->has_msp34xx)
1199 rc = em28xx_get_ctrl(dev, ctrl);
1200 else
1201 rc = -EINVAL;
1202
1203 if (rc == -EINVAL) {
1204 em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl);
1205 rc = 0;
1206 }
1207
1208 mutex_unlock(&dev->lock);
1209 return rc;
1210}
1211
1212static int vidioc_s_ctrl(struct file *file, void *priv,
1213 struct v4l2_control *ctrl)
1214{
1215 struct em28xx_fh *fh = priv;
1216 struct em28xx *dev = fh->dev;
1217 u8 i;
1218 int rc;
1219
1220 rc = check_dev(dev);
1221 if (rc < 0)
1222 return rc;
1223
1224 mutex_lock(&dev->lock);
1225
1226 if (dev->has_msp34xx)
1227 em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl);
1228 else {
1229 rc = 1;
1230 for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
1231 if (ctrl->id == em28xx_qctrl[i].id) {
1232 if (ctrl->value < em28xx_qctrl[i].minimum ||
1233 ctrl->value > em28xx_qctrl[i].maximum) {
1234 rc = -ERANGE;
1235 break;
1236 }
1237
1238 rc = em28xx_set_ctrl(dev, ctrl);
1239 break;
1240 }
1241 }
1242 }
1243
1244 /* Control not found - try to send it to the attached devices */
1245 if (rc == 1) {
1246 em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl);
1247 rc = 0;
1248 }
1249
1250 mutex_unlock(&dev->lock);
1251 return rc;
1252}
1253
1254static int vidioc_g_tuner(struct file *file, void *priv,
1255 struct v4l2_tuner *t)
1256{
1257 struct em28xx_fh *fh = priv;
1258 struct em28xx *dev = fh->dev;
1259 int rc;
1260
1261 rc = check_dev(dev);
1262 if (rc < 0)
1263 return rc;
1264
1265 if (0 != t->index)
1266 return -EINVAL;
1267
1268 strcpy(t->name, "Tuner");
1269
1270 mutex_lock(&dev->lock);
1271
1272 em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
1273
1274 mutex_unlock(&dev->lock);
1275 return 0;
1276}
1277
1278static int vidioc_s_tuner(struct file *file, void *priv,
1279 struct v4l2_tuner *t)
1280{
1281 struct em28xx_fh *fh = priv;
1282 struct em28xx *dev = fh->dev;
1283 int rc;
1284
1285 rc = check_dev(dev);
1286 if (rc < 0)
1287 return rc;
1288
1289 if (0 != t->index)
1290 return -EINVAL;
1291
1292 mutex_lock(&dev->lock);
1293
1294 em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t);
1295
1296 mutex_unlock(&dev->lock);
1297 return 0;
1298}
1299
1300static int vidioc_g_frequency(struct file *file, void *priv,
1301 struct v4l2_frequency *f)
1302{
1303 struct em28xx_fh *fh = priv;
1304 struct em28xx *dev = fh->dev;
1305
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001306 f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001307 f->frequency = dev->ctl_freq;
1308
1309 return 0;
1310}
1311
1312static int vidioc_s_frequency(struct file *file, void *priv,
1313 struct v4l2_frequency *f)
1314{
1315 struct em28xx_fh *fh = priv;
1316 struct em28xx *dev = fh->dev;
1317 int rc;
1318
1319 rc = check_dev(dev);
1320 if (rc < 0)
1321 return rc;
1322
1323 if (0 != f->tuner)
1324 return -EINVAL;
1325
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001326 if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
1327 return -EINVAL;
1328 if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001329 return -EINVAL;
1330
1331 mutex_lock(&dev->lock);
1332
1333 dev->ctl_freq = f->frequency;
1334 em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f);
1335
1336 mutex_unlock(&dev->lock);
1337 return 0;
1338}
1339
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001340#ifdef CONFIG_VIDEO_ADV_DEBUG
1341static int em28xx_reg_len(int reg)
1342{
1343 switch (reg) {
1344 case AC97LSB_REG:
1345 case HSCALELOW_REG:
1346 case VSCALELOW_REG:
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001347 return 2;
1348 default:
1349 return 1;
1350 }
1351}
1352
1353static int vidioc_g_register(struct file *file, void *priv,
1354 struct v4l2_register *reg)
1355{
1356 struct em28xx_fh *fh = priv;
1357 struct em28xx *dev = fh->dev;
1358 int ret;
1359
1360 if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
1361 return -EINVAL;
1362
1363 if (em28xx_reg_len(reg->reg) == 1) {
1364 ret = em28xx_read_reg(dev, reg->reg);
1365 if (ret < 0)
1366 return ret;
1367
1368 reg->val = ret;
1369 } else {
Mauro Carvalho Chehab0df81302008-02-06 15:56:16 -03001370 u64 val = 0;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001371 ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
1372 reg->reg, (char *)&val, 2);
1373 if (ret < 0)
1374 return ret;
1375
Mauro Carvalho Chehab0df81302008-02-06 15:56:16 -03001376 reg->val = cpu_to_le64((__u64)val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001377 }
1378
1379 return 0;
1380}
1381
1382static int vidioc_s_register(struct file *file, void *priv,
1383 struct v4l2_register *reg)
1384{
1385 struct em28xx_fh *fh = priv;
1386 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab0df81302008-02-06 15:56:16 -03001387 u64 buf;
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001388
Mauro Carvalho Chehab0df81302008-02-06 15:56:16 -03001389 buf = le64_to_cpu((__u64)reg->val);
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03001390
1391 return em28xx_write_regs(dev, reg->reg, (char *)&buf,
1392 em28xx_reg_len(reg->reg));
1393}
1394#endif
1395
1396
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001397static int vidioc_cropcap(struct file *file, void *priv,
1398 struct v4l2_cropcap *cc)
1399{
1400 struct em28xx_fh *fh = priv;
1401 struct em28xx *dev = fh->dev;
1402
1403 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1404 return -EINVAL;
1405
1406 cc->bounds.left = 0;
1407 cc->bounds.top = 0;
1408 cc->bounds.width = dev->width;
1409 cc->bounds.height = dev->height;
1410 cc->defrect = cc->bounds;
1411 cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */
1412 cc->pixelaspect.denominator = 59;
1413
1414 return 0;
1415}
1416
1417static int vidioc_streamon(struct file *file, void *priv,
1418 enum v4l2_buf_type type)
1419{
1420 struct em28xx_fh *fh = priv;
1421 struct em28xx *dev = fh->dev;
1422 int rc;
1423
1424 rc = check_dev(dev);
1425 if (rc < 0)
1426 return rc;
1427
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001428
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001429 if (unlikely(res_get(fh) < 0))
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001430 return -EBUSY;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001431
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001432 /* We can't do this from buffer_queue or anything called from
1433 there, since it's called with IRQs disabled and the spinlock held,
1434 and this uses USB functions that may sleep
1435
1436 FIXME FIXME FIXME - putting this here means it may not always
1437 be called when it needs to be */
1438 em28xx_capture_start(dev, 1);
1439
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001440 return (videobuf_streamon(&fh->vb_vidq));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001441}
1442
1443static int vidioc_streamoff(struct file *file, void *priv,
1444 enum v4l2_buf_type type)
1445{
1446 struct em28xx_fh *fh = priv;
1447 struct em28xx *dev = fh->dev;
1448 int rc;
1449
1450 rc = check_dev(dev);
1451 if (rc < 0)
1452 return rc;
1453
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001454 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1455 return -EINVAL;
1456 if (type != fh->type)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001457 return -EINVAL;
1458
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001459 videobuf_streamoff(&fh->vb_vidq);
1460 res_free(fh);
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001461
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001462 return 0;
1463}
1464
1465static int vidioc_querycap(struct file *file, void *priv,
1466 struct v4l2_capability *cap)
1467{
1468 struct em28xx_fh *fh = priv;
1469 struct em28xx *dev = fh->dev;
1470
1471 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1472 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
1473 strlcpy(cap->bus_info, dev->udev->dev.bus_id, sizeof(cap->bus_info));
1474
1475 cap->version = EM28XX_VERSION_CODE;
1476
1477 cap->capabilities =
1478 V4L2_CAP_SLICED_VBI_CAPTURE |
1479 V4L2_CAP_VIDEO_CAPTURE |
1480 V4L2_CAP_AUDIO |
1481 V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
1482
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03001483 if (dev->tuner_type != TUNER_ABSENT)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001484 cap->capabilities |= V4L2_CAP_TUNER;
1485
1486 return 0;
1487}
1488
1489static int vidioc_enum_fmt_cap(struct file *file, void *priv,
1490 struct v4l2_fmtdesc *fmtd)
1491{
1492 if (fmtd->index != 0)
1493 return -EINVAL;
1494
1495 fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1496 strcpy(fmtd->description, "Packed YUY2");
1497 fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
1498 memset(fmtd->reserved, 0, sizeof(fmtd->reserved));
1499
1500 return 0;
1501}
1502
1503/* Sliced VBI ioctls */
1504static int vidioc_g_fmt_vbi_capture(struct file *file, void *priv,
1505 struct v4l2_format *f)
1506{
1507 struct em28xx_fh *fh = priv;
1508 struct em28xx *dev = fh->dev;
1509 int rc;
1510
1511 rc = check_dev(dev);
1512 if (rc < 0)
1513 return rc;
1514
1515 mutex_lock(&dev->lock);
1516
1517 f->fmt.sliced.service_set = 0;
1518
1519 em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f);
1520
1521 if (f->fmt.sliced.service_set == 0)
1522 rc = -EINVAL;
1523
1524 mutex_unlock(&dev->lock);
1525 return rc;
1526}
1527
1528static int vidioc_try_set_vbi_capture(struct file *file, void *priv,
1529 struct v4l2_format *f)
1530{
1531 struct em28xx_fh *fh = priv;
1532 struct em28xx *dev = fh->dev;
1533 int rc;
1534
1535 rc = check_dev(dev);
1536 if (rc < 0)
1537 return rc;
1538
1539 mutex_lock(&dev->lock);
1540 em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f);
1541 mutex_unlock(&dev->lock);
1542
1543 if (f->fmt.sliced.service_set == 0)
1544 return -EINVAL;
1545
1546 return 0;
1547}
1548
1549
1550static int vidioc_reqbufs(struct file *file, void *priv,
1551 struct v4l2_requestbuffers *rb)
1552{
1553 struct em28xx_fh *fh = priv;
1554 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001555 int rc;
1556
1557 rc = check_dev(dev);
1558 if (rc < 0)
1559 return rc;
1560
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001561 return (videobuf_reqbufs(&fh->vb_vidq, rb));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001562}
1563
1564static int vidioc_querybuf(struct file *file, void *priv,
1565 struct v4l2_buffer *b)
1566{
1567 struct em28xx_fh *fh = priv;
1568 struct em28xx *dev = fh->dev;
1569 int rc;
1570
1571 rc = check_dev(dev);
1572 if (rc < 0)
1573 return rc;
1574
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001575 return (videobuf_querybuf(&fh->vb_vidq, b));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001576}
1577
1578static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1579{
1580 struct em28xx_fh *fh = priv;
1581 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001582 int rc;
1583
1584 rc = check_dev(dev);
1585 if (rc < 0)
1586 return rc;
1587
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001588 return (videobuf_qbuf(&fh->vb_vidq, b));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001589}
1590
1591static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1592{
1593 struct em28xx_fh *fh = priv;
1594 struct em28xx *dev = fh->dev;
1595 int rc;
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001596
1597 rc = check_dev(dev);
1598 if (rc < 0)
1599 return rc;
1600
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001601 return (videobuf_dqbuf(&fh->vb_vidq, b,
1602 file->f_flags & O_NONBLOCK));
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001603}
1604
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001605#ifdef CONFIG_VIDEO_V4L1_COMPAT
1606static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
1607{
1608 struct em28xx_fh *fh=priv;
1609
1610 return videobuf_cgmbuf (&fh->vb_vidq, mbuf, 8);
1611}
1612#endif
1613
1614
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001615/* ----------------------------------------------------------- */
1616/* RADIO ESPECIFIC IOCTLS */
1617/* ----------------------------------------------------------- */
1618
1619static int radio_querycap(struct file *file, void *priv,
1620 struct v4l2_capability *cap)
1621{
1622 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1623
1624 strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
1625 strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
1626 strlcpy(cap->bus_info, dev->udev->dev.bus_id, sizeof(cap->bus_info));
1627
1628 cap->version = EM28XX_VERSION_CODE;
1629 cap->capabilities = V4L2_CAP_TUNER;
1630 return 0;
1631}
1632
1633static int radio_g_tuner(struct file *file, void *priv,
1634 struct v4l2_tuner *t)
1635{
1636 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1637
1638 if (unlikely(t->index > 0))
1639 return -EINVAL;
1640
1641 strcpy(t->name, "Radio");
1642 t->type = V4L2_TUNER_RADIO;
1643
1644 em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
1645 return 0;
1646}
1647
1648static int radio_enum_input(struct file *file, void *priv,
1649 struct v4l2_input *i)
1650{
1651 if (i->index != 0)
1652 return -EINVAL;
1653 strcpy(i->name, "Radio");
1654 i->type = V4L2_INPUT_TYPE_TUNER;
1655
1656 return 0;
1657}
1658
1659static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1660{
1661 if (unlikely(a->index))
1662 return -EINVAL;
1663
1664 strcpy(a->name, "Radio");
1665 return 0;
1666}
1667
1668static int radio_s_tuner(struct file *file, void *priv,
1669 struct v4l2_tuner *t)
1670{
1671 struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
1672
1673 if (0 != t->index)
1674 return -EINVAL;
1675
1676 em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t);
1677
1678 return 0;
1679}
1680
1681static int radio_s_audio(struct file *file, void *fh,
1682 struct v4l2_audio *a)
1683{
1684 return 0;
1685}
1686
1687static int radio_s_input(struct file *file, void *fh, unsigned int i)
1688{
1689 return 0;
1690}
1691
1692static int radio_queryctrl(struct file *file, void *priv,
1693 struct v4l2_queryctrl *qc)
1694{
1695 int i;
1696
1697 if (qc->id < V4L2_CID_BASE ||
1698 qc->id >= V4L2_CID_LASTP1)
1699 return -EINVAL;
1700
1701 for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
1702 if (qc->id && qc->id == em28xx_qctrl[i].id) {
1703 memcpy(qc, &(em28xx_qctrl[i]), sizeof(*qc));
1704 return 0;
1705 }
1706 }
1707
1708 return -EINVAL;
1709}
1710
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001711/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001712 * em28xx_v4l2_open()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001713 * inits the device and starts isoc transfer
1714 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001715static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001716{
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001717 int minor = iminor(inode);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001718 int errCode = 0, radio = 0;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001719 struct em28xx *h,*dev = NULL;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001720 struct em28xx_fh *fh;
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001721 enum v4l2_buf_type fh_type = 0;
Markus Rechberger9c755412005-11-08 21:37:52 -08001722
Trent Piephoa991f442007-10-10 05:37:43 -03001723 list_for_each_entry(h, &em28xx_devlist, devlist) {
Markus Rechberger9c755412005-11-08 21:37:52 -08001724 if (h->vdev->minor == minor) {
1725 dev = h;
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001726 fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001727 }
1728 if (h->vbi_dev->minor == minor) {
1729 dev = h;
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001730 fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
Markus Rechberger9c755412005-11-08 21:37:52 -08001731 }
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001732 if (h->radio_dev &&
1733 h->radio_dev->minor == minor) {
1734 radio = 1;
1735 dev = h;
1736 }
Markus Rechberger9c755412005-11-08 21:37:52 -08001737 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001738 if (NULL == dev)
1739 return -ENODEV;
Markus Rechberger9c755412005-11-08 21:37:52 -08001740
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001741 em28xx_videodbg("open minor=%d type=%s users=%d\n",
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001742 minor, v4l2_type_names[fh_type], dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001743
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001744 fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001745
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001746 if (!fh) {
1747 em28xx_errdev("em28xx-video.c: Out of memory?!\n");
1748 return -ENOMEM;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001749 }
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001750 mutex_lock(&dev->lock);
1751 fh->dev = dev;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001752 fh->radio = radio;
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001753 fh->type = fh_type;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001754 filp->private_data = fh;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001755
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001756 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001757 dev->width = norm_maxw(dev);
1758 dev->height = norm_maxh(dev);
1759 dev->frame_size = dev->width * dev->height * 2;
1760 dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */
1761 dev->bytesperline = dev->width * 2;
1762 dev->hscale = 0;
1763 dev->vscale = 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001764
Mauro Carvalho Chehab3687e1e2008-02-08 15:44:25 -03001765 em28xx_set_alternate(dev);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001766 em28xx_resolution_set(dev);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001767
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001768 }
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001769 if (fh->radio) {
1770 em28xx_videodbg("video_open: setting radio device\n");
1771 em28xx_i2c_call_clients(dev, AUDC_SET_RADIO, NULL);
1772 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001773
1774 dev->users++;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001775
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001776 videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
1777 NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
1778 sizeof(struct em28xx_buffer), fh);
1779
Ingo Molnar3593cab2006-02-07 06:49:14 -02001780 mutex_unlock(&dev->lock);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001781 return errCode;
1782}
1783
1784/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001785 * em28xx_realease_resources()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001786 * unregisters the v4l2,i2c and usb devices
1787 * called when the device gets disconected or at module unload
1788*/
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001789static void em28xx_release_resources(struct em28xx *dev)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001790{
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001791
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001792 /*FIXME: I2C IR should be disconnected */
1793
1794 em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n",
1795 dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
1796 dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
Markus Rechberger9c755412005-11-08 21:37:52 -08001797 list_del(&dev->devlist);
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001798 if (dev->radio_dev) {
1799 if (-1 != dev->radio_dev->minor)
1800 video_unregister_device(dev->radio_dev);
1801 else
1802 video_device_release(dev->radio_dev);
1803 dev->radio_dev = NULL;
1804 }
1805 if (dev->vbi_dev) {
1806 if (-1 != dev->vbi_dev->minor)
1807 video_unregister_device(dev->vbi_dev);
1808 else
1809 video_device_release(dev->vbi_dev);
1810 dev->vbi_dev = NULL;
1811 }
1812 if (dev->vdev) {
1813 if (-1 != dev->vdev->minor)
1814 video_unregister_device(dev->vdev);
1815 else
1816 video_device_release(dev->vdev);
1817 dev->vdev = NULL;
1818 }
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001819 em28xx_i2c_unregister(dev);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001820 usb_put_dev(dev->udev);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001821
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001822 /* Mark device as unused */
1823 em28xx_devused&=~(1<<dev->devno);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001824}
1825
1826/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001827 * em28xx_v4l2_close()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001828 * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls
1829 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001830static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001831{
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001832 struct em28xx_fh *fh = filp->private_data;
1833 struct em28xx *dev = fh->dev;
1834 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001835
Mauro Carvalho Chehabeac94352005-11-08 21:38:43 -08001836 em28xx_videodbg("users=%d\n", dev->users);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001837
Mauro Carvalho Chehaba2254522007-11-11 01:08:26 -03001838
1839 if (res_check(fh))
1840 res_free(fh);
1841
Ingo Molnar3593cab2006-02-07 06:49:14 -02001842 mutex_lock(&dev->lock);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001843
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001844 if (dev->users == 1) {
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001845 videobuf_stop(&fh->vb_vidq);
1846 videobuf_mmap_free(&fh->vb_vidq);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001847
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001848 /* the device is already disconnect,
1849 free the remaining resources */
1850 if (dev->state & DEV_DISCONNECTED) {
1851 em28xx_release_resources(dev);
1852 mutex_unlock(&dev->lock);
1853 kfree(dev);
1854 return 0;
1855 }
1856
Aidan Thorntond7aa8022008-04-13 14:38:47 -03001857 /* do this before setting alternate! */
1858 em28xx_uninit_isoc(dev);
1859
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001860 /* set alternate 0 */
1861 dev->alt = 0;
1862 em28xx_videodbg("setting alternate 0\n");
1863 errCode = usb_set_interface(dev->udev, 0, 0);
1864 if (errCode < 0) {
1865 em28xx_errdev("cannot change alternate number to "
1866 "0 (error=%i)\n", errCode);
1867 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001868 }
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001869 kfree(fh);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001870 dev->users--;
1871 wake_up_interruptible_nr(&dev->open, 1);
Ingo Molnar3593cab2006-02-07 06:49:14 -02001872 mutex_unlock(&dev->lock);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001873 return 0;
1874}
1875
1876/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001877 * em28xx_v4l2_read()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001878 * will allocate buffers when called for the first time
1879 */
1880static ssize_t
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001881em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001882 loff_t * pos)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001883{
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001884 struct em28xx_fh *fh = filp->private_data;
1885 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001886 int rc;
1887
1888 rc = check_dev(dev);
1889 if (rc < 0)
1890 return rc;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001891
Mauro Carvalho Chehab9e31ced2007-11-11 01:13:49 -03001892 /* FIXME: read() is not prepared to allow changing the video
1893 resolution while streaming. Seems a bug at em28xx_set_fmt
1894 */
Mauro Carvalho Chehaba2254522007-11-11 01:08:26 -03001895
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001896 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1897 if (unlikely(res_get(fh)))
1898 return -EBUSY;
Mauro Carvalho Chehaba2254522007-11-11 01:08:26 -03001899
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001900 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
1901 filp->f_flags & O_NONBLOCK);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02001902 }
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001903 return 0;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001904}
1905
1906/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001907 * em28xx_v4l2_poll()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001908 * will allocate buffers when called for the first time
1909 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001910static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001911{
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001912 struct em28xx_fh *fh = filp->private_data;
1913 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001914 int rc;
1915
1916 rc = check_dev(dev);
1917 if (rc < 0)
1918 return rc;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001919
Mauro Carvalho Chehaba2254522007-11-11 01:08:26 -03001920 if (unlikely(res_get(fh) < 0))
1921 return POLLERR;
1922
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001923 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
1924 return POLLERR;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001925
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001926 return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001927}
1928
1929/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001930 * em28xx_v4l2_mmap()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001931 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08001932static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001933{
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001934 struct em28xx_fh *fh = filp->private_data;
1935 struct em28xx *dev = fh->dev;
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001936 int rc;
Markus Rechberger9c755412005-11-08 21:37:52 -08001937
Mauro Carvalho Chehaba2254522007-11-11 01:08:26 -03001938 if (unlikely(res_get(fh) < 0))
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001939 return -EBUSY;
Mauro Carvalho Chehaba2254522007-11-11 01:08:26 -03001940
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001941 rc = check_dev(dev);
1942 if (rc < 0)
1943 return rc;
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03001944
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001945 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001946
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001947 em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
1948 (unsigned long)vma->vm_start,
1949 (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
1950 rc);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001951
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03001952 return rc;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001953}
1954
Arjan van de Venfa027c22007-02-12 00:55:33 -08001955static const struct file_operations em28xx_v4l_fops = {
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001956 .owner = THIS_MODULE,
1957 .open = em28xx_v4l2_open,
1958 .release = em28xx_v4l2_close,
1959 .read = em28xx_v4l2_read,
1960 .poll = em28xx_v4l2_poll,
1961 .mmap = em28xx_v4l2_mmap,
1962 .ioctl = video_ioctl2,
1963 .llseek = no_llseek,
1964 .compat_ioctl = v4l_compat_ioctl32,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08001965};
1966
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03001967static const struct file_operations radio_fops = {
1968 .owner = THIS_MODULE,
1969 .open = em28xx_v4l2_open,
1970 .release = em28xx_v4l2_close,
1971 .ioctl = video_ioctl2,
1972 .compat_ioctl = v4l_compat_ioctl32,
1973 .llseek = no_llseek,
1974};
1975
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03001976static const struct video_device em28xx_video_template = {
1977 .fops = &em28xx_v4l_fops,
1978 .release = video_device_release,
1979
1980 .minor = -1,
1981 .vidioc_querycap = vidioc_querycap,
1982 .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap,
1983 .vidioc_g_fmt_cap = vidioc_g_fmt_cap,
1984 .vidioc_try_fmt_cap = vidioc_try_fmt_cap,
1985 .vidioc_s_fmt_cap = vidioc_s_fmt_cap,
1986 .vidioc_g_audio = vidioc_g_audio,
1987 .vidioc_s_audio = vidioc_s_audio,
1988 .vidioc_cropcap = vidioc_cropcap,
1989
1990 .vidioc_g_fmt_vbi_capture = vidioc_g_fmt_vbi_capture,
1991 .vidioc_try_fmt_vbi_capture = vidioc_try_set_vbi_capture,
1992 .vidioc_s_fmt_vbi_capture = vidioc_try_set_vbi_capture,
1993
1994 .vidioc_reqbufs = vidioc_reqbufs,
1995 .vidioc_querybuf = vidioc_querybuf,
1996 .vidioc_qbuf = vidioc_qbuf,
1997 .vidioc_dqbuf = vidioc_dqbuf,
1998 .vidioc_s_std = vidioc_s_std,
1999 .vidioc_enum_input = vidioc_enum_input,
2000 .vidioc_g_input = vidioc_g_input,
2001 .vidioc_s_input = vidioc_s_input,
2002 .vidioc_queryctrl = vidioc_queryctrl,
2003 .vidioc_g_ctrl = vidioc_g_ctrl,
2004 .vidioc_s_ctrl = vidioc_s_ctrl,
2005 .vidioc_streamon = vidioc_streamon,
2006 .vidioc_streamoff = vidioc_streamoff,
2007 .vidioc_g_tuner = vidioc_g_tuner,
2008 .vidioc_s_tuner = vidioc_s_tuner,
2009 .vidioc_g_frequency = vidioc_g_frequency,
2010 .vidioc_s_frequency = vidioc_s_frequency,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002011#ifdef CONFIG_VIDEO_ADV_DEBUG
2012 .vidioc_g_register = vidioc_g_register,
2013 .vidioc_s_register = vidioc_s_register,
2014#endif
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03002015#ifdef CONFIG_VIDEO_V4L1_COMPAT
2016 .vidiocgmbuf = vidiocgmbuf,
2017#endif
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002018
2019 .tvnorms = V4L2_STD_ALL,
Mauro Carvalho Chehab7d497f82007-11-11 14:15:34 -03002020 .current_norm = V4L2_STD_PAL,
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002021};
2022
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002023static struct video_device em28xx_radio_template = {
2024 .name = "em28xx-radio",
2025 .type = VID_TYPE_TUNER,
2026 .fops = &radio_fops,
2027 .minor = -1,
2028 .vidioc_querycap = radio_querycap,
2029 .vidioc_g_tuner = radio_g_tuner,
2030 .vidioc_enum_input = radio_enum_input,
2031 .vidioc_g_audio = radio_g_audio,
2032 .vidioc_s_tuner = radio_s_tuner,
2033 .vidioc_s_audio = radio_s_audio,
2034 .vidioc_s_input = radio_s_input,
2035 .vidioc_queryctrl = radio_queryctrl,
2036 .vidioc_g_ctrl = vidioc_g_ctrl,
2037 .vidioc_s_ctrl = vidioc_s_ctrl,
2038 .vidioc_g_frequency = vidioc_g_frequency,
2039 .vidioc_s_frequency = vidioc_s_frequency,
Mauro Carvalho Chehab1e7ad562008-02-06 09:00:41 -03002040#ifdef CONFIG_VIDEO_ADV_DEBUG
2041 .vidioc_g_register = vidioc_g_register,
2042 .vidioc_s_register = vidioc_s_register,
2043#endif
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002044};
2045
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002046/******************************** usb interface *****************************************/
2047
Mauro Carvalho Chehab6d794682008-01-05 09:57:31 -03002048
2049static LIST_HEAD(em28xx_extension_devlist);
2050static DEFINE_MUTEX(em28xx_extension_devlist_lock);
2051
2052int em28xx_register_extension(struct em28xx_ops *ops)
2053{
2054 struct em28xx *h, *dev = NULL;
2055
2056 list_for_each_entry(h, &em28xx_devlist, devlist)
2057 dev = h;
2058
2059 mutex_lock(&em28xx_extension_devlist_lock);
2060 list_add_tail(&ops->next, &em28xx_extension_devlist);
2061 if (dev)
2062 ops->init(dev);
2063
2064 printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
2065 mutex_unlock(&em28xx_extension_devlist_lock);
2066
2067 return 0;
2068}
2069EXPORT_SYMBOL(em28xx_register_extension);
2070
2071void em28xx_unregister_extension(struct em28xx_ops *ops)
2072{
2073 struct em28xx *h, *dev = NULL;
2074
2075 list_for_each_entry(h, &em28xx_devlist, devlist)
2076 dev = h;
2077
2078 if (dev)
2079 ops->fini(dev);
2080
2081 mutex_lock(&em28xx_extension_devlist_lock);
2082 printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
2083 list_del(&ops->next);
2084 mutex_unlock(&em28xx_extension_devlist_lock);
2085}
2086EXPORT_SYMBOL(em28xx_unregister_extension);
2087
Adrian Bunk532fe652008-01-28 22:10:48 -03002088static struct video_device *em28xx_vdev_init(struct em28xx *dev,
2089 const struct video_device *template,
2090 const int type,
2091 const char *type_name)
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002092{
2093 struct video_device *vfd;
2094
2095 vfd = video_device_alloc();
2096 if (NULL == vfd)
2097 return NULL;
2098 *vfd = *template;
2099 vfd->minor = -1;
2100 vfd->dev = &dev->udev->dev;
2101 vfd->release = video_device_release;
2102 vfd->type = type;
2103
2104 snprintf(vfd->name, sizeof(vfd->name), "%s %s",
2105 dev->name, type_name);
2106
2107 return vfd;
2108}
2109
2110
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002111/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002112 * em28xx_init_dev()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002113 * allocates and inits the device structs, registers i2c bus and v4l device
2114 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002115static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -03002116 int minor)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002117{
Mauro Carvalho Chehab6d794682008-01-05 09:57:31 -03002118 struct em28xx_ops *ops = NULL;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002119 struct em28xx *dev = *devhandle;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002120 int retval = -ENOMEM;
Mauro Carvalho Chehab7d497f82007-11-11 14:15:34 -03002121 int errCode;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002122 unsigned int maxh, maxw;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002123
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002124 dev->udev = udev;
Ingo Molnar3593cab2006-02-07 06:49:14 -02002125 mutex_init(&dev->lock);
Aidan Thorntond7aa8022008-04-13 14:38:47 -03002126 spin_lock_init(&dev->slock);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002127 init_waitqueue_head(&dev->open);
Mauro Carvalho Chehaba3a048c2007-11-10 22:21:01 -03002128 init_waitqueue_head(&dev->wait_frame);
2129 init_waitqueue_head(&dev->wait_stream);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002130
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002131 dev->em28xx_write_regs = em28xx_write_regs;
2132 dev->em28xx_read_reg = em28xx_read_reg;
2133 dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len;
2134 dev->em28xx_write_regs_req = em28xx_write_regs_req;
2135 dev->em28xx_read_reg_req = em28xx_read_reg_req;
Sascha Sommerfad7b952007-11-04 08:06:48 -03002136 dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002137
Mauro Carvalho Chehabd7448a82008-01-05 09:59:03 -03002138 errCode = em28xx_read_reg(dev, CHIPID_REG);
2139 if (errCode >= 0)
2140 em28xx_info("em28xx chip ID = %d\n", errCode);
2141
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -03002142 em28xx_pre_card_setup(dev);
2143
2144 errCode = em28xx_config(dev);
2145 if (errCode) {
2146 em28xx_errdev("error configuring device\n");
2147 em28xx_devused &= ~(1<<dev->devno);
2148 kfree(dev);
2149 return -ENOMEM;
2150 }
2151
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -03002152 /* register i2c bus */
2153 em28xx_i2c_register(dev);
2154
2155 /* Do board specific init and eeprom reading */
2156 em28xx_card_setup(dev);
2157
Mauro Carvalho Chehab3abee532008-01-05 17:01:41 -03002158 /* Configure audio */
2159 em28xx_audio_analog_set(dev);
2160
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -03002161 /* configure the device */
2162 em28xx_config_i2c(dev);
2163
Mauro Carvalho Chehab7d497f82007-11-11 14:15:34 -03002164 /* set default norm */
2165 dev->norm = em28xx_video_template.current_norm;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002166
2167 maxw = norm_maxw(dev);
2168 maxh = norm_maxh(dev);
2169
2170 /* set default image size */
2171 dev->width = maxw;
2172 dev->height = maxh;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002173 dev->interlaced = EM28XX_INTERLACED_DEFAULT;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002174 dev->field_size = dev->width * dev->height;
2175 dev->frame_size =
2176 dev->interlaced ? dev->field_size << 1 : dev->field_size;
2177 dev->bytesperline = dev->width * 2;
2178 dev->hscale = 0;
2179 dev->vscale = 0;
2180 dev->ctl_input = 2;
2181
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002182 errCode = em28xx_config(dev);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002183
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002184 list_add_tail(&dev->devlist, &em28xx_devlist);
2185
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002186 /* allocate and fill video video_device struct */
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002187 dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template,
2188 VID_TYPE_CAPTURE, "video");
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002189 if (NULL == dev->vdev) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002190 em28xx_errdev("cannot allocate video_device.\n");
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002191 goto fail_unreg;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002192 }
Mauro Carvalho Chehabed086312008-01-24 06:59:20 -03002193 if (dev->tuner_type != TUNER_ABSENT)
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002194 dev->vdev->type |= VID_TYPE_TUNER;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002195
2196 /* register v4l2 video video_device */
2197 retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
2198 video_nr[dev->devno]);
2199 if (retval) {
2200 em28xx_errdev("unable to register video device (error=%i).\n",
2201 retval);
2202 goto fail_unreg;
2203 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002204
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002205 /* Allocate and fill vbi video_device struct */
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002206 dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
2207 VFL_TYPE_VBI, "vbi");
2208 /* register v4l2 vbi video_device */
2209 if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
2210 vbi_nr[dev->devno]) < 0) {
2211 em28xx_errdev("unable to register vbi device\n");
2212 retval = -ENODEV;
2213 goto fail_unreg;
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002214 }
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002215
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002216 if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
2217 dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
2218 VFL_TYPE_RADIO, "radio");
2219 if (NULL == dev->radio_dev) {
2220 em28xx_errdev("cannot allocate video_device.\n");
2221 goto fail_unreg;
2222 }
2223 retval = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
2224 radio_nr[dev->devno]);
2225 if (retval < 0) {
2226 em28xx_errdev("can't register radio device\n");
2227 goto fail_unreg;
2228 }
2229 em28xx_info("Registered radio device as /dev/radio%d\n",
2230 dev->radio_dev->minor & 0x1f);
2231 }
2232
Mauro Carvalho Chehabad0ebb92008-04-13 14:37:52 -03002233 /* init video dma queues */
2234 INIT_LIST_HEAD(&dev->vidq.active);
2235 INIT_LIST_HEAD(&dev->vidq.queued);
2236
2237 dev->vidq.timeout.function = em28xx_vid_timeout;
2238 dev->vidq.timeout.data = (unsigned long)dev;
2239 init_timer(&dev->vidq.timeout);
2240
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002241
Sascha Sommer5a804152007-11-03 21:22:38 -03002242 if (dev->has_msp34xx) {
2243 /* Send a reset to other chips via gpio */
2244 em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1);
2245 msleep(3);
2246 em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1);
2247 msleep(3);
Sascha Sommer5a804152007-11-03 21:22:38 -03002248 }
Mauro Carvalho Chehab195a4ef2007-11-11 13:17:17 -03002249
Sascha Sommer5a804152007-11-03 21:22:38 -03002250 video_mux(dev, 0);
2251
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002252 em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n",
2253 dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
2254 dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002255
Mauro Carvalho Chehab6d794682008-01-05 09:57:31 -03002256 mutex_lock(&em28xx_extension_devlist_lock);
2257 if (!list_empty(&em28xx_extension_devlist)) {
2258 list_for_each_entry(ops, &em28xx_extension_devlist, next) {
2259 if (ops->id)
2260 ops->init(dev);
2261 }
2262 }
2263 mutex_unlock(&em28xx_extension_devlist_lock);
2264
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002265 return 0;
Mauro Carvalho Chehab0be43752008-01-05 17:22:01 -03002266
2267fail_unreg:
2268 em28xx_release_resources(dev);
2269 mutex_unlock(&dev->lock);
2270 kfree(dev);
2271 return retval;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002272}
2273
Mauro Carvalho Chehabd7448a82008-01-05 09:59:03 -03002274#if defined(CONFIG_MODULES) && defined(MODULE)
2275static void request_module_async(struct work_struct *work)
2276{
2277 struct em28xx *dev = container_of(work,
2278 struct em28xx, request_module_wk);
2279
Mauro Carvalho Chehab3f4dfe22008-01-06 09:54:17 -03002280 if (dev->has_audio_class)
2281 request_module("snd-usb-audio");
2282 else
Mauro Carvalho Chehabd7448a82008-01-05 09:59:03 -03002283 request_module("em28xx-alsa");
2284}
2285
2286static void request_modules(struct em28xx *dev)
2287{
2288 INIT_WORK(&dev->request_module_wk, request_module_async);
2289 schedule_work(&dev->request_module_wk);
2290}
2291#else
2292#define request_modules(dev)
2293#endif /* CONFIG_MODULES */
2294
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002295/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002296 * em28xx_usb_probe()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002297 * checks for supported devices
2298 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002299static int em28xx_usb_probe(struct usb_interface *interface,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002300 const struct usb_device_id *id)
2301{
2302 const struct usb_endpoint_descriptor *endpoint;
2303 struct usb_device *udev;
Mauro Carvalho Chehab9d4d9c02005-11-08 21:38:52 -08002304 struct usb_interface *uif;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002305 struct em28xx *dev = NULL;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002306 int retval = -ENODEV;
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -03002307 int i, nr, ifnum;
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002308
2309 udev = usb_get_dev(interface_to_usbdev(interface));
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -08002310 ifnum = interface->altsetting[0].desc.bInterfaceNumber;
2311
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002312 /* Check to see next free device and mark as used */
2313 nr=find_first_zero_bit(&em28xx_devused,EM28XX_MAXBOARDS);
2314 em28xx_devused|=1<<nr;
Mauro Carvalho Chehab91cad0f2005-11-08 21:38:13 -08002315
2316 /* Don't register audio interfaces */
2317 if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002318 em28xx_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n",
Mauro Carvalho Chehab91cad0f2005-11-08 21:38:13 -08002319 udev->descriptor.idVendor,udev->descriptor.idProduct,
2320 ifnum,
2321 interface->altsetting[0].desc.bInterfaceClass);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002322
2323 em28xx_devused&=~(1<<nr);
Mauro Carvalho Chehab91cad0f2005-11-08 21:38:13 -08002324 return -ENODEV;
2325 }
2326
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002327 em28xx_err(DRIVER_NAME " new video device (%04x:%04x): interface %i, class %i\n",
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -08002328 udev->descriptor.idVendor,udev->descriptor.idProduct,
2329 ifnum,
2330 interface->altsetting[0].desc.bInterfaceClass);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002331
Mauro Carvalho Chehabd5e52652005-11-08 21:37:32 -08002332 endpoint = &interface->cur_altsetting->endpoint[1].desc;
2333
Michael Opdenacker59c51592007-05-09 08:57:56 +02002334 /* check if the device has the iso in endpoint at the correct place */
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002335 if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
2336 USB_ENDPOINT_XFER_ISOC) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002337 em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n");
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002338 em28xx_devused&=~(1<<nr);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002339 return -ENODEV;
2340 }
2341 if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002342 em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n");
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002343 em28xx_devused&=~(1<<nr);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002344 return -ENODEV;
2345 }
2346
Mauro Carvalho Chehab19478842006-03-14 17:24:57 -03002347 if (nr >= EM28XX_MAXBOARDS) {
Mauro Carvalho Chehab9d4d9c02005-11-08 21:38:52 -08002348 printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002349 em28xx_devused&=~(1<<nr);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -08002350 return -ENOMEM;
2351 }
2352
2353 /* allocate memory for our device state and initialize it */
Panagiotis Issaris74081872006-01-11 19:40:56 -02002354 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -08002355 if (dev == NULL) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002356 em28xx_err(DRIVER_NAME ": out of memory!\n");
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002357 em28xx_devused&=~(1<<nr);
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -08002358 return -ENOMEM;
2359 }
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -08002360
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002361 snprintf(dev->name, 29, "em28xx #%d", nr);
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -03002362 dev->devno = nr;
2363 dev->model = id->driver_info;
Mauro Carvalho Chehab3687e1e2008-02-08 15:44:25 -03002364 dev->alt = -1;
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002365
Mauro Carvalho Chehabd7448a82008-01-05 09:59:03 -03002366 /* Checks if audio is provided by some interface */
2367 for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {
2368 uif = udev->config->interface[i];
2369 if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
2370 dev->has_audio_class = 1;
2371 break;
2372 }
2373 }
2374
2375 printk(KERN_INFO DRIVER_NAME " %s usb audio class\n",
2376 dev->has_audio_class ? "Has" : "Doesn't have");
2377
Mauro Carvalho Chehab9d4d9c02005-11-08 21:38:52 -08002378 /* compute alternate max packet sizes */
2379 uif = udev->actconfig->interface[0];
2380
2381 dev->num_alt=uif->num_altsetting;
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002382 em28xx_info("Alternate settings: %i\n",dev->num_alt);
Mauro Carvalho Chehab9d4d9c02005-11-08 21:38:52 -08002383// dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)*
2384 dev->alt_max_pkt_size = kmalloc(32*
2385 dev->num_alt,GFP_KERNEL);
2386 if (dev->alt_max_pkt_size == NULL) {
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002387 em28xx_errdev("out of memory!\n");
2388 em28xx_devused&=~(1<<nr);
Jesper Juhl1207cf842007-08-09 23:02:36 +02002389 kfree(dev);
Mauro Carvalho Chehab9d4d9c02005-11-08 21:38:52 -08002390 return -ENOMEM;
2391 }
2392
2393 for (i = 0; i < dev->num_alt ; i++) {
2394 u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
2395 wMaxPacketSize);
2396 dev->alt_max_pkt_size[i] =
2397 (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002398 em28xx_info("Alternate setting %i, max size= %i\n",i,
Mauro Carvalho Chehab9d4d9c02005-11-08 21:38:52 -08002399 dev->alt_max_pkt_size[i]);
2400 }
2401
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002402 if ((card[nr]>=0)&&(card[nr]<em28xx_bcount))
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -03002403 dev->model = card[nr];
Mauro Carvalho Chehab596d92d2005-11-08 21:37:24 -08002404
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002405 /* allocate device struct */
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -03002406 retval = em28xx_init_dev(&dev, udev, nr);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002407 if (retval)
2408 return retval;
2409
Mauro Carvalho Chehab03910cc2007-11-03 21:20:59 -03002410 em28xx_info("Found %s\n", em28xx_boards[dev->model].name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002411
2412 /* save our data pointer in this interface device */
2413 usb_set_intfdata(interface, dev);
Mauro Carvalho Chehabd7448a82008-01-05 09:59:03 -03002414
2415 request_modules(dev);
2416
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002417 return 0;
2418}
2419
2420/*
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002421 * em28xx_usb_disconnect()
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002422 * called when the device gets diconencted
2423 * video device will be unregistered on v4l2_close in case it is still open
2424 */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002425static void em28xx_usb_disconnect(struct usb_interface *interface)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002426{
Sascha Sommer5a804152007-11-03 21:22:38 -03002427 struct em28xx *dev;
Mauro Carvalho Chehab6d794682008-01-05 09:57:31 -03002428 struct em28xx_ops *ops = NULL;
Sascha Sommer5a804152007-11-03 21:22:38 -03002429
2430 dev = usb_get_intfdata(interface);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002431 usb_set_intfdata(interface, NULL);
2432
2433 if (!dev)
2434 return;
2435
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002436 em28xx_info("disconnecting %s\n", dev->vdev->name);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002437
Sascha Sommer5a804152007-11-03 21:22:38 -03002438 /* wait until all current v4l2 io is finished then deallocate resources */
2439 mutex_lock(&dev->lock);
2440
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002441 wake_up_interruptible_all(&dev->open);
2442
2443 if (dev->users) {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002444 em28xx_warn
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002445 ("device /dev/video%d is open! Deregistration and memory "
Mauro Carvalho Chehabe5589be2006-01-23 17:11:08 -02002446 "deallocation are deferred on close.\n",
2447 dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN);
2448
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002449 dev->state |= DEV_MISCONFIGURED;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002450 em28xx_uninit_isoc(dev);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002451 dev->state |= DEV_DISCONNECTED;
2452 wake_up_interruptible(&dev->wait_frame);
2453 wake_up_interruptible(&dev->wait_stream);
2454 } else {
2455 dev->state |= DEV_DISCONNECTED;
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002456 em28xx_release_resources(dev);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002457 }
Ingo Molnar3593cab2006-02-07 06:49:14 -02002458 mutex_unlock(&dev->lock);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002459
Mauro Carvalho Chehab6d794682008-01-05 09:57:31 -03002460 mutex_lock(&em28xx_extension_devlist_lock);
2461 if (!list_empty(&em28xx_extension_devlist)) {
2462 list_for_each_entry(ops, &em28xx_extension_devlist, next) {
2463 ops->fini(dev);
2464 }
2465 }
2466 mutex_unlock(&em28xx_extension_devlist_lock);
2467
Mauro Carvalho Chehab9d4d9c02005-11-08 21:38:52 -08002468 if (!dev->users) {
2469 kfree(dev->alt_max_pkt_size);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002470 kfree(dev);
Mauro Carvalho Chehab9d4d9c02005-11-08 21:38:52 -08002471 }
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002472}
2473
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002474static struct usb_driver em28xx_usb_driver = {
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002475 .name = "em28xx",
2476 .probe = em28xx_usb_probe,
2477 .disconnect = em28xx_usb_disconnect,
2478 .id_table = em28xx_id_table,
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002479};
2480
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002481static int __init em28xx_module_init(void)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002482{
2483 int result;
2484
2485 printk(KERN_INFO DRIVER_NAME " v4l2 driver version %d.%d.%d loaded\n",
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002486 (EM28XX_VERSION_CODE >> 16) & 0xff,
2487 (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002488#ifdef SNAPSHOT
2489 printk(KERN_INFO DRIVER_NAME " snapshot date %04d-%02d-%02d\n",
2490 SNAPSHOT / 10000, (SNAPSHOT / 100) % 100, SNAPSHOT % 100);
2491#endif
2492
2493 /* register this driver with the USB subsystem */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002494 result = usb_register(&em28xx_usb_driver);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002495 if (result)
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002496 em28xx_err(DRIVER_NAME
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002497 " usb_register failed. Error number %d.\n", result);
2498
2499 return result;
2500}
2501
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002502static void __exit em28xx_module_exit(void)
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002503{
2504 /* deregister this driver with the USB subsystem */
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002505 usb_deregister(&em28xx_usb_driver);
akpm@osdl.orga6c2ba22005-11-08 21:37:07 -08002506}
2507
Mauro Carvalho Chehab3acf2802005-11-08 21:38:27 -08002508module_init(em28xx_module_init);
2509module_exit(em28xx_module_exit);