diff options
Diffstat (limited to 'drivers/media/video')
52 files changed, 11390 insertions, 3220 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index b8fde5cf4735..29a11c1db1b7 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -184,6 +184,14 @@ config VIDEO_KS0127 | |||
184 | To compile this driver as a module, choose M here: the | 184 | To compile this driver as a module, choose M here: the |
185 | module will be called ks0127. | 185 | module will be called ks0127. |
186 | 186 | ||
187 | config VIDEO_OV7670 | ||
188 | tristate "OmniVision OV7670 sensor support" | ||
189 | depends on I2C && VIDEO_V4L2 | ||
190 | ---help--- | ||
191 | This is a Video4Linux2 sensor-level driver for the OmniVision | ||
192 | OV7670 VGA camera. It currently only works with the M88ALP01 | ||
193 | controller. | ||
194 | |||
187 | config VIDEO_SAA7110 | 195 | config VIDEO_SAA7110 |
188 | tristate "Philips SAA7110 video decoder" | 196 | tristate "Philips SAA7110 video decoder" |
189 | depends on VIDEO_V4L1 && I2C | 197 | depends on VIDEO_V4L1 && I2C |
@@ -567,18 +575,6 @@ config VIDEO_ZORAN_AVS6EYES | |||
567 | help | 575 | help |
568 | Support for the AverMedia 6 Eyes video surveillance card. | 576 | Support for the AverMedia 6 Eyes video surveillance card. |
569 | 577 | ||
570 | config VIDEO_ZR36120 | ||
571 | tristate "Zoran ZR36120/36125 Video For Linux" | ||
572 | depends on PCI && I2C && VIDEO_V4L1 && BROKEN | ||
573 | help | ||
574 | Support for ZR36120/ZR36125 based frame grabber/overlay boards. | ||
575 | This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV, | ||
576 | and Buster boards. Please read the material in | ||
577 | <file:Documentation/video4linux/zr36120.txt> for more information. | ||
578 | |||
579 | To compile this driver as a module, choose M here: the | ||
580 | module will be called zr36120. | ||
581 | |||
582 | config VIDEO_MEYE | 578 | config VIDEO_MEYE |
583 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" | 579 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" |
584 | depends on PCI && SONYPI && VIDEO_V4L1 | 580 | depends on PCI && SONYPI && VIDEO_V4L1 |
@@ -670,6 +666,15 @@ config VIDEO_M32R_AR_M64278 | |||
670 | To compile this driver as a module, choose M here: the | 666 | To compile this driver as a module, choose M here: the |
671 | module will be called arv. | 667 | module will be called arv. |
672 | 668 | ||
669 | config VIDEO_CAFE_CCIC | ||
670 | tristate "Marvell 88ALP01 (Cafe) CMOS Camera Controller support" | ||
671 | depends on I2C && VIDEO_V4L2 | ||
672 | select VIDEO_OV7670 | ||
673 | ---help--- | ||
674 | This is a video4linux2 driver for the Marvell 88ALP01 integrated | ||
675 | CMOS camera controller. This is the controller found on first- | ||
676 | generation OLPC systems. | ||
677 | |||
673 | # | 678 | # |
674 | # USB Multimedia device configuration | 679 | # USB Multimedia device configuration |
675 | # | 680 | # |
@@ -681,6 +686,8 @@ source "drivers/media/video/pvrusb2/Kconfig" | |||
681 | 686 | ||
682 | source "drivers/media/video/em28xx/Kconfig" | 687 | source "drivers/media/video/em28xx/Kconfig" |
683 | 688 | ||
689 | source "drivers/media/video/usbvision/Kconfig" | ||
690 | |||
684 | source "drivers/media/video/usbvideo/Kconfig" | 691 | source "drivers/media/video/usbvideo/Kconfig" |
685 | 692 | ||
686 | source "drivers/media/video/et61x251/Kconfig" | 693 | source "drivers/media/video/et61x251/Kconfig" |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index af57abce8a6e..9b1f3f06bb7c 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -2,7 +2,6 @@ | |||
2 | # Makefile for the video capture/playback device drivers. | 2 | # Makefile for the video capture/playback device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o | ||
6 | zr36067-objs := zoran_procfs.o zoran_device.o \ | 5 | zr36067-objs := zoran_procfs.o zoran_device.o \ |
7 | zoran_driver.o zoran_card.o | 6 | zoran_driver.o zoran_card.o |
8 | tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ | 7 | tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ |
@@ -23,7 +22,6 @@ obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o | |||
23 | obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o | 22 | obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o |
24 | obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o | 23 | obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o |
25 | 24 | ||
26 | obj-$(CONFIG_VIDEO_ZR36120) += zoran.o | ||
27 | obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o | 25 | obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o |
28 | obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o | 26 | obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o |
29 | obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o | 27 | obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o |
@@ -64,6 +62,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o | |||
64 | obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ | 62 | obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ |
65 | obj-$(CONFIG_VIDEO_CX88) += cx88/ | 63 | obj-$(CONFIG_VIDEO_CX88) += cx88/ |
66 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ | 64 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ |
65 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ | ||
67 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o | 66 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o |
68 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ | 67 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ |
69 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o | 68 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o |
@@ -92,6 +91,9 @@ obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o | |||
92 | obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o | 91 | obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o |
93 | obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o | 92 | obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o |
94 | 93 | ||
94 | obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o | ||
95 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o | ||
96 | |||
95 | obj-$(CONFIG_USB_DABUSB) += dabusb.o | 97 | obj-$(CONFIG_USB_DABUSB) += dabusb.o |
96 | obj-$(CONFIG_USB_OV511) += ov511.o | 98 | obj-$(CONFIG_USB_OV511) += ov511.o |
97 | obj-$(CONFIG_USB_SE401) += se401.o | 99 | obj-$(CONFIG_USB_SE401) += se401.o |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 6e1ddad9f0c1..3c8e4742dccc 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -1793,7 +1793,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) | |||
1793 | memset(i,0,sizeof(*i)); | 1793 | memset(i,0,sizeof(*i)); |
1794 | i->index = n; | 1794 | i->index = n; |
1795 | i->type = V4L2_INPUT_TYPE_CAMERA; | 1795 | i->type = V4L2_INPUT_TYPE_CAMERA; |
1796 | i->audioset = 0; | 1796 | i->audioset = 1; |
1797 | if (i->index == bttv_tvcards[btv->c.type].tuner) { | 1797 | if (i->index == bttv_tvcards[btv->c.type].tuner) { |
1798 | sprintf(i->name, "Television"); | 1798 | sprintf(i->name, "Television"); |
1799 | i->type = V4L2_INPUT_TYPE_TUNER; | 1799 | i->type = V4L2_INPUT_TYPE_TUNER; |
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 933d6db09acb..cbc012f71f52 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
@@ -259,24 +259,59 @@ static void bttv_rc5_timer_keyup(unsigned long data) | |||
259 | 259 | ||
260 | /* ---------------------------------------------------------------------- */ | 260 | /* ---------------------------------------------------------------------- */ |
261 | 261 | ||
262 | static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir) | ||
263 | { | ||
264 | if (ir->polling) { | ||
265 | init_timer(&ir->timer); | ||
266 | ir->timer.function = bttv_input_timer; | ||
267 | ir->timer.data = (unsigned long)btv; | ||
268 | ir->timer.expires = jiffies + HZ; | ||
269 | add_timer(&ir->timer); | ||
270 | } else if (ir->rc5_gpio) { | ||
271 | /* set timer_end for code completion */ | ||
272 | init_timer(&ir->timer_end); | ||
273 | ir->timer_end.function = bttv_rc5_timer_end; | ||
274 | ir->timer_end.data = (unsigned long)ir; | ||
275 | |||
276 | init_timer(&ir->timer_keyup); | ||
277 | ir->timer_keyup.function = bttv_rc5_timer_keyup; | ||
278 | ir->timer_keyup.data = (unsigned long)ir; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | static void bttv_ir_stop(struct bttv *btv) | ||
283 | { | ||
284 | if (btv->remote->polling) { | ||
285 | del_timer_sync(&btv->remote->timer); | ||
286 | flush_scheduled_work(); | ||
287 | } | ||
288 | |||
289 | if (btv->remote->rc5_gpio) { | ||
290 | u32 gpio; | ||
291 | |||
292 | del_timer_sync(&btv->remote->timer_end); | ||
293 | flush_scheduled_work(); | ||
294 | |||
295 | gpio = bttv_gpio_read(&btv->c); | ||
296 | bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); | ||
297 | } | ||
298 | } | ||
299 | |||
262 | int bttv_input_init(struct bttv *btv) | 300 | int bttv_input_init(struct bttv *btv) |
263 | { | 301 | { |
264 | struct bttv_ir *ir; | 302 | struct bttv_ir *ir; |
265 | IR_KEYTAB_TYPE *ir_codes = NULL; | 303 | IR_KEYTAB_TYPE *ir_codes = NULL; |
266 | struct input_dev *input_dev; | 304 | struct input_dev *input_dev; |
267 | int ir_type = IR_TYPE_OTHER; | 305 | int ir_type = IR_TYPE_OTHER; |
306 | int err = -ENOMEM; | ||
268 | 307 | ||
269 | if (!btv->has_remote) | 308 | if (!btv->has_remote) |
270 | return -ENODEV; | 309 | return -ENODEV; |
271 | 310 | ||
272 | ir = kzalloc(sizeof(*ir),GFP_KERNEL); | 311 | ir = kzalloc(sizeof(*ir),GFP_KERNEL); |
273 | input_dev = input_allocate_device(); | 312 | input_dev = input_allocate_device(); |
274 | if (!ir || !input_dev) { | 313 | if (!ir || !input_dev) |
275 | kfree(ir); | 314 | goto err_out_free; |
276 | input_free_device(input_dev); | ||
277 | return -ENOMEM; | ||
278 | } | ||
279 | memset(ir,0,sizeof(*ir)); | ||
280 | 315 | ||
281 | /* detect & configure */ | 316 | /* detect & configure */ |
282 | switch (btv->c.type) { | 317 | switch (btv->c.type) { |
@@ -348,10 +383,9 @@ int bttv_input_init(struct bttv *btv) | |||
348 | break; | 383 | break; |
349 | } | 384 | } |
350 | if (NULL == ir_codes) { | 385 | if (NULL == ir_codes) { |
351 | dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type); | 386 | dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type); |
352 | kfree(ir); | 387 | err = -ENODEV; |
353 | input_free_device(input_dev); | 388 | goto err_out_free; |
354 | return -ENODEV; | ||
355 | } | 389 | } |
356 | 390 | ||
357 | if (ir->rc5_gpio) { | 391 | if (ir->rc5_gpio) { |
@@ -389,32 +423,26 @@ int bttv_input_init(struct bttv *btv) | |||
389 | input_dev->cdev.dev = &btv->c.pci->dev; | 423 | input_dev->cdev.dev = &btv->c.pci->dev; |
390 | 424 | ||
391 | btv->remote = ir; | 425 | btv->remote = ir; |
392 | if (ir->polling) { | 426 | bttv_ir_start(btv, ir); |
393 | init_timer(&ir->timer); | ||
394 | ir->timer.function = bttv_input_timer; | ||
395 | ir->timer.data = (unsigned long)btv; | ||
396 | ir->timer.expires = jiffies + HZ; | ||
397 | add_timer(&ir->timer); | ||
398 | } else if (ir->rc5_gpio) { | ||
399 | /* set timer_end for code completion */ | ||
400 | init_timer(&ir->timer_end); | ||
401 | ir->timer_end.function = bttv_rc5_timer_end; | ||
402 | ir->timer_end.data = (unsigned long)ir; | ||
403 | |||
404 | init_timer(&ir->timer_keyup); | ||
405 | ir->timer_keyup.function = bttv_rc5_timer_keyup; | ||
406 | ir->timer_keyup.data = (unsigned long)ir; | ||
407 | } | ||
408 | 427 | ||
409 | /* all done */ | 428 | /* all done */ |
410 | input_register_device(btv->remote->dev); | 429 | err = input_register_device(btv->remote->dev); |
411 | printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys); | 430 | if (err) |
431 | goto err_out_stop; | ||
412 | 432 | ||
413 | /* the remote isn't as bouncy as a keyboard */ | 433 | /* the remote isn't as bouncy as a keyboard */ |
414 | ir->dev->rep[REP_DELAY] = repeat_delay; | 434 | ir->dev->rep[REP_DELAY] = repeat_delay; |
415 | ir->dev->rep[REP_PERIOD] = repeat_period; | 435 | ir->dev->rep[REP_PERIOD] = repeat_period; |
416 | 436 | ||
417 | return 0; | 437 | return 0; |
438 | |||
439 | err_out_stop: | ||
440 | bttv_ir_stop(btv); | ||
441 | btv->remote = NULL; | ||
442 | err_out_free: | ||
443 | input_free_device(input_dev); | ||
444 | kfree(ir); | ||
445 | return err; | ||
418 | } | 446 | } |
419 | 447 | ||
420 | void bttv_input_fini(struct bttv *btv) | 448 | void bttv_input_fini(struct bttv *btv) |
@@ -422,22 +450,7 @@ void bttv_input_fini(struct bttv *btv) | |||
422 | if (btv->remote == NULL) | 450 | if (btv->remote == NULL) |
423 | return; | 451 | return; |
424 | 452 | ||
425 | if (btv->remote->polling) { | 453 | bttv_ir_stop(btv); |
426 | del_timer_sync(&btv->remote->timer); | ||
427 | flush_scheduled_work(); | ||
428 | } | ||
429 | |||
430 | |||
431 | if (btv->remote->rc5_gpio) { | ||
432 | u32 gpio; | ||
433 | |||
434 | del_timer_sync(&btv->remote->timer_end); | ||
435 | flush_scheduled_work(); | ||
436 | |||
437 | gpio = bttv_gpio_read(&btv->c); | ||
438 | bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); | ||
439 | } | ||
440 | |||
441 | input_unregister_device(btv->remote->dev); | 454 | input_unregister_device(btv->remote->dev); |
442 | kfree(btv->remote); | 455 | kfree(btv->remote); |
443 | btv->remote = NULL; | 456 | btv->remote = NULL; |
diff --git a/drivers/media/video/cafe_ccic-regs.h b/drivers/media/video/cafe_ccic-regs.h new file mode 100644 index 000000000000..b2c22a0d6643 --- /dev/null +++ b/drivers/media/video/cafe_ccic-regs.h | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Register definitions for the m88alp01 camera interface. Offsets in bytes | ||
3 | * as given in the spec. | ||
4 | * | ||
5 | * Copyright 2006 One Laptop Per Child Association, Inc. | ||
6 | * | ||
7 | * Written by Jonathan Corbet, corbet@lwn.net. | ||
8 | * | ||
9 | * This file may be distributed under the terms of the GNU General | ||
10 | * Public License, version 2. | ||
11 | */ | ||
12 | #define REG_Y0BAR 0x00 | ||
13 | #define REG_Y1BAR 0x04 | ||
14 | #define REG_Y2BAR 0x08 | ||
15 | /* ... */ | ||
16 | |||
17 | #define REG_IMGPITCH 0x24 /* Image pitch register */ | ||
18 | #define IMGP_YP_SHFT 2 /* Y pitch params */ | ||
19 | #define IMGP_YP_MASK 0x00003ffc /* Y pitch field */ | ||
20 | #define IMGP_UVP_SHFT 18 /* UV pitch (planar) */ | ||
21 | #define IMGP_UVP_MASK 0x3ffc0000 | ||
22 | #define REG_IRQSTATRAW 0x28 /* RAW IRQ Status */ | ||
23 | #define IRQ_EOF0 0x00000001 /* End of frame 0 */ | ||
24 | #define IRQ_EOF1 0x00000002 /* End of frame 1 */ | ||
25 | #define IRQ_EOF2 0x00000004 /* End of frame 2 */ | ||
26 | #define IRQ_SOF0 0x00000008 /* Start of frame 0 */ | ||
27 | #define IRQ_SOF1 0x00000010 /* Start of frame 1 */ | ||
28 | #define IRQ_SOF2 0x00000020 /* Start of frame 2 */ | ||
29 | #define IRQ_OVERFLOW 0x00000040 /* FIFO overflow */ | ||
30 | #define IRQ_TWSIW 0x00010000 /* TWSI (smbus) write */ | ||
31 | #define IRQ_TWSIR 0x00020000 /* TWSI read */ | ||
32 | #define IRQ_TWSIE 0x00040000 /* TWSI error */ | ||
33 | #define TWSIIRQS (IRQ_TWSIW|IRQ_TWSIR|IRQ_TWSIE) | ||
34 | #define FRAMEIRQS (IRQ_EOF0|IRQ_EOF1|IRQ_EOF2|IRQ_SOF0|IRQ_SOF1|IRQ_SOF2) | ||
35 | #define ALLIRQS (TWSIIRQS|FRAMEIRQS|IRQ_OVERFLOW) | ||
36 | #define REG_IRQMASK 0x2c /* IRQ mask - same bits as IRQSTAT */ | ||
37 | #define REG_IRQSTAT 0x30 /* IRQ status / clear */ | ||
38 | |||
39 | #define REG_IMGSIZE 0x34 /* Image size */ | ||
40 | #define IMGSZ_V_MASK 0x1fff0000 | ||
41 | #define IMGSZ_V_SHIFT 16 | ||
42 | #define IMGSZ_H_MASK 0x00003fff | ||
43 | #define REG_IMGOFFSET 0x38 /* IMage offset */ | ||
44 | |||
45 | #define REG_CTRL0 0x3c /* Control 0 */ | ||
46 | #define C0_ENABLE 0x00000001 /* Makes the whole thing go */ | ||
47 | |||
48 | /* Mask for all the format bits */ | ||
49 | #define C0_DF_MASK 0x00fffffc /* Bits 2-23 */ | ||
50 | |||
51 | /* RGB ordering */ | ||
52 | #define C0_RGB4_RGBX 0x00000000 | ||
53 | #define C0_RGB4_XRGB 0x00000004 | ||
54 | #define C0_RGB4_BGRX 0x00000008 | ||
55 | #define C0_RGB4_XBGR 0x0000000c | ||
56 | #define C0_RGB5_RGGB 0x00000000 | ||
57 | #define C0_RGB5_GRBG 0x00000004 | ||
58 | #define C0_RGB5_GBRG 0x00000008 | ||
59 | #define C0_RGB5_BGGR 0x0000000c | ||
60 | |||
61 | /* Spec has two fields for DIN and DOUT, but they must match, so | ||
62 | combine them here. */ | ||
63 | #define C0_DF_YUV 0x00000000 /* Data is YUV */ | ||
64 | #define C0_DF_RGB 0x000000a0 /* ... RGB */ | ||
65 | #define C0_DF_BAYER 0x00000140 /* ... Bayer */ | ||
66 | /* 8-8-8 must be missing from the below - ask */ | ||
67 | #define C0_RGBF_565 0x00000000 | ||
68 | #define C0_RGBF_444 0x00000800 | ||
69 | #define C0_RGB_BGR 0x00001000 /* Blue comes first */ | ||
70 | #define C0_YUV_PLANAR 0x00000000 /* YUV 422 planar format */ | ||
71 | #define C0_YUV_PACKED 0x00008000 /* YUV 422 packed */ | ||
72 | #define C0_YUV_420PL 0x0000a000 /* YUV 420 planar */ | ||
73 | /* Think that 420 packed must be 111 - ask */ | ||
74 | #define C0_YUVE_YUYV 0x00000000 /* Y1CbY0Cr */ | ||
75 | #define C0_YUVE_YVYU 0x00010000 /* Y1CrY0Cb */ | ||
76 | #define C0_YUVE_VYUY 0x00020000 /* CrY1CbY0 */ | ||
77 | #define C0_YUVE_UYVY 0x00030000 /* CbY1CrY0 */ | ||
78 | #define C0_YUVE_XYUV 0x00000000 /* 420: .YUV */ | ||
79 | #define C0_YUVE_XYVU 0x00010000 /* 420: .YVU */ | ||
80 | #define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */ | ||
81 | #define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */ | ||
82 | /* Bayer bits 18,19 if needed */ | ||
83 | #define C0_HPOL_LOW 0x01000000 /* HSYNC polarity active low */ | ||
84 | #define C0_VPOL_LOW 0x02000000 /* VSYNC polarity active low */ | ||
85 | #define C0_VCLK_LOW 0x04000000 /* VCLK on falling edge */ | ||
86 | #define C0_DOWNSCALE 0x08000000 /* Enable downscaler */ | ||
87 | #define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */ | ||
88 | #define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */ | ||
89 | #define CO_SOF_NOSYNC 0x40000000 /* Use inband active signaling */ | ||
90 | |||
91 | |||
92 | #define REG_CTRL1 0x40 /* Control 1 */ | ||
93 | #define C1_444ALPHA 0x00f00000 /* Alpha field in RGB444 */ | ||
94 | #define C1_ALPHA_SHFT 20 | ||
95 | #define C1_DMAB32 0x00000000 /* 32-byte DMA burst */ | ||
96 | #define C1_DMAB16 0x02000000 /* 16-byte DMA burst */ | ||
97 | #define C1_DMAB64 0x04000000 /* 64-byte DMA burst */ | ||
98 | #define C1_DMAB_MASK 0x06000000 | ||
99 | #define C1_TWOBUFS 0x08000000 /* Use only two DMA buffers */ | ||
100 | #define C1_PWRDWN 0x10000000 /* Power down */ | ||
101 | |||
102 | #define REG_CLKCTRL 0x88 /* Clock control */ | ||
103 | #define CLK_DIV_MASK 0x0000ffff /* Upper bits RW "reserved" */ | ||
104 | |||
105 | #define REG_GPR 0xb4 /* General purpose register. This | ||
106 | controls inputs to the power and reset | ||
107 | pins on the OV7670 used with OLPC; | ||
108 | other deployments could differ. */ | ||
109 | #define GPR_C1EN 0x00000020 /* Pad 1 (power down) enable */ | ||
110 | #define GPR_C0EN 0x00000010 /* Pad 0 (reset) enable */ | ||
111 | #define GPR_C1 0x00000002 /* Control 1 value */ | ||
112 | /* | ||
113 | * Control 0 is wired to reset on OLPC machines. For ov7x sensors, | ||
114 | * it is active low, for 0v6x, instead, it's active high. What | ||
115 | * fun. | ||
116 | */ | ||
117 | #define GPR_C0 0x00000001 /* Control 0 value */ | ||
118 | |||
119 | #define REG_TWSIC0 0xb8 /* TWSI (smbus) control 0 */ | ||
120 | #define TWSIC0_EN 0x00000001 /* TWSI enable */ | ||
121 | #define TWSIC0_MODE 0x00000002 /* 1 = 16-bit, 0 = 8-bit */ | ||
122 | #define TWSIC0_SID 0x000003fc /* Slave ID */ | ||
123 | #define TWSIC0_SID_SHIFT 2 | ||
124 | #define TWSIC0_CLKDIV 0x0007fc00 /* Clock divider */ | ||
125 | #define TWSIC0_MASKACK 0x00400000 /* Mask ack from sensor */ | ||
126 | #define TWSIC0_OVMAGIC 0x00800000 /* Make it work on OV sensors */ | ||
127 | |||
128 | #define REG_TWSIC1 0xbc /* TWSI control 1 */ | ||
129 | #define TWSIC1_DATA 0x0000ffff /* Data to/from camchip */ | ||
130 | #define TWSIC1_ADDR 0x00ff0000 /* Address (register) */ | ||
131 | #define TWSIC1_ADDR_SHIFT 16 | ||
132 | #define TWSIC1_READ 0x01000000 /* Set for read op */ | ||
133 | #define TWSIC1_WSTAT 0x02000000 /* Write status */ | ||
134 | #define TWSIC1_RVALID 0x04000000 /* Read data valid */ | ||
135 | #define TWSIC1_ERROR 0x08000000 /* Something screwed up */ | ||
136 | |||
137 | |||
138 | #define REG_UBAR 0xc4 /* Upper base address register */ | ||
139 | |||
140 | /* | ||
141 | * Here's the weird global control registers which are said to live | ||
142 | * way up here. | ||
143 | */ | ||
144 | #define REG_GL_CSR 0x3004 /* Control/status register */ | ||
145 | #define GCSR_SRS 0x00000001 /* SW Reset set */ | ||
146 | #define GCSR_SRC 0x00000002 /* SW Reset clear */ | ||
147 | #define GCSR_MRS 0x00000004 /* Master reset set */ | ||
148 | #define GCSR_MRC 0x00000008 /* HW Reset clear */ | ||
149 | #define GCSR_CCIC_EN 0x00004000 /* CCIC Clock enable */ | ||
150 | #define REG_GL_IMASK 0x300c /* Interrupt mask register */ | ||
151 | #define GIMSK_CCIC_EN 0x00000004 /* CCIC Interrupt enable */ | ||
152 | |||
153 | #define REG_LEN REG_GL_IMASK + 4 | ||
154 | |||
155 | |||
156 | /* | ||
157 | * Useful stuff that probably belongs somewhere global. | ||
158 | */ | ||
159 | #define VGA_WIDTH 640 | ||
160 | #define VGA_HEIGHT 480 | ||
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c new file mode 100644 index 000000000000..e347c7ebc984 --- /dev/null +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -0,0 +1,2228 @@ | |||
1 | /* | ||
2 | * A driver for the CMOS camera controller in the Marvell 88ALP01 "cafe" | ||
3 | * multifunction chip. Currently works with the Omnivision OV7670 | ||
4 | * sensor. | ||
5 | * | ||
6 | * Copyright 2006 One Laptop Per Child Association, Inc. | ||
7 | * | ||
8 | * Written by Jonathan Corbet, corbet@lwn.net. | ||
9 | * | ||
10 | * This file may be distributed under the terms of the GNU General | ||
11 | * Public License, version 2. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/pci.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/videodev2.h> | ||
24 | #include <media/v4l2-common.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/wait.h> | ||
27 | #include <linux/list.h> | ||
28 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/debugfs.h> | ||
31 | #include <linux/jiffies.h> | ||
32 | #include <linux/vmalloc.h> | ||
33 | |||
34 | #include <asm/uaccess.h> | ||
35 | #include <asm/io.h> | ||
36 | |||
37 | #include "cafe_ccic-regs.h" | ||
38 | |||
39 | #define CAFE_VERSION 0x000001 | ||
40 | |||
41 | |||
42 | /* | ||
43 | * Parameters. | ||
44 | */ | ||
45 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); | ||
46 | MODULE_DESCRIPTION("Marvell 88ALP01 CMOS Camera Controller driver"); | ||
47 | MODULE_LICENSE("GPL"); | ||
48 | MODULE_SUPPORTED_DEVICE("Video"); | ||
49 | |||
50 | /* | ||
51 | * Internal DMA buffer management. Since the controller cannot do S/G I/O, | ||
52 | * we must have physically contiguous buffers to bring frames into. | ||
53 | * These parameters control how many buffers we use, whether we | ||
54 | * allocate them at load time (better chance of success, but nails down | ||
55 | * memory) or when somebody tries to use the camera (riskier), and, | ||
56 | * for load-time allocation, how big they should be. | ||
57 | * | ||
58 | * The controller can cycle through three buffers. We could use | ||
59 | * more by flipping pointers around, but it probably makes little | ||
60 | * sense. | ||
61 | */ | ||
62 | |||
63 | #define MAX_DMA_BUFS 3 | ||
64 | static int alloc_bufs_at_load = 0; | ||
65 | module_param(alloc_bufs_at_load, bool, 0444); | ||
66 | MODULE_PARM_DESC(alloc_bufs_at_load, | ||
67 | "Non-zero value causes DMA buffers to be allocated at module " | ||
68 | "load time. This increases the chances of successfully getting " | ||
69 | "those buffers, but at the cost of nailing down the memory from " | ||
70 | "the outset."); | ||
71 | |||
72 | static int n_dma_bufs = 3; | ||
73 | module_param(n_dma_bufs, uint, 0644); | ||
74 | MODULE_PARM_DESC(n_dma_bufs, | ||
75 | "The number of DMA buffers to allocate. Can be either two " | ||
76 | "(saves memory, makes timing tighter) or three."); | ||
77 | |||
78 | static int dma_buf_size = VGA_WIDTH * VGA_HEIGHT * 2; /* Worst case */ | ||
79 | module_param(dma_buf_size, uint, 0444); | ||
80 | MODULE_PARM_DESC(dma_buf_size, | ||
81 | "The size of the allocated DMA buffers. If actual operating " | ||
82 | "parameters require larger buffers, an attempt to reallocate " | ||
83 | "will be made."); | ||
84 | |||
85 | static int min_buffers = 1; | ||
86 | module_param(min_buffers, uint, 0644); | ||
87 | MODULE_PARM_DESC(min_buffers, | ||
88 | "The minimum number of streaming I/O buffers we are willing " | ||
89 | "to work with."); | ||
90 | |||
91 | static int max_buffers = 10; | ||
92 | module_param(max_buffers, uint, 0644); | ||
93 | MODULE_PARM_DESC(max_buffers, | ||
94 | "The maximum number of streaming I/O buffers an application " | ||
95 | "will be allowed to allocate. These buffers are big and live " | ||
96 | "in vmalloc space."); | ||
97 | |||
98 | static int flip = 0; | ||
99 | module_param(flip, bool, 0444); | ||
100 | MODULE_PARM_DESC(flip, | ||
101 | "If set, the sensor will be instructed to flip the image " | ||
102 | "vertically."); | ||
103 | |||
104 | |||
105 | enum cafe_state { | ||
106 | S_NOTREADY, /* Not yet initialized */ | ||
107 | S_IDLE, /* Just hanging around */ | ||
108 | S_FLAKED, /* Some sort of problem */ | ||
109 | S_SINGLEREAD, /* In read() */ | ||
110 | S_SPECREAD, /* Speculative read (for future read()) */ | ||
111 | S_STREAMING /* Streaming data */ | ||
112 | }; | ||
113 | |||
114 | /* | ||
115 | * Tracking of streaming I/O buffers. | ||
116 | */ | ||
117 | struct cafe_sio_buffer { | ||
118 | struct list_head list; | ||
119 | struct v4l2_buffer v4lbuf; | ||
120 | char *buffer; /* Where it lives in kernel space */ | ||
121 | int mapcount; | ||
122 | struct cafe_camera *cam; | ||
123 | }; | ||
124 | |||
125 | /* | ||
126 | * A description of one of our devices. | ||
127 | * Locking: controlled by s_mutex. Certain fields, however, require | ||
128 | * the dev_lock spinlock; they are marked as such by comments. | ||
129 | * dev_lock is also required for access to device registers. | ||
130 | */ | ||
131 | struct cafe_camera | ||
132 | { | ||
133 | enum cafe_state state; | ||
134 | unsigned long flags; /* Buffer status, mainly (dev_lock) */ | ||
135 | int users; /* How many open FDs */ | ||
136 | struct file *owner; /* Who has data access (v4l2) */ | ||
137 | |||
138 | /* | ||
139 | * Subsystem structures. | ||
140 | */ | ||
141 | struct pci_dev *pdev; | ||
142 | struct video_device v4ldev; | ||
143 | struct i2c_adapter i2c_adapter; | ||
144 | struct i2c_client *sensor; | ||
145 | |||
146 | unsigned char __iomem *regs; | ||
147 | struct list_head dev_list; /* link to other devices */ | ||
148 | |||
149 | /* DMA buffers */ | ||
150 | unsigned int nbufs; /* How many are alloc'd */ | ||
151 | int next_buf; /* Next to consume (dev_lock) */ | ||
152 | unsigned int dma_buf_size; /* allocated size */ | ||
153 | void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */ | ||
154 | dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */ | ||
155 | unsigned int specframes; /* Unconsumed spec frames (dev_lock) */ | ||
156 | unsigned int sequence; /* Frame sequence number */ | ||
157 | unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual buffers */ | ||
158 | |||
159 | /* Streaming buffers */ | ||
160 | unsigned int n_sbufs; /* How many we have */ | ||
161 | struct cafe_sio_buffer *sb_bufs; /* The array of housekeeping structs */ | ||
162 | struct list_head sb_avail; /* Available for data (we own) (dev_lock) */ | ||
163 | struct list_head sb_full; /* With data (user space owns) (dev_lock) */ | ||
164 | struct tasklet_struct s_tasklet; | ||
165 | |||
166 | /* Current operating parameters */ | ||
167 | enum v4l2_chip_ident sensor_type; /* Currently ov7670 only */ | ||
168 | struct v4l2_pix_format pix_format; | ||
169 | |||
170 | /* Locks */ | ||
171 | struct mutex s_mutex; /* Access to this structure */ | ||
172 | spinlock_t dev_lock; /* Access to device */ | ||
173 | |||
174 | /* Misc */ | ||
175 | wait_queue_head_t smbus_wait; /* Waiting on i2c events */ | ||
176 | wait_queue_head_t iowait; /* Waiting on frame data */ | ||
177 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
178 | struct dentry *dfs_regs; | ||
179 | struct dentry *dfs_cam_regs; | ||
180 | #endif | ||
181 | }; | ||
182 | |||
183 | /* | ||
184 | * Status flags. Always manipulated with bit operations. | ||
185 | */ | ||
186 | #define CF_BUF0_VALID 0 /* Buffers valid - first three */ | ||
187 | #define CF_BUF1_VALID 1 | ||
188 | #define CF_BUF2_VALID 2 | ||
189 | #define CF_DMA_ACTIVE 3 /* A frame is incoming */ | ||
190 | #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ | ||
191 | |||
192 | |||
193 | |||
194 | /* | ||
195 | * Start over with DMA buffers - dev_lock needed. | ||
196 | */ | ||
197 | static void cafe_reset_buffers(struct cafe_camera *cam) | ||
198 | { | ||
199 | int i; | ||
200 | |||
201 | cam->next_buf = -1; | ||
202 | for (i = 0; i < cam->nbufs; i++) | ||
203 | clear_bit(i, &cam->flags); | ||
204 | cam->specframes = 0; | ||
205 | } | ||
206 | |||
207 | static inline int cafe_needs_config(struct cafe_camera *cam) | ||
208 | { | ||
209 | return test_bit(CF_CONFIG_NEEDED, &cam->flags); | ||
210 | } | ||
211 | |||
212 | static void cafe_set_config_needed(struct cafe_camera *cam, int needed) | ||
213 | { | ||
214 | if (needed) | ||
215 | set_bit(CF_CONFIG_NEEDED, &cam->flags); | ||
216 | else | ||
217 | clear_bit(CF_CONFIG_NEEDED, &cam->flags); | ||
218 | } | ||
219 | |||
220 | |||
221 | |||
222 | |||
223 | /* | ||
224 | * Debugging and related. | ||
225 | */ | ||
226 | #define cam_err(cam, fmt, arg...) \ | ||
227 | dev_err(&(cam)->pdev->dev, fmt, ##arg); | ||
228 | #define cam_warn(cam, fmt, arg...) \ | ||
229 | dev_warn(&(cam)->pdev->dev, fmt, ##arg); | ||
230 | #define cam_dbg(cam, fmt, arg...) \ | ||
231 | dev_dbg(&(cam)->pdev->dev, fmt, ##arg); | ||
232 | |||
233 | |||
234 | /* ---------------------------------------------------------------------*/ | ||
235 | /* | ||
236 | * We keep a simple list of known devices to search at open time. | ||
237 | */ | ||
238 | static LIST_HEAD(cafe_dev_list); | ||
239 | static DEFINE_MUTEX(cafe_dev_list_lock); | ||
240 | |||
241 | static void cafe_add_dev(struct cafe_camera *cam) | ||
242 | { | ||
243 | mutex_lock(&cafe_dev_list_lock); | ||
244 | list_add_tail(&cam->dev_list, &cafe_dev_list); | ||
245 | mutex_unlock(&cafe_dev_list_lock); | ||
246 | } | ||
247 | |||
248 | static void cafe_remove_dev(struct cafe_camera *cam) | ||
249 | { | ||
250 | mutex_lock(&cafe_dev_list_lock); | ||
251 | list_del(&cam->dev_list); | ||
252 | mutex_unlock(&cafe_dev_list_lock); | ||
253 | } | ||
254 | |||
255 | static struct cafe_camera *cafe_find_dev(int minor) | ||
256 | { | ||
257 | struct cafe_camera *cam; | ||
258 | |||
259 | mutex_lock(&cafe_dev_list_lock); | ||
260 | list_for_each_entry(cam, &cafe_dev_list, dev_list) { | ||
261 | if (cam->v4ldev.minor == minor) | ||
262 | goto done; | ||
263 | } | ||
264 | cam = NULL; | ||
265 | done: | ||
266 | mutex_unlock(&cafe_dev_list_lock); | ||
267 | return cam; | ||
268 | } | ||
269 | |||
270 | |||
271 | static struct cafe_camera *cafe_find_by_pdev(struct pci_dev *pdev) | ||
272 | { | ||
273 | struct cafe_camera *cam; | ||
274 | |||
275 | mutex_lock(&cafe_dev_list_lock); | ||
276 | list_for_each_entry(cam, &cafe_dev_list, dev_list) { | ||
277 | if (cam->pdev == pdev) | ||
278 | goto done; | ||
279 | } | ||
280 | cam = NULL; | ||
281 | done: | ||
282 | mutex_unlock(&cafe_dev_list_lock); | ||
283 | return cam; | ||
284 | } | ||
285 | |||
286 | |||
287 | /* ------------------------------------------------------------------------ */ | ||
288 | /* | ||
289 | * Device register I/O | ||
290 | */ | ||
291 | static inline void cafe_reg_write(struct cafe_camera *cam, unsigned int reg, | ||
292 | unsigned int val) | ||
293 | { | ||
294 | iowrite32(val, cam->regs + reg); | ||
295 | } | ||
296 | |||
297 | static inline unsigned int cafe_reg_read(struct cafe_camera *cam, | ||
298 | unsigned int reg) | ||
299 | { | ||
300 | return ioread32(cam->regs + reg); | ||
301 | } | ||
302 | |||
303 | |||
304 | static inline void cafe_reg_write_mask(struct cafe_camera *cam, unsigned int reg, | ||
305 | unsigned int val, unsigned int mask) | ||
306 | { | ||
307 | unsigned int v = cafe_reg_read(cam, reg); | ||
308 | |||
309 | v = (v & ~mask) | (val & mask); | ||
310 | cafe_reg_write(cam, reg, v); | ||
311 | } | ||
312 | |||
313 | static inline void cafe_reg_clear_bit(struct cafe_camera *cam, | ||
314 | unsigned int reg, unsigned int val) | ||
315 | { | ||
316 | cafe_reg_write_mask(cam, reg, 0, val); | ||
317 | } | ||
318 | |||
319 | static inline void cafe_reg_set_bit(struct cafe_camera *cam, | ||
320 | unsigned int reg, unsigned int val) | ||
321 | { | ||
322 | cafe_reg_write_mask(cam, reg, val, val); | ||
323 | } | ||
324 | |||
325 | |||
326 | |||
327 | /* -------------------------------------------------------------------- */ | ||
328 | /* | ||
329 | * The I2C/SMBUS interface to the camera itself starts here. The | ||
330 | * controller handles SMBUS itself, presenting a relatively simple register | ||
331 | * interface; all we have to do is to tell it where to route the data. | ||
332 | */ | ||
333 | #define CAFE_SMBUS_TIMEOUT (HZ) /* generous */ | ||
334 | |||
335 | static int cafe_smbus_write_done(struct cafe_camera *cam) | ||
336 | { | ||
337 | unsigned long flags; | ||
338 | int c1; | ||
339 | |||
340 | /* | ||
341 | * We must delay after the interrupt, or the controller gets confused | ||
342 | * and never does give us good status. Fortunately, we don't do this | ||
343 | * often. | ||
344 | */ | ||
345 | udelay(20); | ||
346 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
347 | c1 = cafe_reg_read(cam, REG_TWSIC1); | ||
348 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
349 | return (c1 & (TWSIC1_WSTAT|TWSIC1_ERROR)) != TWSIC1_WSTAT; | ||
350 | } | ||
351 | |||
352 | static int cafe_smbus_write_data(struct cafe_camera *cam, | ||
353 | u16 addr, u8 command, u8 value) | ||
354 | { | ||
355 | unsigned int rval; | ||
356 | unsigned long flags; | ||
357 | |||
358 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
359 | rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); | ||
360 | rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */ | ||
361 | /* | ||
362 | * Marvell sez set clkdiv to all 1's for now. | ||
363 | */ | ||
364 | rval |= TWSIC0_CLKDIV; | ||
365 | cafe_reg_write(cam, REG_TWSIC0, rval); | ||
366 | (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */ | ||
367 | rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); | ||
368 | cafe_reg_write(cam, REG_TWSIC1, rval); | ||
369 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
370 | msleep(2); /* Required or things flake */ | ||
371 | |||
372 | wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam), | ||
373 | CAFE_SMBUS_TIMEOUT); | ||
374 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
375 | rval = cafe_reg_read(cam, REG_TWSIC1); | ||
376 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
377 | |||
378 | if (rval & TWSIC1_WSTAT) { | ||
379 | cam_err(cam, "SMBUS write (%02x/%02x/%02x) timed out\n", addr, | ||
380 | command, value); | ||
381 | return -EIO; | ||
382 | } | ||
383 | if (rval & TWSIC1_ERROR) { | ||
384 | cam_err(cam, "SMBUS write (%02x/%02x/%02x) error\n", addr, | ||
385 | command, value); | ||
386 | return -EIO; | ||
387 | } | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | |||
392 | |||
393 | static int cafe_smbus_read_done(struct cafe_camera *cam) | ||
394 | { | ||
395 | unsigned long flags; | ||
396 | int c1; | ||
397 | |||
398 | /* | ||
399 | * We must delay after the interrupt, or the controller gets confused | ||
400 | * and never does give us good status. Fortunately, we don't do this | ||
401 | * often. | ||
402 | */ | ||
403 | udelay(20); | ||
404 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
405 | c1 = cafe_reg_read(cam, REG_TWSIC1); | ||
406 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
407 | return c1 & (TWSIC1_RVALID|TWSIC1_ERROR); | ||
408 | } | ||
409 | |||
410 | |||
411 | |||
412 | static int cafe_smbus_read_data(struct cafe_camera *cam, | ||
413 | u16 addr, u8 command, u8 *value) | ||
414 | { | ||
415 | unsigned int rval; | ||
416 | unsigned long flags; | ||
417 | |||
418 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
419 | rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); | ||
420 | rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */ | ||
421 | /* | ||
422 | * Marvel sez set clkdiv to all 1's for now. | ||
423 | */ | ||
424 | rval |= TWSIC0_CLKDIV; | ||
425 | cafe_reg_write(cam, REG_TWSIC0, rval); | ||
426 | (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */ | ||
427 | rval = TWSIC1_READ | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); | ||
428 | cafe_reg_write(cam, REG_TWSIC1, rval); | ||
429 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
430 | |||
431 | wait_event_timeout(cam->smbus_wait, | ||
432 | cafe_smbus_read_done(cam), CAFE_SMBUS_TIMEOUT); | ||
433 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
434 | rval = cafe_reg_read(cam, REG_TWSIC1); | ||
435 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
436 | |||
437 | if (rval & TWSIC1_ERROR) { | ||
438 | cam_err(cam, "SMBUS read (%02x/%02x) error\n", addr, command); | ||
439 | return -EIO; | ||
440 | } | ||
441 | if (! (rval & TWSIC1_RVALID)) { | ||
442 | cam_err(cam, "SMBUS read (%02x/%02x) timed out\n", addr, | ||
443 | command); | ||
444 | return -EIO; | ||
445 | } | ||
446 | *value = rval & 0xff; | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * Perform a transfer over SMBUS. This thing is called under | ||
452 | * the i2c bus lock, so we shouldn't race with ourselves... | ||
453 | */ | ||
454 | static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr, | ||
455 | unsigned short flags, char rw, u8 command, | ||
456 | int size, union i2c_smbus_data *data) | ||
457 | { | ||
458 | struct cafe_camera *cam = i2c_get_adapdata(adapter); | ||
459 | int ret = -EINVAL; | ||
460 | |||
461 | /* | ||
462 | * Refuse to talk to anything but OV cam chips. We should | ||
463 | * never even see an attempt to do so, but one never knows. | ||
464 | */ | ||
465 | if (cam->sensor && addr != cam->sensor->addr) { | ||
466 | cam_err(cam, "funky smbus addr %d\n", addr); | ||
467 | return -EINVAL; | ||
468 | } | ||
469 | /* | ||
470 | * This interface would appear to only do byte data ops. OK | ||
471 | * it can do word too, but the cam chip has no use for that. | ||
472 | */ | ||
473 | if (size != I2C_SMBUS_BYTE_DATA) { | ||
474 | cam_err(cam, "funky xfer size %d\n", size); | ||
475 | return -EINVAL; | ||
476 | } | ||
477 | |||
478 | if (rw == I2C_SMBUS_WRITE) | ||
479 | ret = cafe_smbus_write_data(cam, addr, command, data->byte); | ||
480 | else if (rw == I2C_SMBUS_READ) | ||
481 | ret = cafe_smbus_read_data(cam, addr, command, &data->byte); | ||
482 | return ret; | ||
483 | } | ||
484 | |||
485 | |||
486 | static void cafe_smbus_enable_irq(struct cafe_camera *cam) | ||
487 | { | ||
488 | unsigned long flags; | ||
489 | |||
490 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
491 | cafe_reg_set_bit(cam, REG_IRQMASK, TWSIIRQS); | ||
492 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
493 | } | ||
494 | |||
495 | static u32 cafe_smbus_func(struct i2c_adapter *adapter) | ||
496 | { | ||
497 | return I2C_FUNC_SMBUS_READ_BYTE_DATA | | ||
498 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA; | ||
499 | } | ||
500 | |||
501 | static struct i2c_algorithm cafe_smbus_algo = { | ||
502 | .smbus_xfer = cafe_smbus_xfer, | ||
503 | .functionality = cafe_smbus_func | ||
504 | }; | ||
505 | |||
506 | /* Somebody is on the bus */ | ||
507 | static int cafe_cam_init(struct cafe_camera *cam); | ||
508 | static void cafe_ctlr_stop_dma(struct cafe_camera *cam); | ||
509 | static void cafe_ctlr_power_down(struct cafe_camera *cam); | ||
510 | |||
511 | static int cafe_smbus_attach(struct i2c_client *client) | ||
512 | { | ||
513 | struct cafe_camera *cam = i2c_get_adapdata(client->adapter); | ||
514 | |||
515 | /* | ||
516 | * Don't talk to chips we don't recognize. | ||
517 | */ | ||
518 | if (client->driver->id == I2C_DRIVERID_OV7670) { | ||
519 | cam->sensor = client; | ||
520 | return cafe_cam_init(cam); | ||
521 | } | ||
522 | return -EINVAL; | ||
523 | } | ||
524 | |||
525 | static int cafe_smbus_detach(struct i2c_client *client) | ||
526 | { | ||
527 | struct cafe_camera *cam = i2c_get_adapdata(client->adapter); | ||
528 | |||
529 | if (cam->sensor == client) { | ||
530 | cafe_ctlr_stop_dma(cam); | ||
531 | cafe_ctlr_power_down(cam); | ||
532 | cam_err(cam, "lost the sensor!\n"); | ||
533 | cam->sensor = NULL; /* Bummer, no camera */ | ||
534 | cam->state = S_NOTREADY; | ||
535 | } | ||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | static int cafe_smbus_setup(struct cafe_camera *cam) | ||
540 | { | ||
541 | struct i2c_adapter *adap = &cam->i2c_adapter; | ||
542 | int ret; | ||
543 | |||
544 | cafe_smbus_enable_irq(cam); | ||
545 | adap->id = I2C_HW_SMBUS_CAFE; | ||
546 | adap->class = I2C_CLASS_CAM_DIGITAL; | ||
547 | adap->owner = THIS_MODULE; | ||
548 | adap->client_register = cafe_smbus_attach; | ||
549 | adap->client_unregister = cafe_smbus_detach; | ||
550 | adap->algo = &cafe_smbus_algo; | ||
551 | strcpy(adap->name, "cafe_ccic"); | ||
552 | i2c_set_adapdata(adap, cam); | ||
553 | ret = i2c_add_adapter(adap); | ||
554 | if (ret) | ||
555 | printk(KERN_ERR "Unable to register cafe i2c adapter\n"); | ||
556 | return ret; | ||
557 | } | ||
558 | |||
559 | static void cafe_smbus_shutdown(struct cafe_camera *cam) | ||
560 | { | ||
561 | i2c_del_adapter(&cam->i2c_adapter); | ||
562 | } | ||
563 | |||
564 | |||
565 | /* ------------------------------------------------------------------- */ | ||
566 | /* | ||
567 | * Deal with the controller. | ||
568 | */ | ||
569 | |||
570 | /* | ||
571 | * Do everything we think we need to have the interface operating | ||
572 | * according to the desired format. | ||
573 | */ | ||
574 | static void cafe_ctlr_dma(struct cafe_camera *cam) | ||
575 | { | ||
576 | /* | ||
577 | * Store the first two Y buffers (we aren't supporting | ||
578 | * planar formats for now, so no UV bufs). Then either | ||
579 | * set the third if it exists, or tell the controller | ||
580 | * to just use two. | ||
581 | */ | ||
582 | cafe_reg_write(cam, REG_Y0BAR, cam->dma_handles[0]); | ||
583 | cafe_reg_write(cam, REG_Y1BAR, cam->dma_handles[1]); | ||
584 | if (cam->nbufs > 2) { | ||
585 | cafe_reg_write(cam, REG_Y2BAR, cam->dma_handles[2]); | ||
586 | cafe_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS); | ||
587 | } | ||
588 | else | ||
589 | cafe_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS); | ||
590 | cafe_reg_write(cam, REG_UBAR, 0); /* 32 bits only for now */ | ||
591 | } | ||
592 | |||
593 | static void cafe_ctlr_image(struct cafe_camera *cam) | ||
594 | { | ||
595 | int imgsz; | ||
596 | struct v4l2_pix_format *fmt = &cam->pix_format; | ||
597 | |||
598 | imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) | | ||
599 | (fmt->bytesperline & IMGSZ_H_MASK); | ||
600 | cafe_reg_write(cam, REG_IMGSIZE, imgsz); | ||
601 | cafe_reg_write(cam, REG_IMGOFFSET, 0); | ||
602 | /* YPITCH just drops the last two bits */ | ||
603 | cafe_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline, | ||
604 | IMGP_YP_MASK); | ||
605 | /* | ||
606 | * Tell the controller about the image format we are using. | ||
607 | */ | ||
608 | switch (cam->pix_format.pixelformat) { | ||
609 | case V4L2_PIX_FMT_YUYV: | ||
610 | cafe_reg_write_mask(cam, REG_CTRL0, | ||
611 | C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV, | ||
612 | C0_DF_MASK); | ||
613 | break; | ||
614 | |||
615 | case V4L2_PIX_FMT_RGB444: | ||
616 | cafe_reg_write_mask(cam, REG_CTRL0, | ||
617 | C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB, | ||
618 | C0_DF_MASK); | ||
619 | /* Alpha value? */ | ||
620 | break; | ||
621 | |||
622 | case V4L2_PIX_FMT_RGB565: | ||
623 | cafe_reg_write_mask(cam, REG_CTRL0, | ||
624 | C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR, | ||
625 | C0_DF_MASK); | ||
626 | break; | ||
627 | |||
628 | default: | ||
629 | cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat); | ||
630 | break; | ||
631 | } | ||
632 | /* | ||
633 | * Make sure it knows we want to use hsync/vsync. | ||
634 | */ | ||
635 | cafe_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, | ||
636 | C0_SIFM_MASK); | ||
637 | } | ||
638 | |||
639 | |||
640 | /* | ||
641 | * Configure the controller for operation; caller holds the | ||
642 | * device mutex. | ||
643 | */ | ||
644 | static int cafe_ctlr_configure(struct cafe_camera *cam) | ||
645 | { | ||
646 | unsigned long flags; | ||
647 | |||
648 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
649 | cafe_ctlr_dma(cam); | ||
650 | cafe_ctlr_image(cam); | ||
651 | cafe_set_config_needed(cam, 0); | ||
652 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
653 | return 0; | ||
654 | } | ||
655 | |||
656 | static void cafe_ctlr_irq_enable(struct cafe_camera *cam) | ||
657 | { | ||
658 | /* | ||
659 | * Clear any pending interrupts, since we do not | ||
660 | * expect to have I/O active prior to enabling. | ||
661 | */ | ||
662 | cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); | ||
663 | cafe_reg_set_bit(cam, REG_IRQMASK, FRAMEIRQS); | ||
664 | } | ||
665 | |||
666 | static void cafe_ctlr_irq_disable(struct cafe_camera *cam) | ||
667 | { | ||
668 | cafe_reg_clear_bit(cam, REG_IRQMASK, FRAMEIRQS); | ||
669 | } | ||
670 | |||
671 | /* | ||
672 | * Make the controller start grabbing images. Everything must | ||
673 | * be set up before doing this. | ||
674 | */ | ||
675 | static void cafe_ctlr_start(struct cafe_camera *cam) | ||
676 | { | ||
677 | /* set_bit performs a read, so no other barrier should be | ||
678 | needed here */ | ||
679 | cafe_reg_set_bit(cam, REG_CTRL0, C0_ENABLE); | ||
680 | } | ||
681 | |||
682 | static void cafe_ctlr_stop(struct cafe_camera *cam) | ||
683 | { | ||
684 | cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); | ||
685 | } | ||
686 | |||
687 | static void cafe_ctlr_init(struct cafe_camera *cam) | ||
688 | { | ||
689 | unsigned long flags; | ||
690 | |||
691 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
692 | /* | ||
693 | * Added magic to bring up the hardware on the B-Test board | ||
694 | */ | ||
695 | cafe_reg_write(cam, 0x3038, 0x8); | ||
696 | cafe_reg_write(cam, 0x315c, 0x80008); | ||
697 | /* | ||
698 | * Go through the dance needed to wake the device up. | ||
699 | * Note that these registers are global and shared | ||
700 | * with the NAND and SD devices. Interaction between the | ||
701 | * three still needs to be examined. | ||
702 | */ | ||
703 | cafe_reg_write(cam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */ | ||
704 | cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRC); | ||
705 | cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRS); | ||
706 | mdelay(5); /* FIXME revisit this */ | ||
707 | cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC); | ||
708 | cafe_reg_set_bit(cam, REG_GL_IMASK, GIMSK_CCIC_EN); | ||
709 | /* | ||
710 | * Make sure it's not powered down. | ||
711 | */ | ||
712 | cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); | ||
713 | /* | ||
714 | * Turn off the enable bit. It sure should be off anyway, | ||
715 | * but it's good to be sure. | ||
716 | */ | ||
717 | cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); | ||
718 | /* | ||
719 | * Mask all interrupts. | ||
720 | */ | ||
721 | cafe_reg_write(cam, REG_IRQMASK, 0); | ||
722 | /* | ||
723 | * Clock the sensor appropriately. Controller clock should | ||
724 | * be 48MHz, sensor "typical" value is half that. | ||
725 | */ | ||
726 | cafe_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK); | ||
727 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
728 | } | ||
729 | |||
730 | |||
731 | /* | ||
732 | * Stop the controller, and don't return until we're really sure that no | ||
733 | * further DMA is going on. | ||
734 | */ | ||
735 | static void cafe_ctlr_stop_dma(struct cafe_camera *cam) | ||
736 | { | ||
737 | unsigned long flags; | ||
738 | |||
739 | /* | ||
740 | * Theory: stop the camera controller (whether it is operating | ||
741 | * or not). Delay briefly just in case we race with the SOF | ||
742 | * interrupt, then wait until no DMA is active. | ||
743 | */ | ||
744 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
745 | cafe_ctlr_stop(cam); | ||
746 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
747 | mdelay(1); | ||
748 | wait_event_timeout(cam->iowait, | ||
749 | !test_bit(CF_DMA_ACTIVE, &cam->flags), HZ); | ||
750 | if (test_bit(CF_DMA_ACTIVE, &cam->flags)) | ||
751 | cam_err(cam, "Timeout waiting for DMA to end\n"); | ||
752 | /* This would be bad news - what now? */ | ||
753 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
754 | cam->state = S_IDLE; | ||
755 | cafe_ctlr_irq_disable(cam); | ||
756 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * Power up and down. | ||
761 | */ | ||
762 | static void cafe_ctlr_power_up(struct cafe_camera *cam) | ||
763 | { | ||
764 | unsigned long flags; | ||
765 | |||
766 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
767 | cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); | ||
768 | /* | ||
769 | * Put the sensor into operational mode (assumes OLPC-style | ||
770 | * wiring). Control 0 is reset - set to 1 to operate. | ||
771 | * Control 1 is power down, set to 0 to operate. | ||
772 | */ | ||
773 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ | ||
774 | mdelay(1); /* Marvell says 1ms will do it */ | ||
775 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); | ||
776 | mdelay(1); /* Enough? */ | ||
777 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
778 | } | ||
779 | |||
780 | static void cafe_ctlr_power_down(struct cafe_camera *cam) | ||
781 | { | ||
782 | unsigned long flags; | ||
783 | |||
784 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
785 | cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1); | ||
786 | cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN); | ||
787 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
788 | } | ||
789 | |||
790 | /* -------------------------------------------------------------------- */ | ||
791 | /* | ||
792 | * Communications with the sensor. | ||
793 | */ | ||
794 | |||
795 | static int __cafe_cam_cmd(struct cafe_camera *cam, int cmd, void *arg) | ||
796 | { | ||
797 | struct i2c_client *sc = cam->sensor; | ||
798 | int ret; | ||
799 | |||
800 | if (sc == NULL || sc->driver == NULL || sc->driver->command == NULL) | ||
801 | return -EINVAL; | ||
802 | ret = sc->driver->command(sc, cmd, arg); | ||
803 | if (ret == -EPERM) /* Unsupported command */ | ||
804 | return 0; | ||
805 | return ret; | ||
806 | } | ||
807 | |||
808 | static int __cafe_cam_reset(struct cafe_camera *cam) | ||
809 | { | ||
810 | int zero = 0; | ||
811 | return __cafe_cam_cmd(cam, VIDIOC_INT_RESET, &zero); | ||
812 | } | ||
813 | |||
814 | /* | ||
815 | * We have found the sensor on the i2c. Let's try to have a | ||
816 | * conversation. | ||
817 | */ | ||
818 | static int cafe_cam_init(struct cafe_camera *cam) | ||
819 | { | ||
820 | int ret; | ||
821 | |||
822 | mutex_lock(&cam->s_mutex); | ||
823 | if (cam->state != S_NOTREADY) | ||
824 | cam_warn(cam, "Cam init with device in funky state %d", | ||
825 | cam->state); | ||
826 | ret = __cafe_cam_reset(cam); | ||
827 | if (ret) | ||
828 | goto out; | ||
829 | ret = __cafe_cam_cmd(cam, VIDIOC_INT_G_CHIP_IDENT, &cam->sensor_type); | ||
830 | if (ret) | ||
831 | goto out; | ||
832 | // if (cam->sensor->addr != OV7xx0_SID) { | ||
833 | if (cam->sensor_type != V4L2_IDENT_OV7670) { | ||
834 | cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr); | ||
835 | ret = -EINVAL; | ||
836 | goto out; | ||
837 | } | ||
838 | /* Get/set parameters? */ | ||
839 | ret = 0; | ||
840 | cam->state = S_IDLE; | ||
841 | out: | ||
842 | mutex_unlock(&cam->s_mutex); | ||
843 | return ret; | ||
844 | } | ||
845 | |||
846 | /* | ||
847 | * Configure the sensor to match the parameters we have. Caller should | ||
848 | * hold s_mutex | ||
849 | */ | ||
850 | static int cafe_cam_set_flip(struct cafe_camera *cam) | ||
851 | { | ||
852 | struct v4l2_control ctrl; | ||
853 | |||
854 | memset(&ctrl, 0, sizeof(ctrl)); | ||
855 | ctrl.id = V4L2_CID_VFLIP; | ||
856 | ctrl.value = flip; | ||
857 | return __cafe_cam_cmd(cam, VIDIOC_S_CTRL, &ctrl); | ||
858 | } | ||
859 | |||
860 | |||
861 | static int cafe_cam_configure(struct cafe_camera *cam) | ||
862 | { | ||
863 | struct v4l2_format fmt; | ||
864 | int ret, zero = 0; | ||
865 | |||
866 | if (cam->state != S_IDLE) | ||
867 | return -EINVAL; | ||
868 | fmt.fmt.pix = cam->pix_format; | ||
869 | ret = __cafe_cam_cmd(cam, VIDIOC_INT_INIT, &zero); | ||
870 | if (ret == 0) | ||
871 | ret = __cafe_cam_cmd(cam, VIDIOC_S_FMT, &fmt); | ||
872 | /* | ||
873 | * OV7670 does weird things if flip is set *before* format... | ||
874 | */ | ||
875 | ret += cafe_cam_set_flip(cam); | ||
876 | return ret; | ||
877 | } | ||
878 | |||
879 | /* -------------------------------------------------------------------- */ | ||
880 | /* | ||
881 | * DMA buffer management. These functions need s_mutex held. | ||
882 | */ | ||
883 | |||
884 | /* FIXME: this is inefficient as hell, since dma_alloc_coherent just | ||
885 | * does a get_free_pages() call, and we waste a good chunk of an orderN | ||
886 | * allocation. Should try to allocate the whole set in one chunk. | ||
887 | */ | ||
888 | static int cafe_alloc_dma_bufs(struct cafe_camera *cam, int loadtime) | ||
889 | { | ||
890 | int i; | ||
891 | |||
892 | cafe_set_config_needed(cam, 1); | ||
893 | if (loadtime) | ||
894 | cam->dma_buf_size = dma_buf_size; | ||
895 | else | ||
896 | cam->dma_buf_size = cam->pix_format.sizeimage; | ||
897 | if (n_dma_bufs > 3) | ||
898 | n_dma_bufs = 3; | ||
899 | |||
900 | cam->nbufs = 0; | ||
901 | for (i = 0; i < n_dma_bufs; i++) { | ||
902 | cam->dma_bufs[i] = dma_alloc_coherent(&cam->pdev->dev, | ||
903 | cam->dma_buf_size, cam->dma_handles + i, | ||
904 | GFP_KERNEL); | ||
905 | if (cam->dma_bufs[i] == NULL) { | ||
906 | cam_warn(cam, "Failed to allocate DMA buffer\n"); | ||
907 | break; | ||
908 | } | ||
909 | /* For debug, remove eventually */ | ||
910 | memset(cam->dma_bufs[i], 0xcc, cam->dma_buf_size); | ||
911 | (cam->nbufs)++; | ||
912 | } | ||
913 | |||
914 | switch (cam->nbufs) { | ||
915 | case 1: | ||
916 | dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size, | ||
917 | cam->dma_bufs[0], cam->dma_handles[0]); | ||
918 | cam->nbufs = 0; | ||
919 | case 0: | ||
920 | cam_err(cam, "Insufficient DMA buffers, cannot operate\n"); | ||
921 | return -ENOMEM; | ||
922 | |||
923 | case 2: | ||
924 | if (n_dma_bufs > 2) | ||
925 | cam_warn(cam, "Will limp along with only 2 buffers\n"); | ||
926 | break; | ||
927 | } | ||
928 | return 0; | ||
929 | } | ||
930 | |||
931 | static void cafe_free_dma_bufs(struct cafe_camera *cam) | ||
932 | { | ||
933 | int i; | ||
934 | |||
935 | for (i = 0; i < cam->nbufs; i++) { | ||
936 | dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size, | ||
937 | cam->dma_bufs[i], cam->dma_handles[i]); | ||
938 | cam->dma_bufs[i] = NULL; | ||
939 | } | ||
940 | cam->nbufs = 0; | ||
941 | } | ||
942 | |||
943 | |||
944 | |||
945 | |||
946 | |||
947 | /* ----------------------------------------------------------------------- */ | ||
948 | /* | ||
949 | * Here starts the V4L2 interface code. | ||
950 | */ | ||
951 | |||
952 | /* | ||
953 | * Read an image from the device. | ||
954 | */ | ||
955 | static ssize_t cafe_deliver_buffer(struct cafe_camera *cam, | ||
956 | char __user *buffer, size_t len, loff_t *pos) | ||
957 | { | ||
958 | int bufno; | ||
959 | unsigned long flags; | ||
960 | |||
961 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
962 | if (cam->next_buf < 0) { | ||
963 | cam_err(cam, "deliver_buffer: No next buffer\n"); | ||
964 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
965 | return -EIO; | ||
966 | } | ||
967 | bufno = cam->next_buf; | ||
968 | clear_bit(bufno, &cam->flags); | ||
969 | if (++(cam->next_buf) >= cam->nbufs) | ||
970 | cam->next_buf = 0; | ||
971 | if (! test_bit(cam->next_buf, &cam->flags)) | ||
972 | cam->next_buf = -1; | ||
973 | cam->specframes = 0; | ||
974 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
975 | |||
976 | if (len > cam->pix_format.sizeimage) | ||
977 | len = cam->pix_format.sizeimage; | ||
978 | if (copy_to_user(buffer, cam->dma_bufs[bufno], len)) | ||
979 | return -EFAULT; | ||
980 | (*pos) += len; | ||
981 | return len; | ||
982 | } | ||
983 | |||
984 | /* | ||
985 | * Get everything ready, and start grabbing frames. | ||
986 | */ | ||
987 | static int cafe_read_setup(struct cafe_camera *cam, enum cafe_state state) | ||
988 | { | ||
989 | int ret; | ||
990 | unsigned long flags; | ||
991 | |||
992 | /* | ||
993 | * Configuration. If we still don't have DMA buffers, | ||
994 | * make one last, desperate attempt. | ||
995 | */ | ||
996 | if (cam->nbufs == 0) | ||
997 | if (cafe_alloc_dma_bufs(cam, 0)) | ||
998 | return -ENOMEM; | ||
999 | |||
1000 | if (cafe_needs_config(cam)) { | ||
1001 | cafe_cam_configure(cam); | ||
1002 | ret = cafe_ctlr_configure(cam); | ||
1003 | if (ret) | ||
1004 | return ret; | ||
1005 | } | ||
1006 | |||
1007 | /* | ||
1008 | * Turn it loose. | ||
1009 | */ | ||
1010 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
1011 | cafe_reset_buffers(cam); | ||
1012 | cafe_ctlr_irq_enable(cam); | ||
1013 | cam->state = state; | ||
1014 | cafe_ctlr_start(cam); | ||
1015 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
1016 | return 0; | ||
1017 | } | ||
1018 | |||
1019 | |||
1020 | static ssize_t cafe_v4l_read(struct file *filp, | ||
1021 | char __user *buffer, size_t len, loff_t *pos) | ||
1022 | { | ||
1023 | struct cafe_camera *cam = filp->private_data; | ||
1024 | int ret; | ||
1025 | |||
1026 | /* | ||
1027 | * Perhaps we're in speculative read mode and already | ||
1028 | * have data? | ||
1029 | */ | ||
1030 | mutex_lock(&cam->s_mutex); | ||
1031 | if (cam->state == S_SPECREAD) { | ||
1032 | if (cam->next_buf >= 0) { | ||
1033 | ret = cafe_deliver_buffer(cam, buffer, len, pos); | ||
1034 | if (ret != 0) | ||
1035 | goto out_unlock; | ||
1036 | } | ||
1037 | } else if (cam->state == S_FLAKED || cam->state == S_NOTREADY) { | ||
1038 | ret = -EIO; | ||
1039 | goto out_unlock; | ||
1040 | } else if (cam->state != S_IDLE) { | ||
1041 | ret = -EBUSY; | ||
1042 | goto out_unlock; | ||
1043 | } | ||
1044 | |||
1045 | /* | ||
1046 | * v4l2: multiple processes can open the device, but only | ||
1047 | * one gets to grab data from it. | ||
1048 | */ | ||
1049 | if (cam->owner && cam->owner != filp) { | ||
1050 | ret = -EBUSY; | ||
1051 | goto out_unlock; | ||
1052 | } | ||
1053 | cam->owner = filp; | ||
1054 | |||
1055 | /* | ||
1056 | * Do setup if need be. | ||
1057 | */ | ||
1058 | if (cam->state != S_SPECREAD) { | ||
1059 | ret = cafe_read_setup(cam, S_SINGLEREAD); | ||
1060 | if (ret) | ||
1061 | goto out_unlock; | ||
1062 | } | ||
1063 | /* | ||
1064 | * Wait for something to happen. This should probably | ||
1065 | * be interruptible (FIXME). | ||
1066 | */ | ||
1067 | wait_event_timeout(cam->iowait, cam->next_buf >= 0, HZ); | ||
1068 | if (cam->next_buf < 0) { | ||
1069 | cam_err(cam, "read() operation timed out\n"); | ||
1070 | cafe_ctlr_stop_dma(cam); | ||
1071 | ret = -EIO; | ||
1072 | goto out_unlock; | ||
1073 | } | ||
1074 | /* | ||
1075 | * Give them their data and we should be done. | ||
1076 | */ | ||
1077 | ret = cafe_deliver_buffer(cam, buffer, len, pos); | ||
1078 | |||
1079 | out_unlock: | ||
1080 | mutex_unlock(&cam->s_mutex); | ||
1081 | return ret; | ||
1082 | } | ||
1083 | |||
1084 | |||
1085 | |||
1086 | |||
1087 | |||
1088 | |||
1089 | |||
1090 | |||
1091 | /* | ||
1092 | * Streaming I/O support. | ||
1093 | */ | ||
1094 | |||
1095 | |||
1096 | |||
1097 | static int cafe_vidioc_streamon(struct file *filp, void *priv, | ||
1098 | enum v4l2_buf_type type) | ||
1099 | { | ||
1100 | struct cafe_camera *cam = filp->private_data; | ||
1101 | int ret = -EINVAL; | ||
1102 | |||
1103 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1104 | goto out; | ||
1105 | mutex_lock(&cam->s_mutex); | ||
1106 | if (cam->state != S_IDLE || cam->n_sbufs == 0) | ||
1107 | goto out_unlock; | ||
1108 | |||
1109 | cam->sequence = 0; | ||
1110 | ret = cafe_read_setup(cam, S_STREAMING); | ||
1111 | |||
1112 | out_unlock: | ||
1113 | mutex_unlock(&cam->s_mutex); | ||
1114 | out: | ||
1115 | return ret; | ||
1116 | } | ||
1117 | |||
1118 | |||
1119 | static int cafe_vidioc_streamoff(struct file *filp, void *priv, | ||
1120 | enum v4l2_buf_type type) | ||
1121 | { | ||
1122 | struct cafe_camera *cam = filp->private_data; | ||
1123 | int ret = -EINVAL; | ||
1124 | |||
1125 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1126 | goto out; | ||
1127 | mutex_lock(&cam->s_mutex); | ||
1128 | if (cam->state != S_STREAMING) | ||
1129 | goto out_unlock; | ||
1130 | |||
1131 | cafe_ctlr_stop_dma(cam); | ||
1132 | ret = 0; | ||
1133 | |||
1134 | out_unlock: | ||
1135 | mutex_unlock(&cam->s_mutex); | ||
1136 | out: | ||
1137 | return ret; | ||
1138 | } | ||
1139 | |||
1140 | |||
1141 | |||
1142 | static int cafe_setup_siobuf(struct cafe_camera *cam, int index) | ||
1143 | { | ||
1144 | struct cafe_sio_buffer *buf = cam->sb_bufs + index; | ||
1145 | |||
1146 | INIT_LIST_HEAD(&buf->list); | ||
1147 | buf->v4lbuf.length = PAGE_ALIGN(cam->pix_format.sizeimage); | ||
1148 | buf->buffer = vmalloc_user(buf->v4lbuf.length); | ||
1149 | if (buf->buffer == NULL) | ||
1150 | return -ENOMEM; | ||
1151 | buf->mapcount = 0; | ||
1152 | buf->cam = cam; | ||
1153 | |||
1154 | buf->v4lbuf.index = index; | ||
1155 | buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1156 | buf->v4lbuf.field = V4L2_FIELD_NONE; | ||
1157 | buf->v4lbuf.memory = V4L2_MEMORY_MMAP; | ||
1158 | /* | ||
1159 | * Offset: must be 32-bit even on a 64-bit system. video-buf | ||
1160 | * just uses the length times the index, but the spec warns | ||
1161 | * against doing just that - vma merging problems. So we | ||
1162 | * leave a gap between each pair of buffers. | ||
1163 | */ | ||
1164 | buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length; | ||
1165 | return 0; | ||
1166 | } | ||
1167 | |||
1168 | static int cafe_free_sio_buffers(struct cafe_camera *cam) | ||
1169 | { | ||
1170 | int i; | ||
1171 | |||
1172 | /* | ||
1173 | * If any buffers are mapped, we cannot free them at all. | ||
1174 | */ | ||
1175 | for (i = 0; i < cam->n_sbufs; i++) | ||
1176 | if (cam->sb_bufs[i].mapcount > 0) | ||
1177 | return -EBUSY; | ||
1178 | /* | ||
1179 | * OK, let's do it. | ||
1180 | */ | ||
1181 | for (i = 0; i < cam->n_sbufs; i++) | ||
1182 | vfree(cam->sb_bufs[i].buffer); | ||
1183 | cam->n_sbufs = 0; | ||
1184 | kfree(cam->sb_bufs); | ||
1185 | cam->sb_bufs = NULL; | ||
1186 | INIT_LIST_HEAD(&cam->sb_avail); | ||
1187 | INIT_LIST_HEAD(&cam->sb_full); | ||
1188 | return 0; | ||
1189 | } | ||
1190 | |||
1191 | |||
1192 | |||
1193 | static int cafe_vidioc_reqbufs(struct file *filp, void *priv, | ||
1194 | struct v4l2_requestbuffers *req) | ||
1195 | { | ||
1196 | struct cafe_camera *cam = filp->private_data; | ||
1197 | int ret; | ||
1198 | |||
1199 | /* | ||
1200 | * Make sure it's something we can do. User pointers could be | ||
1201 | * implemented without great pain, but that's not been done yet. | ||
1202 | */ | ||
1203 | if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1204 | return -EINVAL; | ||
1205 | if (req->memory != V4L2_MEMORY_MMAP) | ||
1206 | return -EINVAL; | ||
1207 | /* | ||
1208 | * If they ask for zero buffers, they really want us to stop streaming | ||
1209 | * (if it's happening) and free everything. Should we check owner? | ||
1210 | */ | ||
1211 | mutex_lock(&cam->s_mutex); | ||
1212 | if (req->count == 0) { | ||
1213 | if (cam->state == S_STREAMING) | ||
1214 | cafe_ctlr_stop_dma(cam); | ||
1215 | ret = cafe_free_sio_buffers (cam); | ||
1216 | goto out; | ||
1217 | } | ||
1218 | /* | ||
1219 | * Device needs to be idle and working. We *could* try to do the | ||
1220 | * right thing in S_SPECREAD by shutting things down, but it | ||
1221 | * probably doesn't matter. | ||
1222 | */ | ||
1223 | if (cam->state != S_IDLE || (cam->owner && cam->owner != filp)) { | ||
1224 | ret = -EBUSY; | ||
1225 | goto out; | ||
1226 | } | ||
1227 | cam->owner = filp; | ||
1228 | |||
1229 | if (req->count < min_buffers) | ||
1230 | req->count = min_buffers; | ||
1231 | else if (req->count > max_buffers) | ||
1232 | req->count = max_buffers; | ||
1233 | if (cam->n_sbufs > 0) { | ||
1234 | ret = cafe_free_sio_buffers(cam); | ||
1235 | if (ret) | ||
1236 | goto out; | ||
1237 | } | ||
1238 | |||
1239 | cam->sb_bufs = kzalloc(req->count*sizeof(struct cafe_sio_buffer), | ||
1240 | GFP_KERNEL); | ||
1241 | if (cam->sb_bufs == NULL) { | ||
1242 | ret = -ENOMEM; | ||
1243 | goto out; | ||
1244 | } | ||
1245 | for (cam->n_sbufs = 0; cam->n_sbufs < req->count; (cam->n_sbufs++)) { | ||
1246 | ret = cafe_setup_siobuf(cam, cam->n_sbufs); | ||
1247 | if (ret) | ||
1248 | break; | ||
1249 | } | ||
1250 | |||
1251 | if (cam->n_sbufs == 0) /* no luck at all - ret already set */ | ||
1252 | kfree(cam->sb_bufs); | ||
1253 | else | ||
1254 | ret = 0; | ||
1255 | req->count = cam->n_sbufs; /* In case of partial success */ | ||
1256 | |||
1257 | out: | ||
1258 | mutex_unlock(&cam->s_mutex); | ||
1259 | return ret; | ||
1260 | } | ||
1261 | |||
1262 | |||
1263 | static int cafe_vidioc_querybuf(struct file *filp, void *priv, | ||
1264 | struct v4l2_buffer *buf) | ||
1265 | { | ||
1266 | struct cafe_camera *cam = filp->private_data; | ||
1267 | int ret = -EINVAL; | ||
1268 | |||
1269 | mutex_lock(&cam->s_mutex); | ||
1270 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1271 | goto out; | ||
1272 | if (buf->index < 0 || buf->index >= cam->n_sbufs) | ||
1273 | goto out; | ||
1274 | *buf = cam->sb_bufs[buf->index].v4lbuf; | ||
1275 | ret = 0; | ||
1276 | out: | ||
1277 | mutex_unlock(&cam->s_mutex); | ||
1278 | return ret; | ||
1279 | } | ||
1280 | |||
1281 | static int cafe_vidioc_qbuf(struct file *filp, void *priv, | ||
1282 | struct v4l2_buffer *buf) | ||
1283 | { | ||
1284 | struct cafe_camera *cam = filp->private_data; | ||
1285 | struct cafe_sio_buffer *sbuf; | ||
1286 | int ret = -EINVAL; | ||
1287 | unsigned long flags; | ||
1288 | |||
1289 | mutex_lock(&cam->s_mutex); | ||
1290 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1291 | goto out; | ||
1292 | if (buf->index < 0 || buf->index >= cam->n_sbufs) | ||
1293 | goto out; | ||
1294 | sbuf = cam->sb_bufs + buf->index; | ||
1295 | if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) { | ||
1296 | ret = 0; /* Already queued?? */ | ||
1297 | goto out; | ||
1298 | } | ||
1299 | if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_DONE) { | ||
1300 | /* Spec doesn't say anything, seems appropriate tho */ | ||
1301 | ret = -EBUSY; | ||
1302 | goto out; | ||
1303 | } | ||
1304 | sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED; | ||
1305 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
1306 | list_add(&sbuf->list, &cam->sb_avail); | ||
1307 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
1308 | ret = 0; | ||
1309 | out: | ||
1310 | mutex_unlock(&cam->s_mutex); | ||
1311 | return ret; | ||
1312 | } | ||
1313 | |||
1314 | static int cafe_vidioc_dqbuf(struct file *filp, void *priv, | ||
1315 | struct v4l2_buffer *buf) | ||
1316 | { | ||
1317 | struct cafe_camera *cam = filp->private_data; | ||
1318 | struct cafe_sio_buffer *sbuf; | ||
1319 | int ret = -EINVAL; | ||
1320 | unsigned long flags; | ||
1321 | |||
1322 | mutex_lock(&cam->s_mutex); | ||
1323 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1324 | goto out_unlock; | ||
1325 | if (cam->state != S_STREAMING) | ||
1326 | goto out_unlock; | ||
1327 | if (list_empty(&cam->sb_full) && filp->f_flags & O_NONBLOCK) { | ||
1328 | ret = -EAGAIN; | ||
1329 | goto out_unlock; | ||
1330 | } | ||
1331 | |||
1332 | while (list_empty(&cam->sb_full) && cam->state == S_STREAMING) { | ||
1333 | mutex_unlock(&cam->s_mutex); | ||
1334 | if (wait_event_interruptible(cam->iowait, | ||
1335 | !list_empty(&cam->sb_full))) { | ||
1336 | ret = -ERESTARTSYS; | ||
1337 | goto out; | ||
1338 | } | ||
1339 | mutex_lock(&cam->s_mutex); | ||
1340 | } | ||
1341 | |||
1342 | if (cam->state != S_STREAMING) | ||
1343 | ret = -EINTR; | ||
1344 | else { | ||
1345 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
1346 | /* Should probably recheck !list_empty() here */ | ||
1347 | sbuf = list_entry(cam->sb_full.next, | ||
1348 | struct cafe_sio_buffer, list); | ||
1349 | list_del_init(&sbuf->list); | ||
1350 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
1351 | sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE; | ||
1352 | *buf = sbuf->v4lbuf; | ||
1353 | ret = 0; | ||
1354 | } | ||
1355 | |||
1356 | out_unlock: | ||
1357 | mutex_unlock(&cam->s_mutex); | ||
1358 | out: | ||
1359 | return ret; | ||
1360 | } | ||
1361 | |||
1362 | |||
1363 | |||
1364 | static void cafe_v4l_vm_open(struct vm_area_struct *vma) | ||
1365 | { | ||
1366 | struct cafe_sio_buffer *sbuf = vma->vm_private_data; | ||
1367 | /* | ||
1368 | * Locking: done under mmap_sem, so we don't need to | ||
1369 | * go back to the camera lock here. | ||
1370 | */ | ||
1371 | sbuf->mapcount++; | ||
1372 | } | ||
1373 | |||
1374 | |||
1375 | static void cafe_v4l_vm_close(struct vm_area_struct *vma) | ||
1376 | { | ||
1377 | struct cafe_sio_buffer *sbuf = vma->vm_private_data; | ||
1378 | |||
1379 | mutex_lock(&sbuf->cam->s_mutex); | ||
1380 | sbuf->mapcount--; | ||
1381 | /* Docs say we should stop I/O too... */ | ||
1382 | if (sbuf->mapcount == 0) | ||
1383 | sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED; | ||
1384 | mutex_unlock(&sbuf->cam->s_mutex); | ||
1385 | } | ||
1386 | |||
1387 | static struct vm_operations_struct cafe_v4l_vm_ops = { | ||
1388 | .open = cafe_v4l_vm_open, | ||
1389 | .close = cafe_v4l_vm_close | ||
1390 | }; | ||
1391 | |||
1392 | |||
1393 | static int cafe_v4l_mmap(struct file *filp, struct vm_area_struct *vma) | ||
1394 | { | ||
1395 | struct cafe_camera *cam = filp->private_data; | ||
1396 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
1397 | int ret = -EINVAL; | ||
1398 | int i; | ||
1399 | struct cafe_sio_buffer *sbuf = NULL; | ||
1400 | |||
1401 | if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED)) | ||
1402 | return -EINVAL; | ||
1403 | /* | ||
1404 | * Find the buffer they are looking for. | ||
1405 | */ | ||
1406 | mutex_lock(&cam->s_mutex); | ||
1407 | for (i = 0; i < cam->n_sbufs; i++) | ||
1408 | if (cam->sb_bufs[i].v4lbuf.m.offset == offset) { | ||
1409 | sbuf = cam->sb_bufs + i; | ||
1410 | break; | ||
1411 | } | ||
1412 | if (sbuf == NULL) | ||
1413 | goto out; | ||
1414 | |||
1415 | ret = remap_vmalloc_range(vma, sbuf->buffer, 0); | ||
1416 | if (ret) | ||
1417 | goto out; | ||
1418 | vma->vm_flags |= VM_DONTEXPAND; | ||
1419 | vma->vm_private_data = sbuf; | ||
1420 | vma->vm_ops = &cafe_v4l_vm_ops; | ||
1421 | sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED; | ||
1422 | cafe_v4l_vm_open(vma); | ||
1423 | ret = 0; | ||
1424 | out: | ||
1425 | mutex_unlock(&cam->s_mutex); | ||
1426 | return ret; | ||
1427 | } | ||
1428 | |||
1429 | |||
1430 | |||
1431 | static int cafe_v4l_open(struct inode *inode, struct file *filp) | ||
1432 | { | ||
1433 | struct cafe_camera *cam; | ||
1434 | |||
1435 | cam = cafe_find_dev(iminor(inode)); | ||
1436 | if (cam == NULL) | ||
1437 | return -ENODEV; | ||
1438 | filp->private_data = cam; | ||
1439 | |||
1440 | mutex_lock(&cam->s_mutex); | ||
1441 | if (cam->users == 0) { | ||
1442 | cafe_ctlr_power_up(cam); | ||
1443 | __cafe_cam_reset(cam); | ||
1444 | cafe_set_config_needed(cam, 1); | ||
1445 | /* FIXME make sure this is complete */ | ||
1446 | } | ||
1447 | (cam->users)++; | ||
1448 | mutex_unlock(&cam->s_mutex); | ||
1449 | return 0; | ||
1450 | } | ||
1451 | |||
1452 | |||
1453 | static int cafe_v4l_release(struct inode *inode, struct file *filp) | ||
1454 | { | ||
1455 | struct cafe_camera *cam = filp->private_data; | ||
1456 | |||
1457 | mutex_lock(&cam->s_mutex); | ||
1458 | (cam->users)--; | ||
1459 | if (filp == cam->owner) { | ||
1460 | cafe_ctlr_stop_dma(cam); | ||
1461 | cafe_free_sio_buffers(cam); | ||
1462 | cam->owner = NULL; | ||
1463 | } | ||
1464 | if (cam->users == 0) { | ||
1465 | cafe_ctlr_power_down(cam); | ||
1466 | if (! alloc_bufs_at_load) | ||
1467 | cafe_free_dma_bufs(cam); | ||
1468 | } | ||
1469 | mutex_unlock(&cam->s_mutex); | ||
1470 | return 0; | ||
1471 | } | ||
1472 | |||
1473 | |||
1474 | |||
1475 | static unsigned int cafe_v4l_poll(struct file *filp, | ||
1476 | struct poll_table_struct *pt) | ||
1477 | { | ||
1478 | struct cafe_camera *cam = filp->private_data; | ||
1479 | |||
1480 | poll_wait(filp, &cam->iowait, pt); | ||
1481 | if (cam->next_buf >= 0) | ||
1482 | return POLLIN | POLLRDNORM; | ||
1483 | return 0; | ||
1484 | } | ||
1485 | |||
1486 | |||
1487 | |||
1488 | static int cafe_vidioc_queryctrl(struct file *filp, void *priv, | ||
1489 | struct v4l2_queryctrl *qc) | ||
1490 | { | ||
1491 | struct cafe_camera *cam = filp->private_data; | ||
1492 | int ret; | ||
1493 | |||
1494 | mutex_lock(&cam->s_mutex); | ||
1495 | ret = __cafe_cam_cmd(cam, VIDIOC_QUERYCTRL, qc); | ||
1496 | mutex_unlock(&cam->s_mutex); | ||
1497 | return ret; | ||
1498 | } | ||
1499 | |||
1500 | |||
1501 | static int cafe_vidioc_g_ctrl(struct file *filp, void *priv, | ||
1502 | struct v4l2_control *ctrl) | ||
1503 | { | ||
1504 | struct cafe_camera *cam = filp->private_data; | ||
1505 | int ret; | ||
1506 | |||
1507 | mutex_lock(&cam->s_mutex); | ||
1508 | ret = __cafe_cam_cmd(cam, VIDIOC_G_CTRL, ctrl); | ||
1509 | mutex_unlock(&cam->s_mutex); | ||
1510 | return ret; | ||
1511 | } | ||
1512 | |||
1513 | |||
1514 | static int cafe_vidioc_s_ctrl(struct file *filp, void *priv, | ||
1515 | struct v4l2_control *ctrl) | ||
1516 | { | ||
1517 | struct cafe_camera *cam = filp->private_data; | ||
1518 | int ret; | ||
1519 | |||
1520 | mutex_lock(&cam->s_mutex); | ||
1521 | ret = __cafe_cam_cmd(cam, VIDIOC_S_CTRL, ctrl); | ||
1522 | mutex_unlock(&cam->s_mutex); | ||
1523 | return ret; | ||
1524 | } | ||
1525 | |||
1526 | |||
1527 | |||
1528 | |||
1529 | |||
1530 | static int cafe_vidioc_querycap(struct file *file, void *priv, | ||
1531 | struct v4l2_capability *cap) | ||
1532 | { | ||
1533 | strcpy(cap->driver, "cafe_ccic"); | ||
1534 | strcpy(cap->card, "cafe_ccic"); | ||
1535 | cap->version = CAFE_VERSION; | ||
1536 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
1537 | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; | ||
1538 | return 0; | ||
1539 | } | ||
1540 | |||
1541 | |||
1542 | /* | ||
1543 | * The default format we use until somebody says otherwise. | ||
1544 | */ | ||
1545 | static struct v4l2_pix_format cafe_def_pix_format = { | ||
1546 | .width = VGA_WIDTH, | ||
1547 | .height = VGA_HEIGHT, | ||
1548 | .pixelformat = V4L2_PIX_FMT_YUYV, | ||
1549 | .field = V4L2_FIELD_NONE, | ||
1550 | .bytesperline = VGA_WIDTH*2, | ||
1551 | .sizeimage = VGA_WIDTH*VGA_HEIGHT*2, | ||
1552 | }; | ||
1553 | |||
1554 | static int cafe_vidioc_enum_fmt_cap(struct file *filp, | ||
1555 | void *priv, struct v4l2_fmtdesc *fmt) | ||
1556 | { | ||
1557 | struct cafe_camera *cam = priv; | ||
1558 | int ret; | ||
1559 | |||
1560 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1561 | return -EINVAL; | ||
1562 | mutex_lock(&cam->s_mutex); | ||
1563 | ret = __cafe_cam_cmd(cam, VIDIOC_ENUM_FMT, fmt); | ||
1564 | mutex_unlock(&cam->s_mutex); | ||
1565 | return ret; | ||
1566 | } | ||
1567 | |||
1568 | |||
1569 | static int cafe_vidioc_try_fmt_cap (struct file *filp, void *priv, | ||
1570 | struct v4l2_format *fmt) | ||
1571 | { | ||
1572 | struct cafe_camera *cam = priv; | ||
1573 | int ret; | ||
1574 | |||
1575 | mutex_lock(&cam->s_mutex); | ||
1576 | ret = __cafe_cam_cmd(cam, VIDIOC_TRY_FMT, fmt); | ||
1577 | mutex_unlock(&cam->s_mutex); | ||
1578 | return ret; | ||
1579 | } | ||
1580 | |||
1581 | static int cafe_vidioc_s_fmt_cap(struct file *filp, void *priv, | ||
1582 | struct v4l2_format *fmt) | ||
1583 | { | ||
1584 | struct cafe_camera *cam = priv; | ||
1585 | int ret; | ||
1586 | |||
1587 | /* | ||
1588 | * Can't do anything if the device is not idle | ||
1589 | * Also can't if there are streaming buffers in place. | ||
1590 | */ | ||
1591 | if (cam->state != S_IDLE || cam->n_sbufs > 0) | ||
1592 | return -EBUSY; | ||
1593 | /* | ||
1594 | * See if the formatting works in principle. | ||
1595 | */ | ||
1596 | ret = cafe_vidioc_try_fmt_cap(filp, priv, fmt); | ||
1597 | if (ret) | ||
1598 | return ret; | ||
1599 | /* | ||
1600 | * Now we start to change things for real, so let's do it | ||
1601 | * under lock. | ||
1602 | */ | ||
1603 | mutex_lock(&cam->s_mutex); | ||
1604 | cam->pix_format = fmt->fmt.pix; | ||
1605 | /* | ||
1606 | * Make sure we have appropriate DMA buffers. | ||
1607 | */ | ||
1608 | ret = -ENOMEM; | ||
1609 | if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage) | ||
1610 | cafe_free_dma_bufs(cam); | ||
1611 | if (cam->nbufs == 0) { | ||
1612 | if (cafe_alloc_dma_bufs(cam, 0)) | ||
1613 | goto out; | ||
1614 | } | ||
1615 | /* | ||
1616 | * It looks like this might work, so let's program the sensor. | ||
1617 | */ | ||
1618 | ret = cafe_cam_configure(cam); | ||
1619 | if (! ret) | ||
1620 | ret = cafe_ctlr_configure(cam); | ||
1621 | out: | ||
1622 | mutex_unlock(&cam->s_mutex); | ||
1623 | return ret; | ||
1624 | } | ||
1625 | |||
1626 | /* | ||
1627 | * Return our stored notion of how the camera is/should be configured. | ||
1628 | * The V4l2 spec wants us to be smarter, and actually get this from | ||
1629 | * the camera (and not mess with it at open time). Someday. | ||
1630 | */ | ||
1631 | static int cafe_vidioc_g_fmt_cap(struct file *filp, void *priv, | ||
1632 | struct v4l2_format *f) | ||
1633 | { | ||
1634 | struct cafe_camera *cam = priv; | ||
1635 | |||
1636 | f->fmt.pix = cam->pix_format; | ||
1637 | return 0; | ||
1638 | } | ||
1639 | |||
1640 | /* | ||
1641 | * We only have one input - the sensor - so minimize the nonsense here. | ||
1642 | */ | ||
1643 | static int cafe_vidioc_enum_input(struct file *filp, void *priv, | ||
1644 | struct v4l2_input *input) | ||
1645 | { | ||
1646 | if (input->index != 0) | ||
1647 | return -EINVAL; | ||
1648 | |||
1649 | input->type = V4L2_INPUT_TYPE_CAMERA; | ||
1650 | input->std = V4L2_STD_ALL; /* Not sure what should go here */ | ||
1651 | strcpy(input->name, "Camera"); | ||
1652 | return 0; | ||
1653 | } | ||
1654 | |||
1655 | static int cafe_vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | ||
1656 | { | ||
1657 | *i = 0; | ||
1658 | return 0; | ||
1659 | } | ||
1660 | |||
1661 | static int cafe_vidioc_s_input(struct file *filp, void *priv, unsigned int i) | ||
1662 | { | ||
1663 | if (i != 0) | ||
1664 | return -EINVAL; | ||
1665 | return 0; | ||
1666 | } | ||
1667 | |||
1668 | /* from vivi.c */ | ||
1669 | static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a) | ||
1670 | { | ||
1671 | return 0; | ||
1672 | } | ||
1673 | |||
1674 | /* | ||
1675 | * G/S_PARM. Most of this is done by the sensor, but we are | ||
1676 | * the level which controls the number of read buffers. | ||
1677 | */ | ||
1678 | static int cafe_vidioc_g_parm(struct file *filp, void *priv, | ||
1679 | struct v4l2_streamparm *parms) | ||
1680 | { | ||
1681 | struct cafe_camera *cam = priv; | ||
1682 | int ret; | ||
1683 | |||
1684 | mutex_lock(&cam->s_mutex); | ||
1685 | ret = __cafe_cam_cmd(cam, VIDIOC_G_PARM, parms); | ||
1686 | mutex_unlock(&cam->s_mutex); | ||
1687 | parms->parm.capture.readbuffers = n_dma_bufs; | ||
1688 | return ret; | ||
1689 | } | ||
1690 | |||
1691 | static int cafe_vidioc_s_parm(struct file *filp, void *priv, | ||
1692 | struct v4l2_streamparm *parms) | ||
1693 | { | ||
1694 | struct cafe_camera *cam = priv; | ||
1695 | int ret; | ||
1696 | |||
1697 | mutex_lock(&cam->s_mutex); | ||
1698 | ret = __cafe_cam_cmd(cam, VIDIOC_S_PARM, parms); | ||
1699 | mutex_unlock(&cam->s_mutex); | ||
1700 | parms->parm.capture.readbuffers = n_dma_bufs; | ||
1701 | return ret; | ||
1702 | } | ||
1703 | |||
1704 | |||
1705 | static void cafe_v4l_dev_release(struct video_device *vd) | ||
1706 | { | ||
1707 | struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev); | ||
1708 | |||
1709 | kfree(cam); | ||
1710 | } | ||
1711 | |||
1712 | |||
1713 | /* | ||
1714 | * This template device holds all of those v4l2 methods; we | ||
1715 | * clone it for specific real devices. | ||
1716 | */ | ||
1717 | |||
1718 | static struct file_operations cafe_v4l_fops = { | ||
1719 | .owner = THIS_MODULE, | ||
1720 | .open = cafe_v4l_open, | ||
1721 | .release = cafe_v4l_release, | ||
1722 | .read = cafe_v4l_read, | ||
1723 | .poll = cafe_v4l_poll, | ||
1724 | .mmap = cafe_v4l_mmap, | ||
1725 | .ioctl = video_ioctl2, | ||
1726 | .llseek = no_llseek, | ||
1727 | }; | ||
1728 | |||
1729 | static struct video_device cafe_v4l_template = { | ||
1730 | .name = "cafe", | ||
1731 | .type = VFL_TYPE_GRABBER, | ||
1732 | .type2 = VID_TYPE_CAPTURE, | ||
1733 | .minor = -1, /* Get one dynamically */ | ||
1734 | .tvnorms = V4L2_STD_NTSC_M, | ||
1735 | .current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */ | ||
1736 | |||
1737 | .fops = &cafe_v4l_fops, | ||
1738 | .release = cafe_v4l_dev_release, | ||
1739 | |||
1740 | .vidioc_querycap = cafe_vidioc_querycap, | ||
1741 | .vidioc_enum_fmt_cap = cafe_vidioc_enum_fmt_cap, | ||
1742 | .vidioc_try_fmt_cap = cafe_vidioc_try_fmt_cap, | ||
1743 | .vidioc_s_fmt_cap = cafe_vidioc_s_fmt_cap, | ||
1744 | .vidioc_g_fmt_cap = cafe_vidioc_g_fmt_cap, | ||
1745 | .vidioc_enum_input = cafe_vidioc_enum_input, | ||
1746 | .vidioc_g_input = cafe_vidioc_g_input, | ||
1747 | .vidioc_s_input = cafe_vidioc_s_input, | ||
1748 | .vidioc_s_std = cafe_vidioc_s_std, | ||
1749 | .vidioc_reqbufs = cafe_vidioc_reqbufs, | ||
1750 | .vidioc_querybuf = cafe_vidioc_querybuf, | ||
1751 | .vidioc_qbuf = cafe_vidioc_qbuf, | ||
1752 | .vidioc_dqbuf = cafe_vidioc_dqbuf, | ||
1753 | .vidioc_streamon = cafe_vidioc_streamon, | ||
1754 | .vidioc_streamoff = cafe_vidioc_streamoff, | ||
1755 | .vidioc_queryctrl = cafe_vidioc_queryctrl, | ||
1756 | .vidioc_g_ctrl = cafe_vidioc_g_ctrl, | ||
1757 | .vidioc_s_ctrl = cafe_vidioc_s_ctrl, | ||
1758 | .vidioc_g_parm = cafe_vidioc_g_parm, | ||
1759 | .vidioc_s_parm = cafe_vidioc_s_parm, | ||
1760 | }; | ||
1761 | |||
1762 | |||
1763 | |||
1764 | |||
1765 | |||
1766 | |||
1767 | |||
1768 | /* ---------------------------------------------------------------------- */ | ||
1769 | /* | ||
1770 | * Interrupt handler stuff | ||
1771 | */ | ||
1772 | |||
1773 | |||
1774 | |||
1775 | static void cafe_frame_tasklet(unsigned long data) | ||
1776 | { | ||
1777 | struct cafe_camera *cam = (struct cafe_camera *) data; | ||
1778 | int i; | ||
1779 | unsigned long flags; | ||
1780 | struct cafe_sio_buffer *sbuf; | ||
1781 | |||
1782 | spin_lock_irqsave(&cam->dev_lock, flags); | ||
1783 | for (i = 0; i < cam->nbufs; i++) { | ||
1784 | int bufno = cam->next_buf; | ||
1785 | if (bufno < 0) { /* "will never happen" */ | ||
1786 | cam_err(cam, "No valid bufs in tasklet!\n"); | ||
1787 | break; | ||
1788 | } | ||
1789 | if (++(cam->next_buf) >= cam->nbufs) | ||
1790 | cam->next_buf = 0; | ||
1791 | if (! test_bit(bufno, &cam->flags)) | ||
1792 | continue; | ||
1793 | if (list_empty(&cam->sb_avail)) | ||
1794 | break; /* Leave it valid, hope for better later */ | ||
1795 | clear_bit(bufno, &cam->flags); | ||
1796 | /* | ||
1797 | * We could perhaps drop the spinlock during this | ||
1798 | * big copy. Something to consider. | ||
1799 | */ | ||
1800 | sbuf = list_entry(cam->sb_avail.next, | ||
1801 | struct cafe_sio_buffer, list); | ||
1802 | memcpy(sbuf->buffer, cam->dma_bufs[bufno], | ||
1803 | cam->pix_format.sizeimage); | ||
1804 | sbuf->v4lbuf.bytesused = cam->pix_format.sizeimage; | ||
1805 | sbuf->v4lbuf.sequence = cam->buf_seq[bufno]; | ||
1806 | sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED; | ||
1807 | sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE; | ||
1808 | list_move_tail(&sbuf->list, &cam->sb_full); | ||
1809 | } | ||
1810 | if (! list_empty(&cam->sb_full)) | ||
1811 | wake_up(&cam->iowait); | ||
1812 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
1813 | } | ||
1814 | |||
1815 | |||
1816 | |||
1817 | static void cafe_frame_complete(struct cafe_camera *cam, int frame) | ||
1818 | { | ||
1819 | /* | ||
1820 | * Basic frame housekeeping. | ||
1821 | */ | ||
1822 | if (test_bit(frame, &cam->flags) && printk_ratelimit()) | ||
1823 | cam_err(cam, "Frame overrun on %d, frames lost\n", frame); | ||
1824 | set_bit(frame, &cam->flags); | ||
1825 | clear_bit(CF_DMA_ACTIVE, &cam->flags); | ||
1826 | if (cam->next_buf < 0) | ||
1827 | cam->next_buf = frame; | ||
1828 | cam->buf_seq[frame] = ++(cam->sequence); | ||
1829 | |||
1830 | switch (cam->state) { | ||
1831 | /* | ||
1832 | * If in single read mode, try going speculative. | ||
1833 | */ | ||
1834 | case S_SINGLEREAD: | ||
1835 | cam->state = S_SPECREAD; | ||
1836 | cam->specframes = 0; | ||
1837 | wake_up(&cam->iowait); | ||
1838 | break; | ||
1839 | |||
1840 | /* | ||
1841 | * If we are already doing speculative reads, and nobody is | ||
1842 | * reading them, just stop. | ||
1843 | */ | ||
1844 | case S_SPECREAD: | ||
1845 | if (++(cam->specframes) >= cam->nbufs) { | ||
1846 | cafe_ctlr_stop(cam); | ||
1847 | cafe_ctlr_irq_disable(cam); | ||
1848 | cam->state = S_IDLE; | ||
1849 | } | ||
1850 | wake_up(&cam->iowait); | ||
1851 | break; | ||
1852 | /* | ||
1853 | * For the streaming case, we defer the real work to the | ||
1854 | * camera tasklet. | ||
1855 | * | ||
1856 | * FIXME: if the application is not consuming the buffers, | ||
1857 | * we should eventually put things on hold and restart in | ||
1858 | * vidioc_dqbuf(). | ||
1859 | */ | ||
1860 | case S_STREAMING: | ||
1861 | tasklet_schedule(&cam->s_tasklet); | ||
1862 | break; | ||
1863 | |||
1864 | default: | ||
1865 | cam_err(cam, "Frame interrupt in non-operational state\n"); | ||
1866 | break; | ||
1867 | } | ||
1868 | } | ||
1869 | |||
1870 | |||
1871 | |||
1872 | |||
1873 | static void cafe_frame_irq(struct cafe_camera *cam, unsigned int irqs) | ||
1874 | { | ||
1875 | unsigned int frame; | ||
1876 | |||
1877 | cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); /* Clear'em all */ | ||
1878 | /* | ||
1879 | * Handle any frame completions. There really should | ||
1880 | * not be more than one of these, or we have fallen | ||
1881 | * far behind. | ||
1882 | */ | ||
1883 | for (frame = 0; frame < cam->nbufs; frame++) | ||
1884 | if (irqs & (IRQ_EOF0 << frame)) | ||
1885 | cafe_frame_complete(cam, frame); | ||
1886 | /* | ||
1887 | * If a frame starts, note that we have DMA active. This | ||
1888 | * code assumes that we won't get multiple frame interrupts | ||
1889 | * at once; may want to rethink that. | ||
1890 | */ | ||
1891 | if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) | ||
1892 | set_bit(CF_DMA_ACTIVE, &cam->flags); | ||
1893 | } | ||
1894 | |||
1895 | |||
1896 | |||
1897 | static irqreturn_t cafe_irq(int irq, void *data) | ||
1898 | { | ||
1899 | struct cafe_camera *cam = data; | ||
1900 | unsigned int irqs; | ||
1901 | |||
1902 | spin_lock(&cam->dev_lock); | ||
1903 | irqs = cafe_reg_read(cam, REG_IRQSTAT); | ||
1904 | if ((irqs & ALLIRQS) == 0) { | ||
1905 | spin_unlock(&cam->dev_lock); | ||
1906 | return IRQ_NONE; | ||
1907 | } | ||
1908 | if (irqs & FRAMEIRQS) | ||
1909 | cafe_frame_irq(cam, irqs); | ||
1910 | if (irqs & TWSIIRQS) { | ||
1911 | cafe_reg_write(cam, REG_IRQSTAT, TWSIIRQS); | ||
1912 | wake_up(&cam->smbus_wait); | ||
1913 | } | ||
1914 | spin_unlock(&cam->dev_lock); | ||
1915 | return IRQ_HANDLED; | ||
1916 | } | ||
1917 | |||
1918 | |||
1919 | /* -------------------------------------------------------------------------- */ | ||
1920 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1921 | /* | ||
1922 | * Debugfs stuff. | ||
1923 | */ | ||
1924 | |||
1925 | static char cafe_debug_buf[1024]; | ||
1926 | static struct dentry *cafe_dfs_root; | ||
1927 | |||
1928 | static void cafe_dfs_setup(void) | ||
1929 | { | ||
1930 | cafe_dfs_root = debugfs_create_dir("cafe_ccic", NULL); | ||
1931 | if (IS_ERR(cafe_dfs_root)) { | ||
1932 | cafe_dfs_root = NULL; /* Never mind */ | ||
1933 | printk(KERN_NOTICE "cafe_ccic unable to set up debugfs\n"); | ||
1934 | } | ||
1935 | } | ||
1936 | |||
1937 | static void cafe_dfs_shutdown(void) | ||
1938 | { | ||
1939 | if (cafe_dfs_root) | ||
1940 | debugfs_remove(cafe_dfs_root); | ||
1941 | } | ||
1942 | |||
1943 | static int cafe_dfs_open(struct inode *inode, struct file *file) | ||
1944 | { | ||
1945 | file->private_data = inode->i_private; | ||
1946 | return 0; | ||
1947 | } | ||
1948 | |||
1949 | static ssize_t cafe_dfs_read_regs(struct file *file, | ||
1950 | char __user *buf, size_t count, loff_t *ppos) | ||
1951 | { | ||
1952 | struct cafe_camera *cam = file->private_data; | ||
1953 | char *s = cafe_debug_buf; | ||
1954 | int offset; | ||
1955 | |||
1956 | for (offset = 0; offset < 0x44; offset += 4) | ||
1957 | s += sprintf(s, "%02x: %08x\n", offset, | ||
1958 | cafe_reg_read(cam, offset)); | ||
1959 | for (offset = 0x88; offset <= 0x90; offset += 4) | ||
1960 | s += sprintf(s, "%02x: %08x\n", offset, | ||
1961 | cafe_reg_read(cam, offset)); | ||
1962 | for (offset = 0xb4; offset <= 0xbc; offset += 4) | ||
1963 | s += sprintf(s, "%02x: %08x\n", offset, | ||
1964 | cafe_reg_read(cam, offset)); | ||
1965 | for (offset = 0x3000; offset <= 0x300c; offset += 4) | ||
1966 | s += sprintf(s, "%04x: %08x\n", offset, | ||
1967 | cafe_reg_read(cam, offset)); | ||
1968 | return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, | ||
1969 | s - cafe_debug_buf); | ||
1970 | } | ||
1971 | |||
1972 | static struct file_operations cafe_dfs_reg_ops = { | ||
1973 | .owner = THIS_MODULE, | ||
1974 | .read = cafe_dfs_read_regs, | ||
1975 | .open = cafe_dfs_open | ||
1976 | }; | ||
1977 | |||
1978 | static ssize_t cafe_dfs_read_cam(struct file *file, | ||
1979 | char __user *buf, size_t count, loff_t *ppos) | ||
1980 | { | ||
1981 | struct cafe_camera *cam = file->private_data; | ||
1982 | char *s = cafe_debug_buf; | ||
1983 | int offset; | ||
1984 | |||
1985 | if (! cam->sensor) | ||
1986 | return -EINVAL; | ||
1987 | for (offset = 0x0; offset < 0x8a; offset++) | ||
1988 | { | ||
1989 | u8 v; | ||
1990 | |||
1991 | cafe_smbus_read_data(cam, cam->sensor->addr, offset, &v); | ||
1992 | s += sprintf(s, "%02x: %02x\n", offset, v); | ||
1993 | } | ||
1994 | return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, | ||
1995 | s - cafe_debug_buf); | ||
1996 | } | ||
1997 | |||
1998 | static struct file_operations cafe_dfs_cam_ops = { | ||
1999 | .owner = THIS_MODULE, | ||
2000 | .read = cafe_dfs_read_cam, | ||
2001 | .open = cafe_dfs_open | ||
2002 | }; | ||
2003 | |||
2004 | |||
2005 | |||
2006 | static void cafe_dfs_cam_setup(struct cafe_camera *cam) | ||
2007 | { | ||
2008 | char fname[40]; | ||
2009 | |||
2010 | if (!cafe_dfs_root) | ||
2011 | return; | ||
2012 | sprintf(fname, "regs-%d", cam->v4ldev.minor); | ||
2013 | cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, | ||
2014 | cam, &cafe_dfs_reg_ops); | ||
2015 | sprintf(fname, "cam-%d", cam->v4ldev.minor); | ||
2016 | cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, | ||
2017 | cam, &cafe_dfs_cam_ops); | ||
2018 | } | ||
2019 | |||
2020 | |||
2021 | static void cafe_dfs_cam_shutdown(struct cafe_camera *cam) | ||
2022 | { | ||
2023 | if (! IS_ERR(cam->dfs_regs)) | ||
2024 | debugfs_remove(cam->dfs_regs); | ||
2025 | if (! IS_ERR(cam->dfs_cam_regs)) | ||
2026 | debugfs_remove(cam->dfs_cam_regs); | ||
2027 | } | ||
2028 | |||
2029 | #else | ||
2030 | |||
2031 | #define cafe_dfs_setup() | ||
2032 | #define cafe_dfs_shutdown() | ||
2033 | #define cafe_dfs_cam_setup(cam) | ||
2034 | #define cafe_dfs_cam_shutdown(cam) | ||
2035 | #endif /* CONFIG_VIDEO_ADV_DEBUG */ | ||
2036 | |||
2037 | |||
2038 | |||
2039 | |||
2040 | /* ------------------------------------------------------------------------*/ | ||
2041 | /* | ||
2042 | * PCI interface stuff. | ||
2043 | */ | ||
2044 | |||
2045 | static int cafe_pci_probe(struct pci_dev *pdev, | ||
2046 | const struct pci_device_id *id) | ||
2047 | { | ||
2048 | int ret; | ||
2049 | u16 classword; | ||
2050 | struct cafe_camera *cam; | ||
2051 | /* | ||
2052 | * Make sure we have a camera here - we'll get calls for | ||
2053 | * the other cafe devices as well. | ||
2054 | */ | ||
2055 | pci_read_config_word(pdev, PCI_CLASS_DEVICE, &classword); | ||
2056 | if (classword != PCI_CLASS_MULTIMEDIA_VIDEO) | ||
2057 | return -ENODEV; | ||
2058 | /* | ||
2059 | * Start putting together one of our big camera structures. | ||
2060 | */ | ||
2061 | ret = -ENOMEM; | ||
2062 | cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL); | ||
2063 | if (cam == NULL) | ||
2064 | goto out; | ||
2065 | mutex_init(&cam->s_mutex); | ||
2066 | mutex_lock(&cam->s_mutex); | ||
2067 | spin_lock_init(&cam->dev_lock); | ||
2068 | cam->state = S_NOTREADY; | ||
2069 | cafe_set_config_needed(cam, 1); | ||
2070 | init_waitqueue_head(&cam->smbus_wait); | ||
2071 | init_waitqueue_head(&cam->iowait); | ||
2072 | cam->pdev = pdev; | ||
2073 | cam->pix_format = cafe_def_pix_format; | ||
2074 | INIT_LIST_HEAD(&cam->dev_list); | ||
2075 | INIT_LIST_HEAD(&cam->sb_avail); | ||
2076 | INIT_LIST_HEAD(&cam->sb_full); | ||
2077 | tasklet_init(&cam->s_tasklet, cafe_frame_tasklet, (unsigned long) cam); | ||
2078 | /* | ||
2079 | * Get set up on the PCI bus. | ||
2080 | */ | ||
2081 | ret = pci_enable_device(pdev); | ||
2082 | if (ret) | ||
2083 | goto out_free; | ||
2084 | pci_set_master(pdev); | ||
2085 | |||
2086 | ret = -EIO; | ||
2087 | cam->regs = pci_iomap(pdev, 0, 0); | ||
2088 | if (! cam->regs) { | ||
2089 | printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); | ||
2090 | goto out_free; | ||
2091 | } | ||
2092 | ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); | ||
2093 | if (ret) | ||
2094 | goto out_iounmap; | ||
2095 | cafe_ctlr_init(cam); | ||
2096 | cafe_ctlr_power_up(cam); | ||
2097 | /* | ||
2098 | * Set up I2C/SMBUS communications | ||
2099 | */ | ||
2100 | mutex_unlock(&cam->s_mutex); /* attach can deadlock */ | ||
2101 | ret = cafe_smbus_setup(cam); | ||
2102 | if (ret) | ||
2103 | goto out_freeirq; | ||
2104 | /* | ||
2105 | * Get the v4l2 setup done. | ||
2106 | */ | ||
2107 | mutex_lock(&cam->s_mutex); | ||
2108 | cam->v4ldev = cafe_v4l_template; | ||
2109 | cam->v4ldev.debug = 0; | ||
2110 | // cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG; | ||
2111 | ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1); | ||
2112 | if (ret) | ||
2113 | goto out_smbus; | ||
2114 | /* | ||
2115 | * If so requested, try to get our DMA buffers now. | ||
2116 | */ | ||
2117 | if (alloc_bufs_at_load) { | ||
2118 | if (cafe_alloc_dma_bufs(cam, 1)) | ||
2119 | cam_warn(cam, "Unable to alloc DMA buffers at load" | ||
2120 | " will try again later."); | ||
2121 | } | ||
2122 | |||
2123 | cafe_dfs_cam_setup(cam); | ||
2124 | mutex_unlock(&cam->s_mutex); | ||
2125 | cafe_add_dev(cam); | ||
2126 | return 0; | ||
2127 | |||
2128 | out_smbus: | ||
2129 | cafe_smbus_shutdown(cam); | ||
2130 | out_freeirq: | ||
2131 | cafe_ctlr_power_down(cam); | ||
2132 | free_irq(pdev->irq, cam); | ||
2133 | out_iounmap: | ||
2134 | pci_iounmap(pdev, cam->regs); | ||
2135 | out_free: | ||
2136 | kfree(cam); | ||
2137 | out: | ||
2138 | return ret; | ||
2139 | } | ||
2140 | |||
2141 | |||
2142 | /* | ||
2143 | * Shut down an initialized device | ||
2144 | */ | ||
2145 | static void cafe_shutdown(struct cafe_camera *cam) | ||
2146 | { | ||
2147 | /* FIXME: Make sure we take care of everything here */ | ||
2148 | cafe_dfs_cam_shutdown(cam); | ||
2149 | if (cam->n_sbufs > 0) | ||
2150 | /* What if they are still mapped? Shouldn't be, but... */ | ||
2151 | cafe_free_sio_buffers(cam); | ||
2152 | cafe_remove_dev(cam); | ||
2153 | cafe_ctlr_stop_dma(cam); | ||
2154 | cafe_ctlr_power_down(cam); | ||
2155 | cafe_smbus_shutdown(cam); | ||
2156 | cafe_free_dma_bufs(cam); | ||
2157 | free_irq(cam->pdev->irq, cam); | ||
2158 | pci_iounmap(cam->pdev, cam->regs); | ||
2159 | video_unregister_device(&cam->v4ldev); | ||
2160 | /* kfree(cam); done in v4l_release () */ | ||
2161 | } | ||
2162 | |||
2163 | |||
2164 | static void cafe_pci_remove(struct pci_dev *pdev) | ||
2165 | { | ||
2166 | struct cafe_camera *cam = cafe_find_by_pdev(pdev); | ||
2167 | |||
2168 | if (cam == NULL) { | ||
2169 | cam_warn(cam, "pci_remove on unknown pdev %p\n", pdev); | ||
2170 | return; | ||
2171 | } | ||
2172 | mutex_lock(&cam->s_mutex); | ||
2173 | if (cam->users > 0) | ||
2174 | cam_warn(cam, "Removing a device with users!\n"); | ||
2175 | cafe_shutdown(cam); | ||
2176 | /* No unlock - it no longer exists */ | ||
2177 | } | ||
2178 | |||
2179 | |||
2180 | |||
2181 | |||
2182 | static struct pci_device_id cafe_ids[] = { | ||
2183 | { PCI_DEVICE(0x1148, 0x4340) }, /* Temporary ID on devel board */ | ||
2184 | { PCI_DEVICE(0x11ab, 0x4100) }, /* Eventual real ID */ | ||
2185 | { PCI_DEVICE(0x11ab, 0x4102) }, /* Really eventual real ID */ | ||
2186 | { 0, } | ||
2187 | }; | ||
2188 | |||
2189 | MODULE_DEVICE_TABLE(pci, cafe_ids); | ||
2190 | |||
2191 | static struct pci_driver cafe_pci_driver = { | ||
2192 | .name = "cafe1000-ccic", | ||
2193 | .id_table = cafe_ids, | ||
2194 | .probe = cafe_pci_probe, | ||
2195 | .remove = cafe_pci_remove, | ||
2196 | }; | ||
2197 | |||
2198 | |||
2199 | |||
2200 | |||
2201 | static int __init cafe_init(void) | ||
2202 | { | ||
2203 | int ret; | ||
2204 | |||
2205 | printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n", | ||
2206 | CAFE_VERSION); | ||
2207 | cafe_dfs_setup(); | ||
2208 | ret = pci_register_driver(&cafe_pci_driver); | ||
2209 | if (ret) { | ||
2210 | printk(KERN_ERR "Unable to register cafe_ccic driver\n"); | ||
2211 | goto out; | ||
2212 | } | ||
2213 | request_module("ov7670"); /* FIXME want something more general */ | ||
2214 | ret = 0; | ||
2215 | |||
2216 | out: | ||
2217 | return ret; | ||
2218 | } | ||
2219 | |||
2220 | |||
2221 | static void __exit cafe_exit(void) | ||
2222 | { | ||
2223 | pci_unregister_driver(&cafe_pci_driver); | ||
2224 | cafe_dfs_shutdown(); | ||
2225 | } | ||
2226 | |||
2227 | module_init(cafe_init); | ||
2228 | module_exit(cafe_exit); | ||
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 0f9d96963618..b2a66ba625f9 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -53,6 +53,7 @@ config VIDEO_CX88_DVB | |||
53 | select DVB_OR51132 if !DVB_FE_CUSTOMISE | 53 | select DVB_OR51132 if !DVB_FE_CUSTOMISE |
54 | select DVB_CX22702 if !DVB_FE_CUSTOMISE | 54 | select DVB_CX22702 if !DVB_FE_CUSTOMISE |
55 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 55 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
56 | select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE | ||
56 | select DVB_NXT200X if !DVB_FE_CUSTOMISE | 57 | select DVB_NXT200X if !DVB_FE_CUSTOMISE |
57 | select DVB_CX24123 if !DVB_FE_CUSTOMISE | 58 | select DVB_CX24123 if !DVB_FE_CUSTOMISE |
58 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE | 59 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE |
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 46738321adaf..0cf0360588e6 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
@@ -50,7 +50,6 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); | |||
50 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 50 | #define dprintk(level,fmt, arg...) if (debug >= level) \ |
51 | printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg) | 51 | printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg) |
52 | 52 | ||
53 | static LIST_HEAD(cx8802_devlist); | ||
54 | 53 | ||
55 | /* ------------------------------------------------------------------ */ | 54 | /* ------------------------------------------------------------------ */ |
56 | 55 | ||
@@ -882,7 +881,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, | |||
882 | BLACKBIRD_MPEG_CAPTURE, | 881 | BLACKBIRD_MPEG_CAPTURE, |
883 | BLACKBIRD_RAW_BITS_NONE); | 882 | BLACKBIRD_RAW_BITS_NONE); |
884 | 883 | ||
885 | cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); | 884 | cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook); |
886 | 885 | ||
887 | blackbird_initialize_codec(dev); | 886 | blackbird_initialize_codec(dev); |
888 | cx88_set_scale(dev->core, dev->width, dev->height, | 887 | cx88_set_scale(dev->core, dev->width, dev->height, |
@@ -914,11 +913,15 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, | |||
914 | } | 913 | } |
915 | 914 | ||
916 | default: | 915 | default: |
917 | return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); | 916 | return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook); |
918 | } | 917 | } |
919 | return 0; | 918 | return 0; |
920 | } | 919 | } |
921 | 920 | ||
921 | int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, | ||
922 | unsigned int cmd, void *arg); | ||
923 | unsigned int (*cx88_ioctl_translator)(unsigned int cmd); | ||
924 | |||
922 | static unsigned int mpeg_translate_ioctl(unsigned int cmd) | 925 | static unsigned int mpeg_translate_ioctl(unsigned int cmd) |
923 | { | 926 | { |
924 | return cmd; | 927 | return cmd; |
@@ -927,33 +930,49 @@ static unsigned int mpeg_translate_ioctl(unsigned int cmd) | |||
927 | static int mpeg_ioctl(struct inode *inode, struct file *file, | 930 | static int mpeg_ioctl(struct inode *inode, struct file *file, |
928 | unsigned int cmd, unsigned long arg) | 931 | unsigned int cmd, unsigned long arg) |
929 | { | 932 | { |
930 | cmd = mpeg_translate_ioctl( cmd ); | 933 | cmd = cx88_ioctl_translator( cmd ); |
931 | return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl); | 934 | return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook); |
932 | } | 935 | } |
933 | 936 | ||
934 | static int mpeg_open(struct inode *inode, struct file *file) | 937 | static int mpeg_open(struct inode *inode, struct file *file) |
935 | { | 938 | { |
936 | int minor = iminor(inode); | 939 | int minor = iminor(inode); |
937 | struct cx8802_dev *h,*dev = NULL; | 940 | struct cx8802_dev *dev = NULL; |
938 | struct cx8802_fh *fh; | 941 | struct cx8802_fh *fh; |
939 | struct list_head *list; | 942 | struct cx8802_driver *drv = NULL; |
943 | int err; | ||
940 | 944 | ||
941 | list_for_each(list,&cx8802_devlist) { | 945 | dev = cx8802_get_device(inode); |
942 | h = list_entry(list, struct cx8802_dev, devlist); | 946 | |
943 | if (h->mpeg_dev->minor == minor) | 947 | dprintk( 1, "%s\n", __FUNCTION__); |
944 | dev = h; | 948 | |
945 | } | 949 | if (dev == NULL) |
946 | if (NULL == dev) | ||
947 | return -ENODEV; | 950 | return -ENODEV; |
948 | 951 | ||
949 | if (blackbird_initialize_codec(dev) < 0) | 952 | /* Make sure we can acquire the hardware */ |
953 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
954 | if (drv) { | ||
955 | err = drv->request_acquire(drv); | ||
956 | if(err != 0) { | ||
957 | dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err); | ||
958 | return err; | ||
959 | } | ||
960 | } | ||
961 | |||
962 | if (blackbird_initialize_codec(dev) < 0) { | ||
963 | if (drv) | ||
964 | drv->request_release(drv); | ||
950 | return -EINVAL; | 965 | return -EINVAL; |
966 | } | ||
951 | dprintk(1,"open minor=%d\n",minor); | 967 | dprintk(1,"open minor=%d\n",minor); |
952 | 968 | ||
953 | /* allocate + initialize per filehandle data */ | 969 | /* allocate + initialize per filehandle data */ |
954 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 970 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
955 | if (NULL == fh) | 971 | if (NULL == fh) { |
972 | if (drv) | ||
973 | drv->request_release(drv); | ||
956 | return -ENOMEM; | 974 | return -ENOMEM; |
975 | } | ||
957 | file->private_data = fh; | 976 | file->private_data = fh; |
958 | fh->dev = dev; | 977 | fh->dev = dev; |
959 | 978 | ||
@@ -974,6 +993,8 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
974 | static int mpeg_release(struct inode *inode, struct file *file) | 993 | static int mpeg_release(struct inode *inode, struct file *file) |
975 | { | 994 | { |
976 | struct cx8802_fh *fh = file->private_data; | 995 | struct cx8802_fh *fh = file->private_data; |
996 | struct cx8802_dev *dev = NULL; | ||
997 | struct cx8802_driver *drv = NULL; | ||
977 | 998 | ||
978 | /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ | 999 | /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ |
979 | blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, | 1000 | blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, |
@@ -992,6 +1013,16 @@ static int mpeg_release(struct inode *inode, struct file *file) | |||
992 | videobuf_mmap_free(&fh->mpegq); | 1013 | videobuf_mmap_free(&fh->mpegq); |
993 | file->private_data = NULL; | 1014 | file->private_data = NULL; |
994 | kfree(fh); | 1015 | kfree(fh); |
1016 | |||
1017 | /* Make sure we release the hardware */ | ||
1018 | dev = cx8802_get_device(inode); | ||
1019 | if (dev == NULL) | ||
1020 | return -ENODEV; | ||
1021 | |||
1022 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
1023 | if (drv) | ||
1024 | drv->request_release(drv); | ||
1025 | |||
995 | return 0; | 1026 | return 0; |
996 | } | 1027 | } |
997 | 1028 | ||
@@ -1043,6 +1074,44 @@ static struct video_device cx8802_mpeg_template = | |||
1043 | 1074 | ||
1044 | /* ------------------------------------------------------------------ */ | 1075 | /* ------------------------------------------------------------------ */ |
1045 | 1076 | ||
1077 | /* The CX8802 MPEG API will call this when we can use the hardware */ | ||
1078 | static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv) | ||
1079 | { | ||
1080 | struct cx88_core *core = drv->core; | ||
1081 | int err = 0; | ||
1082 | |||
1083 | switch (core->board) { | ||
1084 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
1085 | /* By default, core setup will leave the cx22702 out of reset, on the bus. | ||
1086 | * We left the hardware on power up with the cx22702 active. | ||
1087 | * We're being given access to re-arrange the GPIOs. | ||
1088 | * Take the bus off the cx22702 and put the cx23416 on it. | ||
1089 | */ | ||
1090 | cx_clear(MO_GP0_IO, 0x00000080); /* cx22702 in reset */ | ||
1091 | cx_set(MO_GP0_IO, 0x00000004); /* Disable the cx22702 */ | ||
1092 | break; | ||
1093 | default: | ||
1094 | err = -ENODEV; | ||
1095 | } | ||
1096 | return err; | ||
1097 | } | ||
1098 | |||
1099 | /* The CX8802 MPEG API will call this when we need to release the hardware */ | ||
1100 | static int cx8802_blackbird_advise_release(struct cx8802_driver *drv) | ||
1101 | { | ||
1102 | struct cx88_core *core = drv->core; | ||
1103 | int err = 0; | ||
1104 | |||
1105 | switch (core->board) { | ||
1106 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
1107 | /* Exit leaving the cx23416 on the bus */ | ||
1108 | break; | ||
1109 | default: | ||
1110 | err = -ENODEV; | ||
1111 | } | ||
1112 | return err; | ||
1113 | } | ||
1114 | |||
1046 | static void blackbird_unregister_video(struct cx8802_dev *dev) | 1115 | static void blackbird_unregister_video(struct cx8802_dev *dev) |
1047 | { | 1116 | { |
1048 | if (dev->mpeg_dev) { | 1117 | if (dev->mpeg_dev) { |
@@ -1073,28 +1142,23 @@ static int blackbird_register_video(struct cx8802_dev *dev) | |||
1073 | 1142 | ||
1074 | /* ----------------------------------------------------------- */ | 1143 | /* ----------------------------------------------------------- */ |
1075 | 1144 | ||
1076 | static int __devinit blackbird_probe(struct pci_dev *pci_dev, | 1145 | static int cx8802_blackbird_probe(struct cx8802_driver *drv) |
1077 | const struct pci_device_id *pci_id) | ||
1078 | { | 1146 | { |
1079 | struct cx8802_dev *dev; | 1147 | struct cx88_core *core = drv->core; |
1080 | struct cx88_core *core; | 1148 | struct cx8802_dev *dev = core->dvbdev; |
1081 | int err; | 1149 | int err; |
1082 | 1150 | ||
1083 | /* general setup */ | 1151 | dprintk( 1, "%s\n", __FUNCTION__); |
1084 | core = cx88_core_get(pci_dev); | 1152 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", |
1085 | if (NULL == core) | 1153 | core->board, |
1086 | return -EINVAL; | 1154 | core->name, |
1155 | core->pci_bus, | ||
1156 | core->pci_slot); | ||
1087 | 1157 | ||
1088 | err = -ENODEV; | 1158 | err = -ENODEV; |
1089 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD)) | 1159 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD)) |
1090 | goto fail_core; | 1160 | goto fail_core; |
1091 | 1161 | ||
1092 | err = -ENOMEM; | ||
1093 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); | ||
1094 | if (NULL == dev) | ||
1095 | goto fail_core; | ||
1096 | dev->pci = pci_dev; | ||
1097 | dev->core = core; | ||
1098 | dev->width = 720; | 1162 | dev->width = 720; |
1099 | dev->height = 576; | 1163 | dev->height = 576; |
1100 | cx2341x_fill_defaults(&dev->params); | 1164 | cx2341x_fill_defaults(&dev->params); |
@@ -1106,64 +1170,36 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev, | |||
1106 | dev->height = 576; | 1170 | dev->height = 576; |
1107 | } | 1171 | } |
1108 | 1172 | ||
1109 | err = cx8802_init_common(dev); | ||
1110 | if (0 != err) | ||
1111 | goto fail_free; | ||
1112 | |||
1113 | /* blackbird stuff */ | 1173 | /* blackbird stuff */ |
1114 | printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", | 1174 | printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", |
1115 | core->name); | 1175 | core->name); |
1116 | host_setup(dev->core); | 1176 | host_setup(dev->core); |
1117 | 1177 | ||
1118 | list_add_tail(&dev->devlist,&cx8802_devlist); | ||
1119 | blackbird_register_video(dev); | 1178 | blackbird_register_video(dev); |
1120 | 1179 | ||
1121 | /* initial device configuration: needed ? */ | 1180 | /* initial device configuration: needed ? */ |
1122 | 1181 | ||
1123 | return 0; | 1182 | return 0; |
1124 | 1183 | ||
1125 | fail_free: | ||
1126 | kfree(dev); | ||
1127 | fail_core: | 1184 | fail_core: |
1128 | cx88_core_put(core,pci_dev); | ||
1129 | return err; | 1185 | return err; |
1130 | } | 1186 | } |
1131 | 1187 | ||
1132 | static void __devexit blackbird_remove(struct pci_dev *pci_dev) | 1188 | static int cx8802_blackbird_remove(struct cx8802_driver *drv) |
1133 | { | 1189 | { |
1134 | struct cx8802_dev *dev = pci_get_drvdata(pci_dev); | ||
1135 | |||
1136 | /* blackbird */ | 1190 | /* blackbird */ |
1137 | blackbird_unregister_video(dev); | 1191 | blackbird_unregister_video(drv->core->dvbdev); |
1138 | list_del(&dev->devlist); | ||
1139 | 1192 | ||
1140 | /* common */ | 1193 | return 0; |
1141 | cx8802_fini_common(dev); | ||
1142 | cx88_core_put(dev->core,dev->pci); | ||
1143 | kfree(dev); | ||
1144 | } | 1194 | } |
1145 | 1195 | ||
1146 | static struct pci_device_id cx8802_pci_tbl[] = { | 1196 | static struct cx8802_driver cx8802_blackbird_driver = { |
1147 | { | 1197 | .type_id = CX88_MPEG_BLACKBIRD, |
1148 | .vendor = 0x14f1, | 1198 | .hw_access = CX8802_DRVCTL_SHARED, |
1149 | .device = 0x8802, | 1199 | .probe = cx8802_blackbird_probe, |
1150 | .subvendor = PCI_ANY_ID, | 1200 | .remove = cx8802_blackbird_remove, |
1151 | .subdevice = PCI_ANY_ID, | 1201 | .advise_acquire = cx8802_blackbird_advise_acquire, |
1152 | },{ | 1202 | .advise_release = cx8802_blackbird_advise_release, |
1153 | /* --- end of list --- */ | ||
1154 | } | ||
1155 | }; | ||
1156 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | ||
1157 | |||
1158 | static struct pci_driver blackbird_pci_driver = { | ||
1159 | .name = "cx88-blackbird", | ||
1160 | .id_table = cx8802_pci_tbl, | ||
1161 | .probe = blackbird_probe, | ||
1162 | .remove = __devexit_p(blackbird_remove), | ||
1163 | #ifdef CONFIG_PM | ||
1164 | .suspend = cx8802_suspend_common, | ||
1165 | .resume = cx8802_resume_common, | ||
1166 | #endif | ||
1167 | }; | 1203 | }; |
1168 | 1204 | ||
1169 | static int blackbird_init(void) | 1205 | static int blackbird_init(void) |
@@ -1176,17 +1212,22 @@ static int blackbird_init(void) | |||
1176 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | 1212 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", |
1177 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | 1213 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); |
1178 | #endif | 1214 | #endif |
1179 | return pci_register_driver(&blackbird_pci_driver); | 1215 | cx88_ioctl_hook = mpeg_do_ioctl; |
1216 | cx88_ioctl_translator = mpeg_translate_ioctl; | ||
1217 | return cx8802_register_driver(&cx8802_blackbird_driver); | ||
1180 | } | 1218 | } |
1181 | 1219 | ||
1182 | static void blackbird_fini(void) | 1220 | static void blackbird_fini(void) |
1183 | { | 1221 | { |
1184 | pci_unregister_driver(&blackbird_pci_driver); | 1222 | cx8802_unregister_driver(&cx8802_blackbird_driver); |
1185 | } | 1223 | } |
1186 | 1224 | ||
1187 | module_init(blackbird_init); | 1225 | module_init(blackbird_init); |
1188 | module_exit(blackbird_fini); | 1226 | module_exit(blackbird_fini); |
1189 | 1227 | ||
1228 | EXPORT_SYMBOL(cx88_ioctl_hook); | ||
1229 | EXPORT_SYMBOL(cx88_ioctl_translator); | ||
1230 | |||
1190 | /* ----------------------------------------------------------- */ | 1231 | /* ----------------------------------------------------------- */ |
1191 | /* | 1232 | /* |
1192 | * Local variables: | 1233 | * Local variables: |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index f764a57c56be..c791708b1336 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -281,18 +281,22 @@ struct cx88_board cx88_boards[] = { | |||
281 | .type = CX88_VMUX_TELEVISION, | 281 | .type = CX88_VMUX_TELEVISION, |
282 | .vmux = 0, | 282 | .vmux = 0, |
283 | .gpio0 = 0x0000bde2, | 283 | .gpio0 = 0x0000bde2, |
284 | .extadc = 1, | ||
284 | },{ | 285 | },{ |
285 | .type = CX88_VMUX_COMPOSITE1, | 286 | .type = CX88_VMUX_COMPOSITE1, |
286 | .vmux = 1, | 287 | .vmux = 1, |
287 | .gpio0 = 0x0000bde6, | 288 | .gpio0 = 0x0000bde6, |
289 | .extadc = 1, | ||
288 | },{ | 290 | },{ |
289 | .type = CX88_VMUX_SVIDEO, | 291 | .type = CX88_VMUX_SVIDEO, |
290 | .vmux = 2, | 292 | .vmux = 2, |
291 | .gpio0 = 0x0000bde6, | 293 | .gpio0 = 0x0000bde6, |
294 | .extadc = 1, | ||
292 | }}, | 295 | }}, |
293 | .radio = { | 296 | .radio = { |
294 | .type = CX88_RADIO, | 297 | .type = CX88_RADIO, |
295 | .gpio0 = 0x0000bd62, | 298 | .gpio0 = 0x0000bd62, |
299 | .extadc = 1, | ||
296 | }, | 300 | }, |
297 | .mpeg = CX88_MPEG_BLACKBIRD, | 301 | .mpeg = CX88_MPEG_BLACKBIRD, |
298 | }, | 302 | }, |
@@ -353,6 +357,7 @@ struct cx88_board cx88_boards[] = { | |||
353 | .type = CX88_VMUX_SVIDEO, | 357 | .type = CX88_VMUX_SVIDEO, |
354 | .vmux = 2, | 358 | .vmux = 2, |
355 | .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? | 359 | .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? |
360 | .extadc = 1, | ||
356 | }}, | 361 | }}, |
357 | .radio = { | 362 | .radio = { |
358 | .type = CX88_RADIO, | 363 | .type = CX88_RADIO, |
@@ -523,6 +528,7 @@ struct cx88_board cx88_boards[] = { | |||
523 | .input = {{ | 528 | .input = {{ |
524 | .type = CX88_VMUX_TELEVISION, | 529 | .type = CX88_VMUX_TELEVISION, |
525 | .vmux = 0, | 530 | .vmux = 0, |
531 | .extadc = 1, | ||
526 | }}, | 532 | }}, |
527 | .mpeg = CX88_MPEG_BLACKBIRD, | 533 | .mpeg = CX88_MPEG_BLACKBIRD, |
528 | }, | 534 | }, |
@@ -646,18 +652,22 @@ struct cx88_board cx88_boards[] = { | |||
646 | .type = CX88_VMUX_TELEVISION, | 652 | .type = CX88_VMUX_TELEVISION, |
647 | .vmux = 0, | 653 | .vmux = 0, |
648 | .gpio0 = 0x00009d80, | 654 | .gpio0 = 0x00009d80, |
655 | .extadc = 1, | ||
649 | },{ | 656 | },{ |
650 | .type = CX88_VMUX_COMPOSITE1, | 657 | .type = CX88_VMUX_COMPOSITE1, |
651 | .vmux = 1, | 658 | .vmux = 1, |
652 | .gpio0 = 0x00009d76, | 659 | .gpio0 = 0x00009d76, |
660 | .extadc = 1, | ||
653 | },{ | 661 | },{ |
654 | .type = CX88_VMUX_SVIDEO, | 662 | .type = CX88_VMUX_SVIDEO, |
655 | .vmux = 2, | 663 | .vmux = 2, |
656 | .gpio0 = 0x00009d76, | 664 | .gpio0 = 0x00009d76, |
665 | .extadc = 1, | ||
657 | }}, | 666 | }}, |
658 | .radio = { | 667 | .radio = { |
659 | .type = CX88_RADIO, | 668 | .type = CX88_RADIO, |
660 | .gpio0 = 0x00009d00, | 669 | .gpio0 = 0x00009d00, |
670 | .extadc = 1, | ||
661 | }, | 671 | }, |
662 | .mpeg = CX88_MPEG_BLACKBIRD, | 672 | .mpeg = CX88_MPEG_BLACKBIRD, |
663 | }, | 673 | }, |
@@ -786,25 +796,29 @@ struct cx88_board cx88_boards[] = { | |||
786 | .tuner_addr = ADDR_UNSET, | 796 | .tuner_addr = ADDR_UNSET, |
787 | .radio_addr = ADDR_UNSET, | 797 | .radio_addr = ADDR_UNSET, |
788 | .tda9887_conf = TDA9887_PRESENT, | 798 | .tda9887_conf = TDA9887_PRESENT, |
789 | .mpeg = CX88_MPEG_BLACKBIRD, | ||
790 | .input = {{ | 799 | .input = {{ |
791 | .type = CX88_VMUX_COMPOSITE1, | 800 | .type = CX88_VMUX_COMPOSITE1, |
792 | .vmux = 0, | 801 | .vmux = 0, |
793 | .gpio0 = 0x0000cd73, | 802 | .gpio0 = 0x0000cd73, |
803 | .extadc = 1, | ||
794 | },{ | 804 | },{ |
795 | .type = CX88_VMUX_SVIDEO, | 805 | .type = CX88_VMUX_SVIDEO, |
796 | .vmux = 1, | 806 | .vmux = 1, |
797 | .gpio0 = 0x0000cd73, | 807 | .gpio0 = 0x0000cd73, |
808 | .extadc = 1, | ||
798 | },{ | 809 | },{ |
799 | .type = CX88_VMUX_TELEVISION, | 810 | .type = CX88_VMUX_TELEVISION, |
800 | .vmux = 3, | 811 | .vmux = 3, |
801 | .gpio0 = 0x0000cdb3, | 812 | .gpio0 = 0x0000cdb3, |
813 | .extadc = 1, | ||
802 | }}, | 814 | }}, |
803 | .radio = { | 815 | .radio = { |
804 | .type = CX88_RADIO, | 816 | .type = CX88_RADIO, |
805 | .vmux = 2, | 817 | .vmux = 2, |
806 | .gpio0 = 0x0000cdf3, | 818 | .gpio0 = 0x0000cdf3, |
819 | .extadc = 1, | ||
807 | }, | 820 | }, |
821 | .mpeg = CX88_MPEG_BLACKBIRD, | ||
808 | }, | 822 | }, |
809 | [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { | 823 | [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { |
810 | /* Alexander Wold <awold@bigfoot.com> */ | 824 | /* Alexander Wold <awold@bigfoot.com> */ |
@@ -1050,7 +1064,6 @@ struct cx88_board cx88_boards[] = { | |||
1050 | .mpeg = CX88_MPEG_DVB, | 1064 | .mpeg = CX88_MPEG_DVB, |
1051 | }, | 1065 | }, |
1052 | [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { | 1066 | [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { |
1053 | /* FIXME: Audio not working for s-video / composite inputs. */ | ||
1054 | .name = "KWorld HardwareMpegTV XPert", | 1067 | .name = "KWorld HardwareMpegTV XPert", |
1055 | .tuner_type = TUNER_PHILIPS_TDA8290, | 1068 | .tuner_type = TUNER_PHILIPS_TDA8290, |
1056 | .radio_type = UNSET, | 1069 | .radio_type = UNSET, |
@@ -1065,10 +1078,12 @@ struct cx88_board cx88_boards[] = { | |||
1065 | .type = CX88_VMUX_COMPOSITE1, | 1078 | .type = CX88_VMUX_COMPOSITE1, |
1066 | .vmux = 1, | 1079 | .vmux = 1, |
1067 | .gpio0 = 0x3de6, | 1080 | .gpio0 = 0x3de6, |
1081 | .extadc = 1, | ||
1068 | },{ | 1082 | },{ |
1069 | .type = CX88_VMUX_SVIDEO, | 1083 | .type = CX88_VMUX_SVIDEO, |
1070 | .vmux = 2, | 1084 | .vmux = 2, |
1071 | .gpio0 = 0x3de6, | 1085 | .gpio0 = 0x3de6, |
1086 | .extadc = 1, | ||
1072 | }}, | 1087 | }}, |
1073 | .radio = { | 1088 | .radio = { |
1074 | .type = CX88_RADIO, | 1089 | .type = CX88_RADIO, |
@@ -1252,35 +1267,35 @@ struct cx88_board cx88_boards[] = { | |||
1252 | .gpio0 = 0x070b, | 1267 | .gpio0 = 0x070b, |
1253 | }}, | 1268 | }}, |
1254 | }, | 1269 | }, |
1255 | [CX88_BOARD_TE_DTV_250_OEM_SWANN] = { | 1270 | [CX88_BOARD_TE_DTV_250_OEM_SWANN] = { |
1256 | .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM", | 1271 | .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM", |
1257 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, | 1272 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, |
1258 | .radio_type = UNSET, | 1273 | .radio_type = UNSET, |
1259 | .tuner_addr = ADDR_UNSET, | 1274 | .tuner_addr = ADDR_UNSET, |
1260 | .radio_addr = ADDR_UNSET, | 1275 | .radio_addr = ADDR_UNSET, |
1261 | .input = {{ | 1276 | .input = {{ |
1262 | .type = CX88_VMUX_TELEVISION, | 1277 | .type = CX88_VMUX_TELEVISION, |
1263 | .vmux = 0, | 1278 | .vmux = 0, |
1264 | .gpio0 = 0x003fffff, | 1279 | .gpio0 = 0x003fffff, |
1265 | .gpio1 = 0x00e00000, | 1280 | .gpio1 = 0x00e00000, |
1266 | .gpio2 = 0x003fffff, | 1281 | .gpio2 = 0x003fffff, |
1267 | .gpio3 = 0x02000000, | 1282 | .gpio3 = 0x02000000, |
1268 | },{ | 1283 | },{ |
1269 | .type = CX88_VMUX_COMPOSITE1, | 1284 | .type = CX88_VMUX_COMPOSITE1, |
1270 | .vmux = 1, | 1285 | .vmux = 1, |
1271 | .gpio0 = 0x003fffff, | 1286 | .gpio0 = 0x003fffff, |
1272 | .gpio1 = 0x00e00000, | 1287 | .gpio1 = 0x00e00000, |
1273 | .gpio2 = 0x003fffff, | 1288 | .gpio2 = 0x003fffff, |
1274 | .gpio3 = 0x02000000, | 1289 | .gpio3 = 0x02000000, |
1275 | },{ | 1290 | },{ |
1276 | .type = CX88_VMUX_SVIDEO, | 1291 | .type = CX88_VMUX_SVIDEO, |
1277 | .vmux = 2, | 1292 | .vmux = 2, |
1278 | .gpio0 = 0x003fffff, | 1293 | .gpio0 = 0x003fffff, |
1279 | .gpio1 = 0x00e00000, | 1294 | .gpio1 = 0x00e00000, |
1280 | .gpio2 = 0x003fffff, | 1295 | .gpio2 = 0x003fffff, |
1281 | .gpio3 = 0x02000000, | 1296 | .gpio3 = 0x02000000, |
1282 | }}, | 1297 | }}, |
1283 | }, | 1298 | }, |
1284 | [CX88_BOARD_HAUPPAUGE_HVR1300] = { | 1299 | [CX88_BOARD_HAUPPAUGE_HVR1300] = { |
1285 | .name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder", | 1300 | .name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder", |
1286 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, | 1301 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, |
@@ -1293,17 +1308,20 @@ struct cx88_board cx88_boards[] = { | |||
1293 | .type = CX88_VMUX_TELEVISION, | 1308 | .type = CX88_VMUX_TELEVISION, |
1294 | .vmux = 0, | 1309 | .vmux = 0, |
1295 | .gpio0 = 0xe780, | 1310 | .gpio0 = 0xe780, |
1311 | .extadc = 1, | ||
1296 | },{ | 1312 | },{ |
1297 | .type = CX88_VMUX_COMPOSITE1, | 1313 | .type = CX88_VMUX_COMPOSITE1, |
1298 | .vmux = 1, | 1314 | .vmux = 1, |
1299 | .gpio0 = 0xe780, | 1315 | .gpio0 = 0xe780, |
1316 | .extadc = 1, | ||
1300 | },{ | 1317 | },{ |
1301 | .type = CX88_VMUX_SVIDEO, | 1318 | .type = CX88_VMUX_SVIDEO, |
1302 | .vmux = 2, | 1319 | .vmux = 2, |
1303 | .gpio0 = 0xe780, | 1320 | .gpio0 = 0xe780, |
1321 | .extadc = 1, | ||
1304 | }}, | 1322 | }}, |
1305 | /* fixme: Add radio support */ | 1323 | /* fixme: Add radio support */ |
1306 | .mpeg = CX88_MPEG_DVB, | 1324 | .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, |
1307 | }, | 1325 | }, |
1308 | }; | 1326 | }; |
1309 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); | 1327 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); |
@@ -1513,6 +1531,10 @@ struct cx88_subid cx88_subids[] = { | |||
1513 | },{ | 1531 | },{ |
1514 | .subvendor = 0x17de, | 1532 | .subvendor = 0x17de, |
1515 | .subdevice = 0x0840, | 1533 | .subdevice = 0x0840, |
1534 | .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, | ||
1535 | },{ | ||
1536 | .subvendor = 0x1421, | ||
1537 | .subdevice = 0x0305, | ||
1516 | .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, | 1538 | .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, |
1517 | },{ | 1539 | },{ |
1518 | .subvendor = 0x18ac, | 1540 | .subvendor = 0x18ac, |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 0ef13e7efa2e..8b203354fccd 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include "cx22702.h" | 42 | #include "cx22702.h" |
43 | #include "or51132.h" | 43 | #include "or51132.h" |
44 | #include "lgdt330x.h" | 44 | #include "lgdt330x.h" |
45 | #include "lg_h06xf.h" | 45 | #include "lgh06xf.h" |
46 | #include "nxt200x.h" | 46 | #include "nxt200x.h" |
47 | #include "cx24123.h" | 47 | #include "cx24123.h" |
48 | #include "isl6421.h" | 48 | #include "isl6421.h" |
@@ -57,7 +57,7 @@ module_param(debug, int, 0644); | |||
57 | MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); | 57 | MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); |
58 | 58 | ||
59 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 59 | #define dprintk(level,fmt, arg...) if (debug >= level) \ |
60 | printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->core->name , ## arg) | 60 | printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg) |
61 | 61 | ||
62 | /* ------------------------------------------------------------------ */ | 62 | /* ------------------------------------------------------------------ */ |
63 | 63 | ||
@@ -74,8 +74,8 @@ static int dvb_buf_setup(struct videobuf_queue *q, | |||
74 | return 0; | 74 | return 0; |
75 | } | 75 | } |
76 | 76 | ||
77 | static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | 77 | static int dvb_buf_prepare(struct videobuf_queue *q, |
78 | enum v4l2_field field) | 78 | struct videobuf_buffer *vb, enum v4l2_field field) |
79 | { | 79 | { |
80 | struct cx8802_dev *dev = q->priv_data; | 80 | struct cx8802_dev *dev = q->priv_data; |
81 | return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); | 81 | return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); |
@@ -87,7 +87,8 @@ static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | |||
87 | cx8802_buf_queue(dev, (struct cx88_buffer*)vb); | 87 | cx8802_buf_queue(dev, (struct cx88_buffer*)vb); |
88 | } | 88 | } |
89 | 89 | ||
90 | static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | 90 | static void dvb_buf_release(struct videobuf_queue *q, |
91 | struct videobuf_buffer *vb) | ||
91 | { | 92 | { |
92 | cx88_free_buffer(q, (struct cx88_buffer*)vb); | 93 | cx88_free_buffer(q, (struct cx88_buffer*)vb); |
93 | } | 94 | } |
@@ -100,6 +101,26 @@ static struct videobuf_queue_ops dvb_qops = { | |||
100 | }; | 101 | }; |
101 | 102 | ||
102 | /* ------------------------------------------------------------------ */ | 103 | /* ------------------------------------------------------------------ */ |
104 | |||
105 | static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) | ||
106 | { | ||
107 | struct cx8802_dev *dev= fe->dvb->priv; | ||
108 | struct cx8802_driver *drv = NULL; | ||
109 | int ret = 0; | ||
110 | |||
111 | drv = cx8802_get_driver(dev, CX88_MPEG_DVB); | ||
112 | if (drv) { | ||
113 | if (acquire) | ||
114 | ret = drv->request_acquire(drv); | ||
115 | else | ||
116 | ret = drv->request_release(drv); | ||
117 | } | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | /* ------------------------------------------------------------------ */ | ||
123 | |||
103 | static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) | 124 | static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) |
104 | { | 125 | { |
105 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; | 126 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; |
@@ -268,35 +289,6 @@ static struct mt352_config dntv_live_dvbt_pro_config = { | |||
268 | }; | 289 | }; |
269 | #endif | 290 | #endif |
270 | 291 | ||
271 | static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe, | ||
272 | struct dvb_frontend_parameters *params) | ||
273 | { | ||
274 | u8 pllbuf[4]; | ||
275 | struct cx8802_dev *dev= fe->dvb->priv; | ||
276 | struct i2c_msg msg = | ||
277 | { .addr = dev->core->pll_addr, .flags = 0, | ||
278 | .buf = pllbuf, .len = 4 }; | ||
279 | int err; | ||
280 | |||
281 | dvb_pll_configure(dev->core->pll_desc, pllbuf, | ||
282 | params->frequency, | ||
283 | params->u.ofdm.bandwidth); | ||
284 | |||
285 | if (fe->ops.i2c_gate_ctrl) | ||
286 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
287 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { | ||
288 | printk(KERN_WARNING "cx88-dvb: %s error " | ||
289 | "(addr %02x <- %02x, err = %i)\n", | ||
290 | __FUNCTION__, pllbuf[0], pllbuf[1], err); | ||
291 | if (err < 0) | ||
292 | return err; | ||
293 | else | ||
294 | return -EREMOTEIO; | ||
295 | } | ||
296 | |||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static struct zl10353_config dvico_fusionhdtv_hybrid = { | 292 | static struct zl10353_config dvico_fusionhdtv_hybrid = { |
301 | .demod_address = 0x0f, | 293 | .demod_address = 0x0f, |
302 | .no_tuner = 1, | 294 | .no_tuner = 1, |
@@ -311,28 +303,12 @@ static struct cx22702_config connexant_refboard_config = { | |||
311 | .output_mode = CX22702_SERIAL_OUTPUT, | 303 | .output_mode = CX22702_SERIAL_OUTPUT, |
312 | }; | 304 | }; |
313 | 305 | ||
314 | static struct cx22702_config hauppauge_novat_config = { | 306 | static struct cx22702_config hauppauge_hvr_config = { |
315 | .demod_address = 0x43, | ||
316 | .output_mode = CX22702_SERIAL_OUTPUT, | ||
317 | }; | ||
318 | |||
319 | static struct cx22702_config hauppauge_hvr1100_config = { | ||
320 | .demod_address = 0x63, | 307 | .demod_address = 0x63, |
321 | .output_mode = CX22702_SERIAL_OUTPUT, | 308 | .output_mode = CX22702_SERIAL_OUTPUT, |
322 | }; | 309 | }; |
323 | 310 | ||
324 | static struct cx22702_config hauppauge_hvr1300_config = { | 311 | static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured) |
325 | .demod_address = 0x63, | ||
326 | .output_mode = CX22702_SERIAL_OUTPUT, | ||
327 | }; | ||
328 | |||
329 | static struct cx22702_config hauppauge_hvr3000_config = { | ||
330 | .demod_address = 0x63, | ||
331 | .output_mode = CX22702_SERIAL_OUTPUT, | ||
332 | }; | ||
333 | |||
334 | static int or51132_set_ts_param(struct dvb_frontend* fe, | ||
335 | int is_punctured) | ||
336 | { | 312 | { |
337 | struct cx8802_dev *dev= fe->dvb->priv; | 313 | struct cx8802_dev *dev= fe->dvb->priv; |
338 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; | 314 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; |
@@ -344,50 +320,6 @@ static struct or51132_config pchdtv_hd3000 = { | |||
344 | .set_ts_params = or51132_set_ts_param, | 320 | .set_ts_params = or51132_set_ts_param, |
345 | }; | 321 | }; |
346 | 322 | ||
347 | static int lgdt3302_tuner_set_params(struct dvb_frontend* fe, | ||
348 | struct dvb_frontend_parameters* params) | ||
349 | { | ||
350 | /* FIXME make this routine use the tuner-simple code. | ||
351 | * It could probably be shared with a number of ATSC | ||
352 | * frontends. Many share the same tuner with analog TV. */ | ||
353 | |||
354 | struct cx8802_dev *dev= fe->dvb->priv; | ||
355 | struct cx88_core *core = dev->core; | ||
356 | u8 buf[4]; | ||
357 | struct i2c_msg msg = | ||
358 | { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; | ||
359 | int err; | ||
360 | |||
361 | dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); | ||
362 | dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
363 | __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); | ||
364 | |||
365 | if (fe->ops.i2c_gate_ctrl) | ||
366 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
367 | if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) { | ||
368 | printk(KERN_WARNING "cx88-dvb: %s error " | ||
369 | "(addr %02x <- %02x, err = %i)\n", | ||
370 | __FUNCTION__, buf[0], buf[1], err); | ||
371 | if (err < 0) | ||
372 | return err; | ||
373 | else | ||
374 | return -EREMOTEIO; | ||
375 | } | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, | ||
380 | struct dvb_frontend_parameters* params) | ||
381 | { | ||
382 | struct cx8802_dev *dev= fe->dvb->priv; | ||
383 | struct cx88_core *core = dev->core; | ||
384 | |||
385 | /* Put the analog decoder in standby to keep it quiet */ | ||
386 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
387 | |||
388 | return lg_h06xf_pll_set(fe, &core->i2c_adap, params); | ||
389 | } | ||
390 | |||
391 | static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) | 323 | static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) |
392 | { | 324 | { |
393 | struct cx8802_dev *dev= fe->dvb->priv; | 325 | struct cx8802_dev *dev= fe->dvb->priv; |
@@ -432,8 +364,7 @@ static struct lgdt330x_config pchdtv_hd5500 = { | |||
432 | .set_ts_params = lgdt330x_set_ts_param, | 364 | .set_ts_params = lgdt330x_set_ts_param, |
433 | }; | 365 | }; |
434 | 366 | ||
435 | static int nxt200x_set_ts_param(struct dvb_frontend* fe, | 367 | static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured) |
436 | int is_punctured) | ||
437 | { | 368 | { |
438 | struct cx8802_dev *dev= fe->dvb->priv; | 369 | struct cx8802_dev *dev= fe->dvb->priv; |
439 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; | 370 | dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; |
@@ -469,11 +400,10 @@ static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, | |||
469 | struct cx8802_dev *dev= fe->dvb->priv; | 400 | struct cx8802_dev *dev= fe->dvb->priv; |
470 | struct cx88_core *core = dev->core; | 401 | struct cx88_core *core = dev->core; |
471 | 402 | ||
472 | if (voltage == SEC_VOLTAGE_OFF) { | 403 | if (voltage == SEC_VOLTAGE_OFF) |
473 | cx_write(MO_GP0_IO, 0x000006fb); | 404 | cx_write(MO_GP0_IO, 0x000006fb); |
474 | } else { | 405 | else |
475 | cx_write(MO_GP0_IO, 0x000006f9); | 406 | cx_write(MO_GP0_IO, 0x000006f9); |
476 | } | ||
477 | 407 | ||
478 | if (core->prev_set_voltage) | 408 | if (core->prev_set_voltage) |
479 | return core->prev_set_voltage(fe, voltage); | 409 | return core->prev_set_voltage(fe, voltage); |
@@ -522,7 +452,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
522 | switch (dev->core->board) { | 452 | switch (dev->core->board) { |
523 | case CX88_BOARD_HAUPPAUGE_DVB_T1: | 453 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
524 | dev->dvb.frontend = dvb_attach(cx22702_attach, | 454 | dev->dvb.frontend = dvb_attach(cx22702_attach, |
525 | &hauppauge_novat_config, | 455 | &connexant_refboard_config, |
526 | &dev->core->i2c_adap); | 456 | &dev->core->i2c_adap); |
527 | if (dev->dvb.frontend != NULL) { | 457 | if (dev->dvb.frontend != NULL) { |
528 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 458 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
@@ -547,32 +477,11 @@ static int dvb_register(struct cx8802_dev *dev) | |||
547 | case CX88_BOARD_HAUPPAUGE_HVR1100: | 477 | case CX88_BOARD_HAUPPAUGE_HVR1100: |
548 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | 478 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: |
549 | dev->dvb.frontend = dvb_attach(cx22702_attach, | 479 | dev->dvb.frontend = dvb_attach(cx22702_attach, |
550 | &hauppauge_hvr1100_config, | 480 | &hauppauge_hvr_config, |
551 | &dev->core->i2c_adap); | ||
552 | if (dev->dvb.frontend != NULL) { | ||
553 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
554 | &dev->core->i2c_adap, | ||
555 | &dvb_pll_fmd1216me); | ||
556 | } | ||
557 | break; | ||
558 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
559 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
560 | &hauppauge_hvr1300_config, | ||
561 | &dev->core->i2c_adap); | ||
562 | if (dev->dvb.frontend != NULL) { | ||
563 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
564 | &dev->core->i2c_adap, | ||
565 | &dvb_pll_fmd1216me); | ||
566 | } | ||
567 | break; | ||
568 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
569 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
570 | &hauppauge_hvr3000_config, | ||
571 | &dev->core->i2c_adap); | 481 | &dev->core->i2c_adap); |
572 | if (dev->dvb.frontend != NULL) { | 482 | if (dev->dvb.frontend != NULL) { |
573 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 483 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
574 | &dev->core->i2c_adap, | 484 | &dev->core->i2c_adap, &dvb_pll_fmd1216me); |
575 | &dvb_pll_fmd1216me); | ||
576 | } | 485 | } |
577 | break; | 486 | break; |
578 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: | 487 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: |
@@ -647,18 +556,17 @@ static int dvb_register(struct cx8802_dev *dev) | |||
647 | #endif | 556 | #endif |
648 | break; | 557 | break; |
649 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: | 558 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: |
650 | dev->core->pll_addr = 0x61; | ||
651 | dev->core->pll_desc = &dvb_pll_thomson_fe6600; | ||
652 | dev->dvb.frontend = dvb_attach(zl10353_attach, | 559 | dev->dvb.frontend = dvb_attach(zl10353_attach, |
653 | &dvico_fusionhdtv_hybrid, | 560 | &dvico_fusionhdtv_hybrid, |
654 | &dev->core->i2c_adap); | 561 | &dev->core->i2c_adap); |
655 | if (dev->dvb.frontend != NULL) { | 562 | if (dev->dvb.frontend != NULL) { |
656 | dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params; | 563 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
564 | &dev->core->i2c_adap, | ||
565 | &dvb_pll_thomson_fe6600); | ||
657 | } | 566 | } |
658 | break; | 567 | break; |
659 | case CX88_BOARD_PCHDTV_HD3000: | 568 | case CX88_BOARD_PCHDTV_HD3000: |
660 | dev->dvb.frontend = dvb_attach(or51132_attach, | 569 | dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, |
661 | &pchdtv_hd3000, | ||
662 | &dev->core->i2c_adap); | 570 | &dev->core->i2c_adap); |
663 | if (dev->dvb.frontend != NULL) { | 571 | if (dev->dvb.frontend != NULL) { |
664 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 572 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
@@ -679,13 +587,13 @@ static int dvb_register(struct cx8802_dev *dev) | |||
679 | 587 | ||
680 | /* Select RF connector callback */ | 588 | /* Select RF connector callback */ |
681 | fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; | 589 | fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; |
682 | dev->core->pll_addr = 0x61; | ||
683 | dev->core->pll_desc = &dvb_pll_microtune_4042; | ||
684 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, | 590 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, |
685 | &fusionhdtv_3_gold, | 591 | &fusionhdtv_3_gold, |
686 | &dev->core->i2c_adap); | 592 | &dev->core->i2c_adap); |
687 | if (dev->dvb.frontend != NULL) { | 593 | if (dev->dvb.frontend != NULL) { |
688 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; | 594 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
595 | &dev->core->i2c_adap, | ||
596 | &dvb_pll_microtune_4042); | ||
689 | } | 597 | } |
690 | } | 598 | } |
691 | break; | 599 | break; |
@@ -699,13 +607,13 @@ static int dvb_register(struct cx8802_dev *dev) | |||
699 | mdelay(100); | 607 | mdelay(100); |
700 | cx_set(MO_GP0_IO, 9); | 608 | cx_set(MO_GP0_IO, 9); |
701 | mdelay(200); | 609 | mdelay(200); |
702 | dev->core->pll_addr = 0x61; | ||
703 | dev->core->pll_desc = &dvb_pll_thomson_dtt761x; | ||
704 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, | 610 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, |
705 | &fusionhdtv_3_gold, | 611 | &fusionhdtv_3_gold, |
706 | &dev->core->i2c_adap); | 612 | &dev->core->i2c_adap); |
707 | if (dev->dvb.frontend != NULL) { | 613 | if (dev->dvb.frontend != NULL) { |
708 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; | 614 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
615 | &dev->core->i2c_adap, | ||
616 | &dvb_pll_thomson_dtt761x); | ||
709 | } | 617 | } |
710 | } | 618 | } |
711 | break; | 619 | break; |
@@ -723,7 +631,8 @@ static int dvb_register(struct cx8802_dev *dev) | |||
723 | &fusionhdtv_5_gold, | 631 | &fusionhdtv_5_gold, |
724 | &dev->core->i2c_adap); | 632 | &dev->core->i2c_adap); |
725 | if (dev->dvb.frontend != NULL) { | 633 | if (dev->dvb.frontend != NULL) { |
726 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; | 634 | dvb_attach(lgh06xf_attach, dev->dvb.frontend, |
635 | &dev->core->i2c_adap); | ||
727 | } | 636 | } |
728 | } | 637 | } |
729 | break; | 638 | break; |
@@ -741,7 +650,8 @@ static int dvb_register(struct cx8802_dev *dev) | |||
741 | &pchdtv_hd5500, | 650 | &pchdtv_hd5500, |
742 | &dev->core->i2c_adap); | 651 | &dev->core->i2c_adap); |
743 | if (dev->dvb.frontend != NULL) { | 652 | if (dev->dvb.frontend != NULL) { |
744 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; | 653 | dvb_attach(lgh06xf_attach, dev->dvb.frontend, |
654 | &dev->core->i2c_adap); | ||
745 | } | 655 | } |
746 | } | 656 | } |
747 | break; | 657 | break; |
@@ -782,6 +692,24 @@ static int dvb_register(struct cx8802_dev *dev) | |||
782 | dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; | 692 | dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; |
783 | } | 693 | } |
784 | break; | 694 | break; |
695 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
696 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
697 | &hauppauge_hvr_config, | ||
698 | &dev->core->i2c_adap); | ||
699 | if (dev->dvb.frontend != NULL) { | ||
700 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
701 | &dev->core->i2c_adap, &dvb_pll_fmd1216me); | ||
702 | } | ||
703 | break; | ||
704 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
705 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
706 | &hauppauge_hvr_config, | ||
707 | &dev->core->i2c_adap); | ||
708 | if (dev->dvb.frontend != NULL) { | ||
709 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
710 | &dev->core->i2c_adap, &dvb_pll_fmd1216me); | ||
711 | } | ||
712 | break; | ||
785 | default: | 713 | default: |
786 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", | 714 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", |
787 | dev->core->name); | 715 | dev->core->name); |
@@ -796,6 +724,8 @@ static int dvb_register(struct cx8802_dev *dev) | |||
796 | dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; | 724 | dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; |
797 | dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; | 725 | dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; |
798 | } | 726 | } |
727 | /* Ensure all frontends negotiate bus access */ | ||
728 | dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; | ||
799 | 729 | ||
800 | /* Put the analog decoder in standby to keep it quiet */ | 730 | /* Put the analog decoder in standby to keep it quiet */ |
801 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | 731 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); |
@@ -806,37 +736,67 @@ static int dvb_register(struct cx8802_dev *dev) | |||
806 | 736 | ||
807 | /* ----------------------------------------------------------- */ | 737 | /* ----------------------------------------------------------- */ |
808 | 738 | ||
809 | static int __devinit dvb_probe(struct pci_dev *pci_dev, | 739 | /* CX8802 MPEG -> mini driver - We have been given the hardware */ |
810 | const struct pci_device_id *pci_id) | 740 | static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) |
811 | { | 741 | { |
812 | struct cx8802_dev *dev; | 742 | struct cx88_core *core = drv->core; |
813 | struct cx88_core *core; | 743 | int err = 0; |
744 | dprintk( 1, "%s\n", __FUNCTION__); | ||
745 | |||
746 | switch (core->board) { | ||
747 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
748 | /* We arrive here with either the cx23416 or the cx22702 | ||
749 | * on the bus. Take the bus from the cx23416 and enable the | ||
750 | * cx22702 demod | ||
751 | */ | ||
752 | cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset and enable */ | ||
753 | cx_clear(MO_GP0_IO, 0x00000004); | ||
754 | udelay(1000); | ||
755 | break; | ||
756 | default: | ||
757 | err = -ENODEV; | ||
758 | } | ||
759 | return err; | ||
760 | } | ||
761 | |||
762 | /* CX8802 MPEG -> mini driver - We no longer have the hardware */ | ||
763 | static int cx8802_dvb_advise_release(struct cx8802_driver *drv) | ||
764 | { | ||
765 | struct cx88_core *core = drv->core; | ||
766 | int err = 0; | ||
767 | dprintk( 1, "%s\n", __FUNCTION__); | ||
768 | |||
769 | switch (core->board) { | ||
770 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
771 | /* Do Nothing, leave the cx22702 on the bus. */ | ||
772 | break; | ||
773 | default: | ||
774 | err = -ENODEV; | ||
775 | } | ||
776 | return err; | ||
777 | } | ||
778 | |||
779 | static int cx8802_dvb_probe(struct cx8802_driver *drv) | ||
780 | { | ||
781 | struct cx88_core *core = drv->core; | ||
782 | struct cx8802_dev *dev = drv->core->dvbdev; | ||
814 | int err; | 783 | int err; |
815 | 784 | ||
816 | /* general setup */ | 785 | dprintk( 1, "%s\n", __FUNCTION__); |
817 | core = cx88_core_get(pci_dev); | 786 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", |
818 | if (NULL == core) | 787 | core->board, |
819 | return -EINVAL; | 788 | core->name, |
789 | core->pci_bus, | ||
790 | core->pci_slot); | ||
820 | 791 | ||
821 | err = -ENODEV; | 792 | err = -ENODEV; |
822 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) | 793 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) |
823 | goto fail_core; | 794 | goto fail_core; |
824 | 795 | ||
825 | err = -ENOMEM; | ||
826 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); | ||
827 | if (NULL == dev) | ||
828 | goto fail_core; | ||
829 | dev->pci = pci_dev; | ||
830 | dev->core = core; | ||
831 | |||
832 | err = cx8802_init_common(dev); | ||
833 | if (0 != err) | ||
834 | goto fail_free; | ||
835 | |||
836 | #ifdef HAVE_VP3054_I2C | 796 | #ifdef HAVE_VP3054_I2C |
837 | err = vp3054_i2c_probe(dev); | 797 | err = vp3054_i2c_probe(dev); |
838 | if (0 != err) | 798 | if (0 != err) |
839 | goto fail_free; | 799 | goto fail_core; |
840 | #endif | 800 | #endif |
841 | 801 | ||
842 | /* dvb stuff */ | 802 | /* dvb stuff */ |
@@ -848,28 +808,16 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev, | |||
848 | sizeof(struct cx88_buffer), | 808 | sizeof(struct cx88_buffer), |
849 | dev); | 809 | dev); |
850 | err = dvb_register(dev); | 810 | err = dvb_register(dev); |
851 | if (0 != err) | 811 | if (err != 0) |
852 | goto fail_fini; | 812 | printk("%s dvb_register failed err = %d\n", __FUNCTION__, err); |
853 | 813 | ||
854 | /* Maintain a reference to cx88-video can query the 8802 device. */ | ||
855 | core->dvbdev = dev; | ||
856 | return 0; | ||
857 | |||
858 | fail_fini: | ||
859 | cx8802_fini_common(dev); | ||
860 | fail_free: | ||
861 | kfree(dev); | ||
862 | fail_core: | 814 | fail_core: |
863 | cx88_core_put(core,pci_dev); | ||
864 | return err; | 815 | return err; |
865 | } | 816 | } |
866 | 817 | ||
867 | static void __devexit dvb_remove(struct pci_dev *pci_dev) | 818 | static int cx8802_dvb_remove(struct cx8802_driver *drv) |
868 | { | 819 | { |
869 | struct cx8802_dev *dev = pci_get_drvdata(pci_dev); | 820 | struct cx8802_dev *dev = drv->core->dvbdev; |
870 | |||
871 | /* Destroy any 8802 reference. */ | ||
872 | dev->core->dvbdev = NULL; | ||
873 | 821 | ||
874 | /* dvb */ | 822 | /* dvb */ |
875 | videobuf_dvb_unregister(&dev->dvb); | 823 | videobuf_dvb_unregister(&dev->dvb); |
@@ -878,33 +826,16 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev) | |||
878 | vp3054_i2c_remove(dev); | 826 | vp3054_i2c_remove(dev); |
879 | #endif | 827 | #endif |
880 | 828 | ||
881 | /* common */ | 829 | return 0; |
882 | cx8802_fini_common(dev); | ||
883 | cx88_core_put(dev->core,dev->pci); | ||
884 | kfree(dev); | ||
885 | } | 830 | } |
886 | 831 | ||
887 | static struct pci_device_id cx8802_pci_tbl[] = { | 832 | static struct cx8802_driver cx8802_dvb_driver = { |
888 | { | 833 | .type_id = CX88_MPEG_DVB, |
889 | .vendor = 0x14f1, | 834 | .hw_access = CX8802_DRVCTL_SHARED, |
890 | .device = 0x8802, | 835 | .probe = cx8802_dvb_probe, |
891 | .subvendor = PCI_ANY_ID, | 836 | .remove = cx8802_dvb_remove, |
892 | .subdevice = PCI_ANY_ID, | 837 | .advise_acquire = cx8802_dvb_advise_acquire, |
893 | },{ | 838 | .advise_release = cx8802_dvb_advise_release, |
894 | /* --- end of list --- */ | ||
895 | } | ||
896 | }; | ||
897 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | ||
898 | |||
899 | static struct pci_driver dvb_pci_driver = { | ||
900 | .name = "cx88-dvb", | ||
901 | .id_table = cx8802_pci_tbl, | ||
902 | .probe = dvb_probe, | ||
903 | .remove = __devexit_p(dvb_remove), | ||
904 | #ifdef CONFIG_PM | ||
905 | .suspend = cx8802_suspend_common, | ||
906 | .resume = cx8802_resume_common, | ||
907 | #endif | ||
908 | }; | 839 | }; |
909 | 840 | ||
910 | static int dvb_init(void) | 841 | static int dvb_init(void) |
@@ -917,12 +848,12 @@ static int dvb_init(void) | |||
917 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | 848 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", |
918 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | 849 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); |
919 | #endif | 850 | #endif |
920 | return pci_register_driver(&dvb_pci_driver); | 851 | return cx8802_register_driver(&cx8802_dvb_driver); |
921 | } | 852 | } |
922 | 853 | ||
923 | static void dvb_fini(void) | 854 | static void dvb_fini(void) |
924 | { | 855 | { |
925 | pci_unregister_driver(&dvb_pci_driver); | 856 | cx8802_unregister_driver(&cx8802_dvb_driver); |
926 | } | 857 | } |
927 | 858 | ||
928 | module_init(dvb_init); | 859 | module_init(dvb_init); |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index e60a0a52e4b2..8136673fe9e8 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -155,6 +155,35 @@ static void cx88_ir_work(struct work_struct *work) | |||
155 | mod_timer(&ir->timer, timeout); | 155 | mod_timer(&ir->timer, timeout); |
156 | } | 156 | } |
157 | 157 | ||
158 | static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) | ||
159 | { | ||
160 | if (ir->polling) { | ||
161 | INIT_WORK(&ir->work, cx88_ir_work); | ||
162 | init_timer(&ir->timer); | ||
163 | ir->timer.function = ir_timer; | ||
164 | ir->timer.data = (unsigned long)ir; | ||
165 | schedule_work(&ir->work); | ||
166 | } | ||
167 | if (ir->sampling) { | ||
168 | core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */ | ||
169 | cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ | ||
170 | cx_write(MO_DDSCFG_IO, 0x5); /* enable */ | ||
171 | } | ||
172 | } | ||
173 | |||
174 | static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) | ||
175 | { | ||
176 | if (ir->sampling) { | ||
177 | cx_write(MO_DDSCFG_IO, 0x0); | ||
178 | core->pci_irqmask &= ~(1 << 18); | ||
179 | } | ||
180 | |||
181 | if (ir->polling) { | ||
182 | del_timer_sync(&ir->timer); | ||
183 | flush_scheduled_work(); | ||
184 | } | ||
185 | } | ||
186 | |||
158 | /* ---------------------------------------------------------------------- */ | 187 | /* ---------------------------------------------------------------------- */ |
159 | 188 | ||
160 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | 189 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) |
@@ -163,14 +192,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
163 | struct input_dev *input_dev; | 192 | struct input_dev *input_dev; |
164 | IR_KEYTAB_TYPE *ir_codes = NULL; | 193 | IR_KEYTAB_TYPE *ir_codes = NULL; |
165 | int ir_type = IR_TYPE_OTHER; | 194 | int ir_type = IR_TYPE_OTHER; |
195 | int err = -ENOMEM; | ||
166 | 196 | ||
167 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | 197 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); |
168 | input_dev = input_allocate_device(); | 198 | input_dev = input_allocate_device(); |
169 | if (!ir || !input_dev) { | 199 | if (!ir || !input_dev) |
170 | kfree(ir); | 200 | goto err_out_free; |
171 | input_free_device(input_dev); | ||
172 | return -ENOMEM; | ||
173 | } | ||
174 | 201 | ||
175 | ir->input = input_dev; | 202 | ir->input = input_dev; |
176 | 203 | ||
@@ -280,9 +307,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
280 | } | 307 | } |
281 | 308 | ||
282 | if (NULL == ir_codes) { | 309 | if (NULL == ir_codes) { |
283 | kfree(ir); | 310 | err = -ENODEV; |
284 | input_free_device(input_dev); | 311 | goto err_out_free; |
285 | return -ENODEV; | ||
286 | } | 312 | } |
287 | 313 | ||
288 | /* init input device */ | 314 | /* init input device */ |
@@ -307,23 +333,22 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
307 | ir->core = core; | 333 | ir->core = core; |
308 | core->ir = ir; | 334 | core->ir = ir; |
309 | 335 | ||
310 | if (ir->polling) { | 336 | cx88_ir_start(core, ir); |
311 | INIT_WORK(&ir->work, cx88_ir_work); | ||
312 | init_timer(&ir->timer); | ||
313 | ir->timer.function = ir_timer; | ||
314 | ir->timer.data = (unsigned long)ir; | ||
315 | schedule_work(&ir->work); | ||
316 | } | ||
317 | if (ir->sampling) { | ||
318 | core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */ | ||
319 | cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ | ||
320 | cx_write(MO_DDSCFG_IO, 0x5); /* enable */ | ||
321 | } | ||
322 | 337 | ||
323 | /* all done */ | 338 | /* all done */ |
324 | input_register_device(ir->input); | 339 | err = input_register_device(ir->input); |
340 | if (err) | ||
341 | goto err_out_stop; | ||
325 | 342 | ||
326 | return 0; | 343 | return 0; |
344 | |||
345 | err_out_stop: | ||
346 | cx88_ir_stop(core, ir); | ||
347 | core->ir = NULL; | ||
348 | err_out_free: | ||
349 | input_free_device(input_dev); | ||
350 | kfree(ir); | ||
351 | return err; | ||
327 | } | 352 | } |
328 | 353 | ||
329 | int cx88_ir_fini(struct cx88_core *core) | 354 | int cx88_ir_fini(struct cx88_core *core) |
@@ -334,15 +359,7 @@ int cx88_ir_fini(struct cx88_core *core) | |||
334 | if (NULL == ir) | 359 | if (NULL == ir) |
335 | return 0; | 360 | return 0; |
336 | 361 | ||
337 | if (ir->sampling) { | 362 | cx88_ir_stop(core, ir); |
338 | cx_write(MO_DDSCFG_IO, 0x0); | ||
339 | core->pci_irqmask &= ~(1 << 18); | ||
340 | } | ||
341 | if (ir->polling) { | ||
342 | del_timer(&ir->timer); | ||
343 | flush_scheduled_work(); | ||
344 | } | ||
345 | |||
346 | input_unregister_device(ir->input); | 363 | input_unregister_device(ir->input); |
347 | kfree(ir); | 364 | kfree(ir); |
348 | 365 | ||
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 6b23a4e6f66d..1fe1a833c7c7 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -44,8 +44,12 @@ module_param(debug,int,0644); | |||
44 | MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); | 44 | MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); |
45 | 45 | ||
46 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 46 | #define dprintk(level,fmt, arg...) if (debug >= level) \ |
47 | printk(KERN_DEBUG "%s/2: " fmt, dev->core->name , ## arg) | 47 | printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg) |
48 | 48 | ||
49 | #define mpeg_dbg(level,fmt, arg...) if (debug >= level) \ | ||
50 | printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg) | ||
51 | |||
52 | static LIST_HEAD(cx8802_devlist); | ||
49 | /* ------------------------------------------------------------------ */ | 53 | /* ------------------------------------------------------------------ */ |
50 | 54 | ||
51 | static int cx8802_start_dma(struct cx8802_dev *dev, | 55 | static int cx8802_start_dma(struct cx8802_dev *dev, |
@@ -65,17 +69,13 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
65 | 69 | ||
66 | /* FIXME: this needs a review. | 70 | /* FIXME: this needs a review. |
67 | * also: move to cx88-blackbird + cx88-dvb source files? */ | 71 | * also: move to cx88-blackbird + cx88-dvb source files? */ |
68 | if (cx88_boards[core->board].mpeg == (CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) ) { | ||
69 | /* Report a warning until the mini driver patch is applied, | ||
70 | * else the following conditions will set the dma registers incorrectly. | ||
71 | * This will be removed in the next major patch and changes to the conditions | ||
72 | * will be made. | ||
73 | */ | ||
74 | printk(KERN_INFO "%s() board->(CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) is invalid\n", __FUNCTION__); | ||
75 | return -EINVAL; | ||
76 | } | ||
77 | 72 | ||
78 | if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) { | 73 | dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id); |
74 | |||
75 | if ( (core->active_type_id == CX88_MPEG_DVB) && | ||
76 | (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) { | ||
77 | |||
78 | dprintk( 1, "cx8802_start_dma doing .dvb\n"); | ||
79 | /* negedge driven & software reset */ | 79 | /* negedge driven & software reset */ |
80 | cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl); | 80 | cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl); |
81 | udelay(100); | 81 | udelay(100); |
@@ -93,15 +93,17 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
93 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ | 93 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ |
94 | udelay(100); | 94 | udelay(100); |
95 | break; | 95 | break; |
96 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
97 | break; | ||
96 | default: | 98 | default: |
97 | cx_write(TS_SOP_STAT, 0x00); | 99 | cx_write(TS_SOP_STAT, 0x00); |
98 | break; | 100 | break; |
99 | } | 101 | } |
100 | cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); | 102 | cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); |
101 | udelay(100); | 103 | udelay(100); |
102 | } | 104 | } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) && |
103 | 105 | (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) ) { | |
104 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { | 106 | dprintk( 1, "cx8802_start_dma doing .blackbird\n"); |
105 | cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */ | 107 | cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */ |
106 | 108 | ||
107 | cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */ | 109 | cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */ |
@@ -112,6 +114,10 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
112 | 114 | ||
113 | cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */ | 115 | cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */ |
114 | udelay(100); | 116 | udelay(100); |
117 | } else { | ||
118 | printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__, | ||
119 | cx88_boards[core->board].mpeg ); | ||
120 | return -EINVAL; | ||
115 | } | 121 | } |
116 | 122 | ||
117 | /* reset counter */ | 123 | /* reset counter */ |
@@ -542,8 +548,315 @@ int cx8802_resume_common(struct pci_dev *pci_dev) | |||
542 | return 0; | 548 | return 0; |
543 | } | 549 | } |
544 | 550 | ||
551 | struct cx8802_dev * cx8802_get_device(struct inode *inode) | ||
552 | { | ||
553 | int minor = iminor(inode); | ||
554 | struct cx8802_dev *h = NULL; | ||
555 | struct list_head *list; | ||
556 | |||
557 | list_for_each(list,&cx8802_devlist) { | ||
558 | h = list_entry(list, struct cx8802_dev, devlist); | ||
559 | if (h->mpeg_dev->minor == minor) | ||
560 | return h; | ||
561 | } | ||
562 | |||
563 | return NULL; | ||
564 | } | ||
565 | |||
566 | struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype) | ||
567 | { | ||
568 | struct cx8802_dev *h = NULL; | ||
569 | struct cx8802_driver *d = NULL; | ||
570 | struct list_head *list; | ||
571 | struct list_head *list2; | ||
572 | |||
573 | list_for_each(list,&cx8802_devlist) { | ||
574 | h = list_entry(list, struct cx8802_dev, devlist); | ||
575 | if (h != dev) | ||
576 | continue; | ||
577 | |||
578 | list_for_each(list2, &h->drvlist.devlist) { | ||
579 | d = list_entry(list2, struct cx8802_driver, devlist); | ||
580 | |||
581 | /* only unregister the correct driver type */ | ||
582 | if (d->type_id == btype) { | ||
583 | return d; | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
588 | return NULL; | ||
589 | } | ||
590 | |||
591 | /* Driver asked for hardware access. */ | ||
592 | int cx8802_request_acquire(struct cx8802_driver *drv) | ||
593 | { | ||
594 | struct cx88_core *core = drv->core; | ||
595 | |||
596 | /* Fail a request for hardware if the device is busy. */ | ||
597 | if (core->active_type_id != CX88_BOARD_NONE) | ||
598 | return -EBUSY; | ||
599 | |||
600 | if (drv->advise_acquire) | ||
601 | { | ||
602 | core->active_type_id = drv->type_id; | ||
603 | drv->advise_acquire(drv); | ||
604 | |||
605 | mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); | ||
606 | } | ||
607 | |||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | /* Driver asked to release hardware. */ | ||
612 | int cx8802_request_release(struct cx8802_driver *drv) | ||
613 | { | ||
614 | struct cx88_core *core = drv->core; | ||
615 | |||
616 | if (drv->advise_release) | ||
617 | { | ||
618 | drv->advise_release(drv); | ||
619 | core->active_type_id = CX88_BOARD_NONE; | ||
620 | mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); | ||
621 | } | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static int cx8802_check_driver(struct cx8802_driver *drv) | ||
627 | { | ||
628 | if (drv == NULL) | ||
629 | return -ENODEV; | ||
630 | |||
631 | if ((drv->type_id != CX88_MPEG_DVB) && | ||
632 | (drv->type_id != CX88_MPEG_BLACKBIRD)) | ||
633 | return -EINVAL; | ||
634 | |||
635 | if ((drv->hw_access != CX8802_DRVCTL_SHARED) && | ||
636 | (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE)) | ||
637 | return -EINVAL; | ||
638 | |||
639 | if ((drv->probe == NULL) || | ||
640 | (drv->remove == NULL) || | ||
641 | (drv->advise_acquire == NULL) || | ||
642 | (drv->advise_release == NULL)) | ||
643 | return -EINVAL; | ||
644 | |||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | int cx8802_register_driver(struct cx8802_driver *drv) | ||
649 | { | ||
650 | struct cx8802_dev *h; | ||
651 | struct cx8802_driver *driver; | ||
652 | struct list_head *list; | ||
653 | int err = 0, i = 0; | ||
654 | |||
655 | printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ , | ||
656 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", | ||
657 | drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); | ||
658 | |||
659 | if ((err = cx8802_check_driver(drv)) != 0) { | ||
660 | printk(KERN_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ ); | ||
661 | return err; | ||
662 | } | ||
663 | |||
664 | list_for_each(list,&cx8802_devlist) { | ||
665 | h = list_entry(list, struct cx8802_dev, devlist); | ||
666 | |||
667 | printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n", | ||
668 | h->core->name,h->pci->subsystem_vendor, | ||
669 | h->pci->subsystem_device,cx88_boards[h->core->board].name, | ||
670 | h->core->board); | ||
671 | |||
672 | /* Bring up a new struct for each driver instance */ | ||
673 | driver = kzalloc(sizeof(*drv),GFP_KERNEL); | ||
674 | if (driver == NULL) | ||
675 | return -ENOMEM; | ||
676 | |||
677 | /* Snapshot of the driver registration data */ | ||
678 | drv->core = h->core; | ||
679 | drv->suspend = cx8802_suspend_common; | ||
680 | drv->resume = cx8802_resume_common; | ||
681 | drv->request_acquire = cx8802_request_acquire; | ||
682 | drv->request_release = cx8802_request_release; | ||
683 | memcpy(driver, drv, sizeof(*driver)); | ||
684 | |||
685 | err = drv->probe(driver); | ||
686 | if (err == 0) { | ||
687 | i++; | ||
688 | mutex_lock(&drv->core->lock); | ||
689 | list_add_tail(&driver->devlist,&h->drvlist.devlist); | ||
690 | mutex_unlock(&drv->core->lock); | ||
691 | } else { | ||
692 | printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err); | ||
693 | } | ||
694 | |||
695 | } | ||
696 | if (i == 0) | ||
697 | err = -ENODEV; | ||
698 | else | ||
699 | err = 0; | ||
700 | |||
701 | return err; | ||
702 | } | ||
703 | |||
704 | int cx8802_unregister_driver(struct cx8802_driver *drv) | ||
705 | { | ||
706 | struct cx8802_dev *h; | ||
707 | struct cx8802_driver *d; | ||
708 | struct list_head *list; | ||
709 | struct list_head *list2, *q; | ||
710 | int err = 0, i = 0; | ||
711 | |||
712 | printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ , | ||
713 | drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird"); | ||
714 | |||
715 | list_for_each(list,&cx8802_devlist) { | ||
716 | i++; | ||
717 | h = list_entry(list, struct cx8802_dev, devlist); | ||
718 | |||
719 | printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n", | ||
720 | h->core->name,h->pci->subsystem_vendor, | ||
721 | h->pci->subsystem_device,cx88_boards[h->core->board].name, | ||
722 | h->core->board); | ||
723 | |||
724 | list_for_each_safe(list2, q, &h->drvlist.devlist) { | ||
725 | d = list_entry(list2, struct cx8802_driver, devlist); | ||
726 | |||
727 | /* only unregister the correct driver type */ | ||
728 | if (d->type_id != drv->type_id) | ||
729 | continue; | ||
730 | |||
731 | err = d->remove(d); | ||
732 | if (err == 0) { | ||
733 | mutex_lock(&drv->core->lock); | ||
734 | list_del(list2); | ||
735 | mutex_unlock(&drv->core->lock); | ||
736 | } else | ||
737 | printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err); | ||
738 | |||
739 | } | ||
740 | |||
741 | } | ||
742 | |||
743 | return err; | ||
744 | } | ||
745 | |||
545 | /* ----------------------------------------------------------- */ | 746 | /* ----------------------------------------------------------- */ |
747 | static int __devinit cx8802_probe(struct pci_dev *pci_dev, | ||
748 | const struct pci_device_id *pci_id) | ||
749 | { | ||
750 | struct cx8802_dev *dev; | ||
751 | struct cx88_core *core; | ||
752 | int err; | ||
753 | |||
754 | /* general setup */ | ||
755 | core = cx88_core_get(pci_dev); | ||
756 | if (NULL == core) | ||
757 | return -EINVAL; | ||
546 | 758 | ||
759 | printk("%s/2: cx2388x 8802 Driver Manager\n", core->name); | ||
760 | |||
761 | err = -ENODEV; | ||
762 | if (!cx88_boards[core->board].mpeg) | ||
763 | goto fail_core; | ||
764 | |||
765 | err = -ENOMEM; | ||
766 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); | ||
767 | if (NULL == dev) | ||
768 | goto fail_core; | ||
769 | dev->pci = pci_dev; | ||
770 | dev->core = core; | ||
771 | |||
772 | err = cx8802_init_common(dev); | ||
773 | if (err != 0) | ||
774 | goto fail_free; | ||
775 | |||
776 | INIT_LIST_HEAD(&dev->drvlist.devlist); | ||
777 | list_add_tail(&dev->devlist,&cx8802_devlist); | ||
778 | |||
779 | /* Maintain a reference so cx88-video can query the 8802 device. */ | ||
780 | core->dvbdev = dev; | ||
781 | return 0; | ||
782 | |||
783 | fail_free: | ||
784 | kfree(dev); | ||
785 | fail_core: | ||
786 | cx88_core_put(core,pci_dev); | ||
787 | return err; | ||
788 | } | ||
789 | |||
790 | static void __devexit cx8802_remove(struct pci_dev *pci_dev) | ||
791 | { | ||
792 | struct cx8802_dev *dev; | ||
793 | struct cx8802_driver *h; | ||
794 | struct list_head *list; | ||
795 | |||
796 | dev = pci_get_drvdata(pci_dev); | ||
797 | |||
798 | dprintk( 1, "%s\n", __FUNCTION__); | ||
799 | |||
800 | list_for_each(list,&dev->drvlist.devlist) { | ||
801 | h = list_entry(list, struct cx8802_driver, devlist); | ||
802 | dprintk( 1, " ->driver\n"); | ||
803 | if (h->remove == NULL) { | ||
804 | printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__); | ||
805 | continue; | ||
806 | } | ||
807 | printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id); | ||
808 | cx8802_unregister_driver(h); | ||
809 | list_del(&dev->drvlist.devlist); | ||
810 | } | ||
811 | |||
812 | /* Destroy any 8802 reference. */ | ||
813 | dev->core->dvbdev = NULL; | ||
814 | |||
815 | /* common */ | ||
816 | cx8802_fini_common(dev); | ||
817 | cx88_core_put(dev->core,dev->pci); | ||
818 | kfree(dev); | ||
819 | } | ||
820 | |||
821 | static struct pci_device_id cx8802_pci_tbl[] = { | ||
822 | { | ||
823 | .vendor = 0x14f1, | ||
824 | .device = 0x8802, | ||
825 | .subvendor = PCI_ANY_ID, | ||
826 | .subdevice = PCI_ANY_ID, | ||
827 | },{ | ||
828 | /* --- end of list --- */ | ||
829 | } | ||
830 | }; | ||
831 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | ||
832 | |||
833 | static struct pci_driver cx8802_pci_driver = { | ||
834 | .name = "cx88-mpeg driver manager", | ||
835 | .id_table = cx8802_pci_tbl, | ||
836 | .probe = cx8802_probe, | ||
837 | .remove = __devexit_p(cx8802_remove), | ||
838 | }; | ||
839 | |||
840 | static int cx8802_init(void) | ||
841 | { | ||
842 | printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n", | ||
843 | (CX88_VERSION_CODE >> 16) & 0xff, | ||
844 | (CX88_VERSION_CODE >> 8) & 0xff, | ||
845 | CX88_VERSION_CODE & 0xff); | ||
846 | #ifdef SNAPSHOT | ||
847 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | ||
848 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | ||
849 | #endif | ||
850 | return pci_register_driver(&cx8802_pci_driver); | ||
851 | } | ||
852 | |||
853 | static void cx8802_fini(void) | ||
854 | { | ||
855 | pci_unregister_driver(&cx8802_pci_driver); | ||
856 | } | ||
857 | |||
858 | module_init(cx8802_init); | ||
859 | module_exit(cx8802_fini); | ||
547 | EXPORT_SYMBOL(cx8802_buf_prepare); | 860 | EXPORT_SYMBOL(cx8802_buf_prepare); |
548 | EXPORT_SYMBOL(cx8802_buf_queue); | 861 | EXPORT_SYMBOL(cx8802_buf_queue); |
549 | EXPORT_SYMBOL(cx8802_cancel_buffers); | 862 | EXPORT_SYMBOL(cx8802_cancel_buffers); |
@@ -551,9 +864,10 @@ EXPORT_SYMBOL(cx8802_cancel_buffers); | |||
551 | EXPORT_SYMBOL(cx8802_init_common); | 864 | EXPORT_SYMBOL(cx8802_init_common); |
552 | EXPORT_SYMBOL(cx8802_fini_common); | 865 | EXPORT_SYMBOL(cx8802_fini_common); |
553 | 866 | ||
554 | EXPORT_SYMBOL(cx8802_suspend_common); | 867 | EXPORT_SYMBOL(cx8802_register_driver); |
555 | EXPORT_SYMBOL(cx8802_resume_common); | 868 | EXPORT_SYMBOL(cx8802_unregister_driver); |
556 | 869 | EXPORT_SYMBOL(cx8802_get_device); | |
870 | EXPORT_SYMBOL(cx8802_get_driver); | ||
557 | /* ----------------------------------------------------------- */ | 871 | /* ----------------------------------------------------------- */ |
558 | /* | 872 | /* |
559 | * Local variables: | 873 | * Local variables: |
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 58ba9f773524..3482e0114d43 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c | |||
@@ -143,19 +143,6 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) | |||
143 | cx88_start_audio_dma(core); | 143 | cx88_start_audio_dma(core); |
144 | 144 | ||
145 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { | 145 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { |
146 | /* sets sound input from external adc */ | ||
147 | switch (core->board) { | ||
148 | case CX88_BOARD_HAUPPAUGE_ROSLYN: | ||
149 | case CX88_BOARD_KWORLD_MCE200_DELUXE: | ||
150 | case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT: | ||
151 | case CX88_BOARD_PIXELVIEW_PLAYTV_P7000: | ||
152 | case CX88_BOARD_ASUS_PVR_416: | ||
153 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); | ||
154 | break; | ||
155 | default: | ||
156 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); | ||
157 | } | ||
158 | |||
159 | cx_write(AUD_I2SINPUTCNTL, 4); | 146 | cx_write(AUD_I2SINPUTCNTL, 4); |
160 | cx_write(AUD_BAUDRATE, 1); | 147 | cx_write(AUD_BAUDRATE, 1); |
161 | /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ | 148 | /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 90e298d074d1..8613378428fd 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -454,6 +454,14 @@ static int video_mux(struct cx88_core *core, unsigned int input) | |||
454 | cx_clear(MO_FILTER_ODD, 0x00002020); | 454 | cx_clear(MO_FILTER_ODD, 0x00002020); |
455 | break; | 455 | break; |
456 | } | 456 | } |
457 | |||
458 | if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { | ||
459 | /* sets sound input from external adc */ | ||
460 | if (INPUT(input)->extadc) | ||
461 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); | ||
462 | else | ||
463 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); | ||
464 | } | ||
457 | return 0; | 465 | return 0; |
458 | } | 466 | } |
459 | 467 | ||
@@ -1490,6 +1498,30 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, | |||
1490 | mutex_unlock(&core->lock); | 1498 | mutex_unlock(&core->lock); |
1491 | return 0; | 1499 | return 0; |
1492 | } | 1500 | } |
1501 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1502 | /* ioctls to allow direct acces to the cx2388x registers */ | ||
1503 | case VIDIOC_INT_G_REGISTER: | ||
1504 | { | ||
1505 | struct v4l2_register *reg = arg; | ||
1506 | |||
1507 | if (reg->i2c_id != 0) | ||
1508 | return -EINVAL; | ||
1509 | /* cx2388x has a 24-bit register space */ | ||
1510 | reg->val = cx_read(reg->reg&0xffffff); | ||
1511 | return 0; | ||
1512 | } | ||
1513 | case VIDIOC_INT_S_REGISTER: | ||
1514 | { | ||
1515 | struct v4l2_register *reg = arg; | ||
1516 | |||
1517 | if (reg->i2c_id != 0) | ||
1518 | return -EINVAL; | ||
1519 | if (!capable(CAP_SYS_ADMIN)) | ||
1520 | return -EPERM; | ||
1521 | cx_write(reg->reg&0xffffff, reg->val); | ||
1522 | return 0; | ||
1523 | } | ||
1524 | #endif | ||
1493 | 1525 | ||
1494 | default: | 1526 | default: |
1495 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | 1527 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 3bc91aad4fe5..7054e941f1d7 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -74,6 +74,11 @@ enum cx88_board_type { | |||
74 | CX88_MPEG_BLACKBIRD | 74 | CX88_MPEG_BLACKBIRD |
75 | }; | 75 | }; |
76 | 76 | ||
77 | enum cx8802_board_access { | ||
78 | CX8802_DRVCTL_SHARED = 1, | ||
79 | CX8802_DRVCTL_EXCLUSIVE = 2, | ||
80 | }; | ||
81 | |||
77 | /* ----------------------------------------------------------- */ | 82 | /* ----------------------------------------------------------- */ |
78 | /* tv norms */ | 83 | /* tv norms */ |
79 | 84 | ||
@@ -220,6 +225,7 @@ struct cx88_input { | |||
220 | enum cx88_itype type; | 225 | enum cx88_itype type; |
221 | unsigned int vmux; | 226 | unsigned int vmux; |
222 | u32 gpio0, gpio1, gpio2, gpio3; | 227 | u32 gpio0, gpio1, gpio2, gpio3; |
228 | unsigned int extadc:1; | ||
223 | }; | 229 | }; |
224 | 230 | ||
225 | struct cx88_board { | 231 | struct cx88_board { |
@@ -330,6 +336,7 @@ struct cx88_core { | |||
330 | 336 | ||
331 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ | 337 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ |
332 | struct cx8802_dev *dvbdev; | 338 | struct cx8802_dev *dvbdev; |
339 | enum cx88_board_type active_type_id; | ||
333 | }; | 340 | }; |
334 | 341 | ||
335 | struct cx8800_dev; | 342 | struct cx8800_dev; |
@@ -405,6 +412,31 @@ struct cx8802_suspend_state { | |||
405 | int disabled; | 412 | int disabled; |
406 | }; | 413 | }; |
407 | 414 | ||
415 | struct cx8802_driver { | ||
416 | struct cx88_core *core; | ||
417 | struct list_head devlist; | ||
418 | |||
419 | /* Type of driver and access required */ | ||
420 | enum cx88_board_type type_id; | ||
421 | enum cx8802_board_access hw_access; | ||
422 | |||
423 | /* MPEG 8802 internal only */ | ||
424 | int (*suspend)(struct pci_dev *pci_dev, pm_message_t state); | ||
425 | int (*resume)(struct pci_dev *pci_dev); | ||
426 | |||
427 | /* MPEG 8802 -> mini driver - Driver probe and configuration */ | ||
428 | int (*probe)(struct cx8802_driver *drv); | ||
429 | int (*remove)(struct cx8802_driver *drv); | ||
430 | |||
431 | /* MPEG 8802 -> mini driver - Access for hardware control */ | ||
432 | int (*advise_acquire)(struct cx8802_driver *drv); | ||
433 | int (*advise_release)(struct cx8802_driver *drv); | ||
434 | |||
435 | /* MPEG 8802 <- mini driver - Access for hardware control */ | ||
436 | int (*request_acquire)(struct cx8802_driver *drv); | ||
437 | int (*request_release)(struct cx8802_driver *drv); | ||
438 | }; | ||
439 | |||
408 | struct cx8802_dev { | 440 | struct cx8802_dev { |
409 | struct cx88_core *core; | 441 | struct cx88_core *core; |
410 | spinlock_t slock; | 442 | spinlock_t slock; |
@@ -439,6 +471,9 @@ struct cx8802_dev { | |||
439 | 471 | ||
440 | /* mpeg params */ | 472 | /* mpeg params */ |
441 | struct cx2341x_mpeg_params params; | 473 | struct cx2341x_mpeg_params params; |
474 | |||
475 | /* List of attached drivers */ | ||
476 | struct cx8802_driver drvlist; | ||
442 | }; | 477 | }; |
443 | 478 | ||
444 | /* ----------------------------------------------------------- */ | 479 | /* ----------------------------------------------------------- */ |
@@ -571,6 +606,11 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t); | |||
571 | void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual); | 606 | void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual); |
572 | int cx88_audio_thread(void *data); | 607 | int cx88_audio_thread(void *data); |
573 | 608 | ||
609 | int cx8802_register_driver(struct cx8802_driver *drv); | ||
610 | int cx8802_unregister_driver(struct cx8802_driver *drv); | ||
611 | struct cx8802_dev * cx8802_get_device(struct inode *inode); | ||
612 | struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype); | ||
613 | |||
574 | /* ----------------------------------------------------------- */ | 614 | /* ----------------------------------------------------------- */ |
575 | /* cx88-input.c */ | 615 | /* cx88-input.c */ |
576 | 616 | ||
@@ -600,6 +640,13 @@ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, | |||
600 | extern const u32 cx88_user_ctrls[]; | 640 | extern const u32 cx88_user_ctrls[]; |
601 | extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); | 641 | extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); |
602 | 642 | ||
643 | /* ----------------------------------------------------------- */ | ||
644 | /* cx88-blackbird.c */ | ||
645 | /* used by cx88-ivtv ioctl emulation layer */ | ||
646 | extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, | ||
647 | unsigned int cmd, void *arg); | ||
648 | extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd); | ||
649 | |||
603 | /* | 650 | /* |
604 | * Local variables: | 651 | * Local variables: |
605 | * c-basic-offset: 8 | 652 | * c-basic-offset: 8 |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index ab87e7bfe84f..59edf58204de 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -305,15 +305,14 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
305 | int ir_type; | 305 | int ir_type; |
306 | struct IR_i2c *ir; | 306 | struct IR_i2c *ir; |
307 | struct input_dev *input_dev; | 307 | struct input_dev *input_dev; |
308 | int err; | ||
308 | 309 | ||
309 | ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); | 310 | ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); |
310 | input_dev = input_allocate_device(); | 311 | input_dev = input_allocate_device(); |
311 | if (!ir || !input_dev) { | 312 | if (!ir || !input_dev) { |
312 | input_free_device(input_dev); | 313 | err = -ENOMEM; |
313 | kfree(ir); | 314 | goto err_out_free; |
314 | return -ENOMEM; | ||
315 | } | 315 | } |
316 | memset(ir,0,sizeof(*ir)); | ||
317 | 316 | ||
318 | ir->c = client_template; | 317 | ir->c = client_template; |
319 | ir->input = input_dev; | 318 | ir->input = input_dev; |
@@ -355,32 +354,34 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
355 | break; | 354 | break; |
356 | case 0x7a: | 355 | case 0x7a: |
357 | case 0x47: | 356 | case 0x47: |
357 | case 0x71: | ||
358 | /* Handled by saa7134-input */ | 358 | /* Handled by saa7134-input */ |
359 | name = "SAA713x remote"; | 359 | name = "SAA713x remote"; |
360 | ir_type = IR_TYPE_OTHER; | 360 | ir_type = IR_TYPE_OTHER; |
361 | break; | 361 | break; |
362 | default: | 362 | default: |
363 | /* shouldn't happen */ | 363 | /* shouldn't happen */ |
364 | printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr); | 364 | printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr); |
365 | kfree(ir); | 365 | err = -ENODEV; |
366 | return -1; | 366 | goto err_out_free; |
367 | } | 367 | } |
368 | 368 | ||
369 | /* Sets name */ | 369 | /* Sets name */ |
370 | snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); | 370 | snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); |
371 | ir->ir_codes=ir_codes; | 371 | ir->ir_codes = ir_codes; |
372 | 372 | ||
373 | /* register i2c device | 373 | /* register i2c device |
374 | * At device register, IR codes may be changed to be | 374 | * At device register, IR codes may be changed to be |
375 | * board dependent. | 375 | * board dependent. |
376 | */ | 376 | */ |
377 | i2c_attach_client(&ir->c); | 377 | err = i2c_attach_client(&ir->c); |
378 | if (err) | ||
379 | goto err_out_free; | ||
378 | 380 | ||
379 | /* If IR not supported or disabled, unregisters driver */ | 381 | /* If IR not supported or disabled, unregisters driver */ |
380 | if (ir->get_key == NULL) { | 382 | if (ir->get_key == NULL) { |
381 | i2c_detach_client(&ir->c); | 383 | err = -ENODEV; |
382 | kfree(ir); | 384 | goto err_out_detach; |
383 | return -1; | ||
384 | } | 385 | } |
385 | 386 | ||
386 | /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */ | 387 | /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */ |
@@ -389,15 +390,17 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
389 | ir->c.dev.bus_id); | 390 | ir->c.dev.bus_id); |
390 | 391 | ||
391 | /* init + register input device */ | 392 | /* init + register input device */ |
392 | ir_input_init(input_dev,&ir->ir,ir_type,ir->ir_codes); | 393 | ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); |
393 | input_dev->id.bustype = BUS_I2C; | 394 | input_dev->id.bustype = BUS_I2C; |
394 | input_dev->name = ir->c.name; | 395 | input_dev->name = ir->c.name; |
395 | input_dev->phys = ir->phys; | 396 | input_dev->phys = ir->phys; |
396 | 397 | ||
397 | /* register event device */ | 398 | err = input_register_device(ir->input); |
398 | input_register_device(ir->input); | 399 | if (err) |
400 | goto err_out_detach; | ||
401 | |||
399 | printk(DEVNAME ": %s detected at %s [%s]\n", | 402 | printk(DEVNAME ": %s detected at %s [%s]\n", |
400 | ir->input->name,ir->input->phys,adap->name); | 403 | ir->input->name, ir->input->phys, adap->name); |
401 | 404 | ||
402 | /* start polling via eventd */ | 405 | /* start polling via eventd */ |
403 | INIT_WORK(&ir->work, ir_work); | 406 | INIT_WORK(&ir->work, ir_work); |
@@ -407,6 +410,13 @@ static int ir_attach(struct i2c_adapter *adap, int addr, | |||
407 | schedule_work(&ir->work); | 410 | schedule_work(&ir->work); |
408 | 411 | ||
409 | return 0; | 412 | return 0; |
413 | |||
414 | err_out_detach: | ||
415 | i2c_detach_client(&ir->c); | ||
416 | err_out_free: | ||
417 | input_free_device(input_dev); | ||
418 | kfree(ir); | ||
419 | return err; | ||
410 | } | 420 | } |
411 | 421 | ||
412 | static int ir_detach(struct i2c_client *client) | 422 | static int ir_detach(struct i2c_client *client) |
@@ -414,7 +424,7 @@ static int ir_detach(struct i2c_client *client) | |||
414 | struct IR_i2c *ir = i2c_get_clientdata(client); | 424 | struct IR_i2c *ir = i2c_get_clientdata(client); |
415 | 425 | ||
416 | /* kill outstanding polls */ | 426 | /* kill outstanding polls */ |
417 | del_timer(&ir->timer); | 427 | del_timer_sync(&ir->timer); |
418 | flush_scheduled_work(); | 428 | flush_scheduled_work(); |
419 | 429 | ||
420 | /* unregister devices */ | 430 | /* unregister devices */ |
@@ -439,7 +449,7 @@ static int ir_probe(struct i2c_adapter *adap) | |||
439 | */ | 449 | */ |
440 | 450 | ||
441 | static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; | 451 | static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; |
442 | static const int probe_saa7134[] = { 0x7a, 0x47, -1 }; | 452 | static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 }; |
443 | static const int probe_em28XX[] = { 0x30, 0x47, -1 }; | 453 | static const int probe_em28XX[] = { 0x30, 0x47, -1 }; |
444 | const int *probe = NULL; | 454 | const int *probe = NULL; |
445 | struct i2c_client c; | 455 | struct i2c_client c; |
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index b0aea4002d11..152cc6b3e152 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c | |||
@@ -160,10 +160,6 @@ static int mxb_probe(struct saa7146_dev* dev) | |||
160 | printk("mxb: saa7111 i2c module not available.\n"); | 160 | printk("mxb: saa7111 i2c module not available.\n"); |
161 | return -ENODEV; | 161 | return -ENODEV; |
162 | } | 162 | } |
163 | if ((result = request_module("tuner")) < 0) { | ||
164 | printk("mxb: tuner i2c module not available.\n"); | ||
165 | return -ENODEV; | ||
166 | } | ||
167 | if ((result = request_module("tea6420")) < 0) { | 163 | if ((result = request_module("tea6420")) < 0) { |
168 | printk("mxb: tea6420 i2c module not available.\n"); | 164 | printk("mxb: tea6420 i2c module not available.\n"); |
169 | return -ENODEV; | 165 | return -ENODEV; |
@@ -176,6 +172,10 @@ static int mxb_probe(struct saa7146_dev* dev) | |||
176 | printk("mxb: tda9840 i2c module not available.\n"); | 172 | printk("mxb: tda9840 i2c module not available.\n"); |
177 | return -ENODEV; | 173 | return -ENODEV; |
178 | } | 174 | } |
175 | if ((result = request_module("tuner")) < 0) { | ||
176 | printk("mxb: tuner i2c module not available.\n"); | ||
177 | return -ENODEV; | ||
178 | } | ||
179 | 179 | ||
180 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); | 180 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); |
181 | if( NULL == mxb ) { | 181 | if( NULL == mxb ) { |
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c new file mode 100644 index 000000000000..89dd18c3c5cc --- /dev/null +++ b/drivers/media/video/ov7670.c | |||
@@ -0,0 +1,1333 @@ | |||
1 | /* | ||
2 | * A V4L2 driver for OmniVision OV7670 cameras. | ||
3 | * | ||
4 | * Copyright 2006 One Laptop Per Child Association, Inc. Written | ||
5 | * by Jonathan Corbet with substantial inspiration from Mark | ||
6 | * McClelland's ovcamchip code. | ||
7 | * | ||
8 | * This file may be distributed under the terms of the GNU General | ||
9 | * Public License, version 2. | ||
10 | */ | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/videodev.h> | ||
17 | #include <media/v4l2-common.h> | ||
18 | #include <linux/i2c.h> | ||
19 | |||
20 | |||
21 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net."); | ||
22 | MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors"); | ||
23 | MODULE_LICENSE("GPL"); | ||
24 | |||
25 | /* | ||
26 | * Basic window sizes. These probably belong somewhere more globally | ||
27 | * useful. | ||
28 | */ | ||
29 | #define VGA_WIDTH 640 | ||
30 | #define VGA_HEIGHT 480 | ||
31 | #define QVGA_WIDTH 320 | ||
32 | #define QVGA_HEIGHT 240 | ||
33 | #define CIF_WIDTH 352 | ||
34 | #define CIF_HEIGHT 288 | ||
35 | #define QCIF_WIDTH 176 | ||
36 | #define QCIF_HEIGHT 144 | ||
37 | |||
38 | /* | ||
39 | * Our nominal (default) frame rate. | ||
40 | */ | ||
41 | #define OV7670_FRAME_RATE 30 | ||
42 | |||
43 | /* | ||
44 | * The 7670 sits on i2c with ID 0x42 | ||
45 | */ | ||
46 | #define OV7670_I2C_ADDR 0x42 | ||
47 | |||
48 | /* Registers */ | ||
49 | #define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ | ||
50 | #define REG_BLUE 0x01 /* blue gain */ | ||
51 | #define REG_RED 0x02 /* red gain */ | ||
52 | #define REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ | ||
53 | #define REG_COM1 0x04 /* Control 1 */ | ||
54 | #define COM1_CCIR656 0x40 /* CCIR656 enable */ | ||
55 | #define REG_BAVE 0x05 /* U/B Average level */ | ||
56 | #define REG_GbAVE 0x06 /* Y/Gb Average level */ | ||
57 | #define REG_AECHH 0x07 /* AEC MS 5 bits */ | ||
58 | #define REG_RAVE 0x08 /* V/R Average level */ | ||
59 | #define REG_COM2 0x09 /* Control 2 */ | ||
60 | #define COM2_SSLEEP 0x10 /* Soft sleep mode */ | ||
61 | #define REG_PID 0x0a /* Product ID MSB */ | ||
62 | #define REG_VER 0x0b /* Product ID LSB */ | ||
63 | #define REG_COM3 0x0c /* Control 3 */ | ||
64 | #define COM3_SWAP 0x40 /* Byte swap */ | ||
65 | #define COM3_SCALEEN 0x08 /* Enable scaling */ | ||
66 | #define COM3_DCWEN 0x04 /* Enable downsamp/crop/window */ | ||
67 | #define REG_COM4 0x0d /* Control 4 */ | ||
68 | #define REG_COM5 0x0e /* All "reserved" */ | ||
69 | #define REG_COM6 0x0f /* Control 6 */ | ||
70 | #define REG_AECH 0x10 /* More bits of AEC value */ | ||
71 | #define REG_CLKRC 0x11 /* Clocl control */ | ||
72 | #define CLK_EXT 0x40 /* Use external clock directly */ | ||
73 | #define CLK_SCALE 0x3f /* Mask for internal clock scale */ | ||
74 | #define REG_COM7 0x12 /* Control 7 */ | ||
75 | #define COM7_RESET 0x80 /* Register reset */ | ||
76 | #define COM7_FMT_MASK 0x38 | ||
77 | #define COM7_FMT_VGA 0x00 | ||
78 | #define COM7_FMT_CIF 0x20 /* CIF format */ | ||
79 | #define COM7_FMT_QVGA 0x10 /* QVGA format */ | ||
80 | #define COM7_FMT_QCIF 0x08 /* QCIF format */ | ||
81 | #define COM7_RGB 0x04 /* bits 0 and 2 - RGB format */ | ||
82 | #define COM7_YUV 0x00 /* YUV */ | ||
83 | #define COM7_BAYER 0x01 /* Bayer format */ | ||
84 | #define COM7_PBAYER 0x05 /* "Processed bayer" */ | ||
85 | #define REG_COM8 0x13 /* Control 8 */ | ||
86 | #define COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ | ||
87 | #define COM8_AECSTEP 0x40 /* Unlimited AEC step size */ | ||
88 | #define COM8_BFILT 0x20 /* Band filter enable */ | ||
89 | #define COM8_AGC 0x04 /* Auto gain enable */ | ||
90 | #define COM8_AWB 0x02 /* White balance enable */ | ||
91 | #define COM8_AEC 0x01 /* Auto exposure enable */ | ||
92 | #define REG_COM9 0x14 /* Control 9 - gain ceiling */ | ||
93 | #define REG_COM10 0x15 /* Control 10 */ | ||
94 | #define COM10_HSYNC 0x40 /* HSYNC instead of HREF */ | ||
95 | #define COM10_PCLK_HB 0x20 /* Suppress PCLK on horiz blank */ | ||
96 | #define COM10_HREF_REV 0x08 /* Reverse HREF */ | ||
97 | #define COM10_VS_LEAD 0x04 /* VSYNC on clock leading edge */ | ||
98 | #define COM10_VS_NEG 0x02 /* VSYNC negative */ | ||
99 | #define COM10_HS_NEG 0x01 /* HSYNC negative */ | ||
100 | #define REG_HSTART 0x17 /* Horiz start high bits */ | ||
101 | #define REG_HSTOP 0x18 /* Horiz stop high bits */ | ||
102 | #define REG_VSTART 0x19 /* Vert start high bits */ | ||
103 | #define REG_VSTOP 0x1a /* Vert stop high bits */ | ||
104 | #define REG_PSHFT 0x1b /* Pixel delay after HREF */ | ||
105 | #define REG_MIDH 0x1c /* Manuf. ID high */ | ||
106 | #define REG_MIDL 0x1d /* Manuf. ID low */ | ||
107 | #define REG_MVFP 0x1e /* Mirror / vflip */ | ||
108 | #define MVFP_MIRROR 0x20 /* Mirror image */ | ||
109 | #define MVFP_FLIP 0x10 /* Vertical flip */ | ||
110 | |||
111 | #define REG_AEW 0x24 /* AGC upper limit */ | ||
112 | #define REG_AEB 0x25 /* AGC lower limit */ | ||
113 | #define REG_VPT 0x26 /* AGC/AEC fast mode op region */ | ||
114 | #define REG_HSYST 0x30 /* HSYNC rising edge delay */ | ||
115 | #define REG_HSYEN 0x31 /* HSYNC falling edge delay */ | ||
116 | #define REG_HREF 0x32 /* HREF pieces */ | ||
117 | #define REG_TSLB 0x3a /* lots of stuff */ | ||
118 | #define TSLB_YLAST 0x04 /* UYVY or VYUY - see com13 */ | ||
119 | #define REG_COM11 0x3b /* Control 11 */ | ||
120 | #define COM11_NIGHT 0x80 /* NIght mode enable */ | ||
121 | #define COM11_NMFR 0x60 /* Two bit NM frame rate */ | ||
122 | #define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ | ||
123 | #define COM11_50HZ 0x08 /* Manual 50Hz select */ | ||
124 | #define COM11_EXP 0x02 | ||
125 | #define REG_COM12 0x3c /* Control 12 */ | ||
126 | #define COM12_HREF 0x80 /* HREF always */ | ||
127 | #define REG_COM13 0x3d /* Control 13 */ | ||
128 | #define COM13_GAMMA 0x80 /* Gamma enable */ | ||
129 | #define COM13_UVSAT 0x40 /* UV saturation auto adjustment */ | ||
130 | #define COM13_UVSWAP 0x01 /* V before U - w/TSLB */ | ||
131 | #define REG_COM14 0x3e /* Control 14 */ | ||
132 | #define COM14_DCWEN 0x10 /* DCW/PCLK-scale enable */ | ||
133 | #define REG_EDGE 0x3f /* Edge enhancement factor */ | ||
134 | #define REG_COM15 0x40 /* Control 15 */ | ||
135 | #define COM15_R10F0 0x00 /* Data range 10 to F0 */ | ||
136 | #define COM15_R01FE 0x80 /* 01 to FE */ | ||
137 | #define COM15_R00FF 0xc0 /* 00 to FF */ | ||
138 | #define COM15_RGB565 0x10 /* RGB565 output */ | ||
139 | #define COM15_RGB555 0x30 /* RGB555 output */ | ||
140 | #define REG_COM16 0x41 /* Control 16 */ | ||
141 | #define COM16_AWBGAIN 0x08 /* AWB gain enable */ | ||
142 | #define REG_COM17 0x42 /* Control 17 */ | ||
143 | #define COM17_AECWIN 0xc0 /* AEC window - must match COM4 */ | ||
144 | #define COM17_CBAR 0x08 /* DSP Color bar */ | ||
145 | |||
146 | /* | ||
147 | * This matrix defines how the colors are generated, must be | ||
148 | * tweaked to adjust hue and saturation. | ||
149 | * | ||
150 | * Order: v-red, v-green, v-blue, u-red, u-green, u-blue | ||
151 | * | ||
152 | * They are nine-bit signed quantities, with the sign bit | ||
153 | * stored in 0x58. Sign for v-red is bit 0, and up from there. | ||
154 | */ | ||
155 | #define REG_CMATRIX_BASE 0x4f | ||
156 | #define CMATRIX_LEN 6 | ||
157 | #define REG_CMATRIX_SIGN 0x58 | ||
158 | |||
159 | |||
160 | #define REG_BRIGHT 0x55 /* Brightness */ | ||
161 | #define REG_CONTRAS 0x56 /* Contrast control */ | ||
162 | |||
163 | #define REG_GFIX 0x69 /* Fix gain control */ | ||
164 | |||
165 | #define REG_RGB444 0x8c /* RGB 444 control */ | ||
166 | #define R444_ENABLE 0x02 /* Turn on RGB444, overrides 5x5 */ | ||
167 | #define R444_RGBX 0x01 /* Empty nibble at end */ | ||
168 | |||
169 | #define REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ | ||
170 | #define REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ | ||
171 | |||
172 | #define REG_BD50MAX 0xa5 /* 50hz banding step limit */ | ||
173 | #define REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ | ||
174 | #define REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ | ||
175 | #define REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ | ||
176 | #define REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ | ||
177 | #define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ | ||
178 | #define REG_BD60MAX 0xab /* 60hz banding step limit */ | ||
179 | |||
180 | |||
181 | /* | ||
182 | * Information we maintain about a known sensor. | ||
183 | */ | ||
184 | struct ov7670_format_struct; /* coming later */ | ||
185 | struct ov7670_info { | ||
186 | struct ov7670_format_struct *fmt; /* Current format */ | ||
187 | unsigned char sat; /* Saturation value */ | ||
188 | int hue; /* Hue value */ | ||
189 | }; | ||
190 | |||
191 | |||
192 | |||
193 | |||
194 | /* | ||
195 | * The default register settings, as obtained from OmniVision. There | ||
196 | * is really no making sense of most of these - lots of "reserved" values | ||
197 | * and such. | ||
198 | * | ||
199 | * These settings give VGA YUYV. | ||
200 | */ | ||
201 | |||
202 | struct regval_list { | ||
203 | unsigned char reg_num; | ||
204 | unsigned char value; | ||
205 | }; | ||
206 | |||
207 | static struct regval_list ov7670_default_regs[] = { | ||
208 | { REG_COM7, COM7_RESET }, | ||
209 | /* | ||
210 | * Clock scale: 3 = 15fps | ||
211 | * 2 = 20fps | ||
212 | * 1 = 30fps | ||
213 | */ | ||
214 | { REG_CLKRC, 0x1 }, /* OV: clock scale (30 fps) */ | ||
215 | { REG_TSLB, 0x04 }, /* OV */ | ||
216 | { REG_COM7, 0 }, /* VGA */ | ||
217 | /* | ||
218 | * Set the hardware window. These values from OV don't entirely | ||
219 | * make sense - hstop is less than hstart. But they work... | ||
220 | */ | ||
221 | { REG_HSTART, 0x13 }, { REG_HSTOP, 0x01 }, | ||
222 | { REG_HREF, 0xb6 }, { REG_VSTART, 0x02 }, | ||
223 | { REG_VSTOP, 0x7a }, { REG_VREF, 0x0a }, | ||
224 | |||
225 | { REG_COM3, 0 }, { REG_COM14, 0 }, | ||
226 | /* Mystery scaling numbers */ | ||
227 | { 0x70, 0x3a }, { 0x71, 0x35 }, | ||
228 | { 0x72, 0x11 }, { 0x73, 0xf0 }, | ||
229 | { 0xa2, 0x02 }, { REG_COM10, 0x0 }, | ||
230 | |||
231 | /* Gamma curve values */ | ||
232 | { 0x7a, 0x20 }, { 0x7b, 0x10 }, | ||
233 | { 0x7c, 0x1e }, { 0x7d, 0x35 }, | ||
234 | { 0x7e, 0x5a }, { 0x7f, 0x69 }, | ||
235 | { 0x80, 0x76 }, { 0x81, 0x80 }, | ||
236 | { 0x82, 0x88 }, { 0x83, 0x8f }, | ||
237 | { 0x84, 0x96 }, { 0x85, 0xa3 }, | ||
238 | { 0x86, 0xaf }, { 0x87, 0xc4 }, | ||
239 | { 0x88, 0xd7 }, { 0x89, 0xe8 }, | ||
240 | |||
241 | /* AGC and AEC parameters. Note we start by disabling those features, | ||
242 | then turn them only after tweaking the values. */ | ||
243 | { REG_COM8, COM8_FASTAEC | COM8_AECSTEP | COM8_BFILT }, | ||
244 | { REG_GAIN, 0 }, { REG_AECH, 0 }, | ||
245 | { REG_COM4, 0x40 }, /* magic reserved bit */ | ||
246 | { REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ | ||
247 | { REG_BD50MAX, 0x05 }, { REG_BD60MAX, 0x07 }, | ||
248 | { REG_AEW, 0x95 }, { REG_AEB, 0x33 }, | ||
249 | { REG_VPT, 0xe3 }, { REG_HAECC1, 0x78 }, | ||
250 | { REG_HAECC2, 0x68 }, { 0xa1, 0x03 }, /* magic */ | ||
251 | { REG_HAECC3, 0xd8 }, { REG_HAECC4, 0xd8 }, | ||
252 | { REG_HAECC5, 0xf0 }, { REG_HAECC6, 0x90 }, | ||
253 | { REG_HAECC7, 0x94 }, | ||
254 | { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC }, | ||
255 | |||
256 | /* Almost all of these are magic "reserved" values. */ | ||
257 | { REG_COM5, 0x61 }, { REG_COM6, 0x4b }, | ||
258 | { 0x16, 0x02 }, { REG_MVFP, 0x07|MVFP_MIRROR }, | ||
259 | { 0x21, 0x02 }, { 0x22, 0x91 }, | ||
260 | { 0x29, 0x07 }, { 0x33, 0x0b }, | ||
261 | { 0x35, 0x0b }, { 0x37, 0x1d }, | ||
262 | { 0x38, 0x71 }, { 0x39, 0x2a }, | ||
263 | { REG_COM12, 0x78 }, { 0x4d, 0x40 }, | ||
264 | { 0x4e, 0x20 }, { REG_GFIX, 0 }, | ||
265 | { 0x6b, 0x4a }, { 0x74, 0x10 }, | ||
266 | { 0x8d, 0x4f }, { 0x8e, 0 }, | ||
267 | { 0x8f, 0 }, { 0x90, 0 }, | ||
268 | { 0x91, 0 }, { 0x96, 0 }, | ||
269 | { 0x9a, 0 }, { 0xb0, 0x84 }, | ||
270 | { 0xb1, 0x0c }, { 0xb2, 0x0e }, | ||
271 | { 0xb3, 0x82 }, { 0xb8, 0x0a }, | ||
272 | |||
273 | /* More reserved magic, some of which tweaks white balance */ | ||
274 | { 0x43, 0x0a }, { 0x44, 0xf0 }, | ||
275 | { 0x45, 0x34 }, { 0x46, 0x58 }, | ||
276 | { 0x47, 0x28 }, { 0x48, 0x3a }, | ||
277 | { 0x59, 0x88 }, { 0x5a, 0x88 }, | ||
278 | { 0x5b, 0x44 }, { 0x5c, 0x67 }, | ||
279 | { 0x5d, 0x49 }, { 0x5e, 0x0e }, | ||
280 | { 0x6c, 0x0a }, { 0x6d, 0x55 }, | ||
281 | { 0x6e, 0x11 }, { 0x6f, 0x9f }, /* "9e for advance AWB" */ | ||
282 | { 0x6a, 0x40 }, { REG_BLUE, 0x40 }, | ||
283 | { REG_RED, 0x60 }, | ||
284 | { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC|COM8_AWB }, | ||
285 | |||
286 | /* Matrix coefficients */ | ||
287 | { 0x4f, 0x80 }, { 0x50, 0x80 }, | ||
288 | { 0x51, 0 }, { 0x52, 0x22 }, | ||
289 | { 0x53, 0x5e }, { 0x54, 0x80 }, | ||
290 | { 0x58, 0x9e }, | ||
291 | |||
292 | { REG_COM16, COM16_AWBGAIN }, { REG_EDGE, 0 }, | ||
293 | { 0x75, 0x05 }, { 0x76, 0xe1 }, | ||
294 | { 0x4c, 0 }, { 0x77, 0x01 }, | ||
295 | { REG_COM13, 0xc3 }, { 0x4b, 0x09 }, | ||
296 | { 0xc9, 0x60 }, { REG_COM16, 0x38 }, | ||
297 | { 0x56, 0x40 }, | ||
298 | |||
299 | { 0x34, 0x11 }, { REG_COM11, COM11_EXP|COM11_HZAUTO }, | ||
300 | { 0xa4, 0x88 }, { 0x96, 0 }, | ||
301 | { 0x97, 0x30 }, { 0x98, 0x20 }, | ||
302 | { 0x99, 0x30 }, { 0x9a, 0x84 }, | ||
303 | { 0x9b, 0x29 }, { 0x9c, 0x03 }, | ||
304 | { 0x9d, 0x4c }, { 0x9e, 0x3f }, | ||
305 | { 0x78, 0x04 }, | ||
306 | |||
307 | /* Extra-weird stuff. Some sort of multiplexor register */ | ||
308 | { 0x79, 0x01 }, { 0xc8, 0xf0 }, | ||
309 | { 0x79, 0x0f }, { 0xc8, 0x00 }, | ||
310 | { 0x79, 0x10 }, { 0xc8, 0x7e }, | ||
311 | { 0x79, 0x0a }, { 0xc8, 0x80 }, | ||
312 | { 0x79, 0x0b }, { 0xc8, 0x01 }, | ||
313 | { 0x79, 0x0c }, { 0xc8, 0x0f }, | ||
314 | { 0x79, 0x0d }, { 0xc8, 0x20 }, | ||
315 | { 0x79, 0x09 }, { 0xc8, 0x80 }, | ||
316 | { 0x79, 0x02 }, { 0xc8, 0xc0 }, | ||
317 | { 0x79, 0x03 }, { 0xc8, 0x40 }, | ||
318 | { 0x79, 0x05 }, { 0xc8, 0x30 }, | ||
319 | { 0x79, 0x26 }, | ||
320 | |||
321 | { 0xff, 0xff }, /* END MARKER */ | ||
322 | }; | ||
323 | |||
324 | |||
325 | /* | ||
326 | * Here we'll try to encapsulate the changes for just the output | ||
327 | * video format. | ||
328 | * | ||
329 | * RGB656 and YUV422 come from OV; RGB444 is homebrewed. | ||
330 | * | ||
331 | * IMPORTANT RULE: the first entry must be for COM7, see ov7670_s_fmt for why. | ||
332 | */ | ||
333 | |||
334 | |||
335 | static struct regval_list ov7670_fmt_yuv422[] = { | ||
336 | { REG_COM7, 0x0 }, /* Selects YUV mode */ | ||
337 | { REG_RGB444, 0 }, /* No RGB444 please */ | ||
338 | { REG_COM1, 0 }, | ||
339 | { REG_COM15, COM15_R00FF }, | ||
340 | { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */ | ||
341 | { 0x4f, 0x80 }, /* "matrix coefficient 1" */ | ||
342 | { 0x50, 0x80 }, /* "matrix coefficient 2" */ | ||
343 | { 0x51, 0 }, /* vb */ | ||
344 | { 0x52, 0x22 }, /* "matrix coefficient 4" */ | ||
345 | { 0x53, 0x5e }, /* "matrix coefficient 5" */ | ||
346 | { 0x54, 0x80 }, /* "matrix coefficient 6" */ | ||
347 | { REG_COM13, COM13_GAMMA|COM13_UVSAT }, | ||
348 | { 0xff, 0xff }, | ||
349 | }; | ||
350 | |||
351 | static struct regval_list ov7670_fmt_rgb565[] = { | ||
352 | { REG_COM7, COM7_RGB }, /* Selects RGB mode */ | ||
353 | { REG_RGB444, 0 }, /* No RGB444 please */ | ||
354 | { REG_COM1, 0x0 }, | ||
355 | { REG_COM15, COM15_RGB565 }, | ||
356 | { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ | ||
357 | { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ | ||
358 | { 0x50, 0xb3 }, /* "matrix coefficient 2" */ | ||
359 | { 0x51, 0 }, /* vb */ | ||
360 | { 0x52, 0x3d }, /* "matrix coefficient 4" */ | ||
361 | { 0x53, 0xa7 }, /* "matrix coefficient 5" */ | ||
362 | { 0x54, 0xe4 }, /* "matrix coefficient 6" */ | ||
363 | { REG_COM13, COM13_GAMMA|COM13_UVSAT }, | ||
364 | { 0xff, 0xff }, | ||
365 | }; | ||
366 | |||
367 | static struct regval_list ov7670_fmt_rgb444[] = { | ||
368 | { REG_COM7, COM7_RGB }, /* Selects RGB mode */ | ||
369 | { REG_RGB444, R444_ENABLE }, /* Enable xxxxrrrr ggggbbbb */ | ||
370 | { REG_COM1, 0x40 }, /* Magic reserved bit */ | ||
371 | { REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */ | ||
372 | { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ | ||
373 | { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ | ||
374 | { 0x50, 0xb3 }, /* "matrix coefficient 2" */ | ||
375 | { 0x51, 0 }, /* vb */ | ||
376 | { 0x52, 0x3d }, /* "matrix coefficient 4" */ | ||
377 | { 0x53, 0xa7 }, /* "matrix coefficient 5" */ | ||
378 | { 0x54, 0xe4 }, /* "matrix coefficient 6" */ | ||
379 | { REG_COM13, COM13_GAMMA|COM13_UVSAT|0x2 }, /* Magic rsvd bit */ | ||
380 | { 0xff, 0xff }, | ||
381 | }; | ||
382 | |||
383 | |||
384 | |||
385 | |||
386 | /* | ||
387 | * Low-level register I/O. | ||
388 | */ | ||
389 | |||
390 | static int ov7670_read(struct i2c_client *c, unsigned char reg, | ||
391 | unsigned char *value) | ||
392 | { | ||
393 | int ret; | ||
394 | |||
395 | ret = i2c_smbus_read_byte_data(c, reg); | ||
396 | if (ret >= 0) | ||
397 | *value = (unsigned char) ret; | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | |||
402 | static int ov7670_write(struct i2c_client *c, unsigned char reg, | ||
403 | unsigned char value) | ||
404 | { | ||
405 | return i2c_smbus_write_byte_data(c, reg, value); | ||
406 | } | ||
407 | |||
408 | |||
409 | /* | ||
410 | * Write a list of register settings; ff/ff stops the process. | ||
411 | */ | ||
412 | static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals) | ||
413 | { | ||
414 | while (vals->reg_num != 0xff || vals->value != 0xff) { | ||
415 | int ret = ov7670_write(c, vals->reg_num, vals->value); | ||
416 | if (ret < 0) | ||
417 | return ret; | ||
418 | vals++; | ||
419 | } | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | |||
424 | /* | ||
425 | * Stuff that knows about the sensor. | ||
426 | */ | ||
427 | static void ov7670_reset(struct i2c_client *client) | ||
428 | { | ||
429 | ov7670_write(client, REG_COM7, COM7_RESET); | ||
430 | msleep(1); | ||
431 | } | ||
432 | |||
433 | |||
434 | static int ov7670_init(struct i2c_client *client) | ||
435 | { | ||
436 | return ov7670_write_array(client, ov7670_default_regs); | ||
437 | } | ||
438 | |||
439 | |||
440 | |||
441 | static int ov7670_detect(struct i2c_client *client) | ||
442 | { | ||
443 | unsigned char v; | ||
444 | int ret; | ||
445 | |||
446 | ret = ov7670_init(client); | ||
447 | if (ret < 0) | ||
448 | return ret; | ||
449 | ret = ov7670_read(client, REG_MIDH, &v); | ||
450 | if (ret < 0) | ||
451 | return ret; | ||
452 | if (v != 0x7f) /* OV manuf. id. */ | ||
453 | return -ENODEV; | ||
454 | ret = ov7670_read(client, REG_MIDL, &v); | ||
455 | if (ret < 0) | ||
456 | return ret; | ||
457 | if (v != 0xa2) | ||
458 | return -ENODEV; | ||
459 | /* | ||
460 | * OK, we know we have an OmniVision chip...but which one? | ||
461 | */ | ||
462 | ret = ov7670_read(client, REG_PID, &v); | ||
463 | if (ret < 0) | ||
464 | return ret; | ||
465 | if (v != 0x76) /* PID + VER = 0x76 / 0x73 */ | ||
466 | return -ENODEV; | ||
467 | ret = ov7670_read(client, REG_VER, &v); | ||
468 | if (ret < 0) | ||
469 | return ret; | ||
470 | if (v != 0x73) /* PID + VER = 0x76 / 0x73 */ | ||
471 | return -ENODEV; | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | |||
476 | /* | ||
477 | * Store information about the video data format. The color matrix | ||
478 | * is deeply tied into the format, so keep the relevant values here. | ||
479 | * The magic matrix nubmers come from OmniVision. | ||
480 | */ | ||
481 | static struct ov7670_format_struct { | ||
482 | __u8 *desc; | ||
483 | __u32 pixelformat; | ||
484 | struct regval_list *regs; | ||
485 | int cmatrix[CMATRIX_LEN]; | ||
486 | } ov7670_formats[] = { | ||
487 | { | ||
488 | .desc = "YUYV 4:2:2", | ||
489 | .pixelformat = V4L2_PIX_FMT_YUYV, | ||
490 | .regs = ov7670_fmt_yuv422, | ||
491 | .cmatrix = { 128, -128, 0, -34, -94, 128 }, | ||
492 | }, | ||
493 | { | ||
494 | .desc = "RGB 444", | ||
495 | .pixelformat = V4L2_PIX_FMT_RGB444, | ||
496 | .regs = ov7670_fmt_rgb444, | ||
497 | .cmatrix = { 179, -179, 0, -61, -176, 228 }, | ||
498 | }, | ||
499 | { | ||
500 | .desc = "RGB 565", | ||
501 | .pixelformat = V4L2_PIX_FMT_RGB565, | ||
502 | .regs = ov7670_fmt_rgb565, | ||
503 | .cmatrix = { 179, -179, 0, -61, -176, 228 }, | ||
504 | }, | ||
505 | }; | ||
506 | #define N_OV7670_FMTS (sizeof(ov7670_formats)/sizeof(ov7670_formats[0])) | ||
507 | |||
508 | /* | ||
509 | * All formats we support are 2 bytes/pixel. | ||
510 | */ | ||
511 | #define BYTES_PER_PIXEL 2 | ||
512 | |||
513 | /* | ||
514 | * Then there is the issue of window sizes. Try to capture the info here. | ||
515 | */ | ||
516 | |||
517 | /* | ||
518 | * QCIF mode is done (by OV) in a very strange way - it actually looks like | ||
519 | * VGA with weird scaling options - they do *not* use the canned QCIF mode | ||
520 | * which is allegedly provided by the sensor. So here's the weird register | ||
521 | * settings. | ||
522 | */ | ||
523 | static struct regval_list ov7670_qcif_regs[] = { | ||
524 | { REG_COM3, COM3_SCALEEN|COM3_DCWEN }, | ||
525 | { REG_COM3, COM3_DCWEN }, | ||
526 | { REG_COM14, COM14_DCWEN | 0x01}, | ||
527 | { 0x73, 0xf1 }, | ||
528 | { 0xa2, 0x52 }, | ||
529 | { 0x7b, 0x1c }, | ||
530 | { 0x7c, 0x28 }, | ||
531 | { 0x7d, 0x3c }, | ||
532 | { 0x7f, 0x69 }, | ||
533 | { REG_COM9, 0x38 }, | ||
534 | { 0xa1, 0x0b }, | ||
535 | { 0x74, 0x19 }, | ||
536 | { 0x9a, 0x80 }, | ||
537 | { 0x43, 0x14 }, | ||
538 | { REG_COM13, 0xc0 }, | ||
539 | { 0xff, 0xff }, | ||
540 | }; | ||
541 | |||
542 | static struct ov7670_win_size { | ||
543 | int width; | ||
544 | int height; | ||
545 | unsigned char com7_bit; | ||
546 | int hstart; /* Start/stop values for the camera. Note */ | ||
547 | int hstop; /* that they do not always make complete */ | ||
548 | int vstart; /* sense to humans, but evidently the sensor */ | ||
549 | int vstop; /* will do the right thing... */ | ||
550 | struct regval_list *regs; /* Regs to tweak */ | ||
551 | /* h/vref stuff */ | ||
552 | } ov7670_win_sizes[] = { | ||
553 | /* VGA */ | ||
554 | { | ||
555 | .width = VGA_WIDTH, | ||
556 | .height = VGA_HEIGHT, | ||
557 | .com7_bit = COM7_FMT_VGA, | ||
558 | .hstart = 158, /* These values from */ | ||
559 | .hstop = 14, /* Omnivision */ | ||
560 | .vstart = 10, | ||
561 | .vstop = 490, | ||
562 | .regs = NULL, | ||
563 | }, | ||
564 | /* CIF */ | ||
565 | { | ||
566 | .width = CIF_WIDTH, | ||
567 | .height = CIF_HEIGHT, | ||
568 | .com7_bit = COM7_FMT_CIF, | ||
569 | .hstart = 170, /* Empirically determined */ | ||
570 | .hstop = 90, | ||
571 | .vstart = 14, | ||
572 | .vstop = 494, | ||
573 | .regs = NULL, | ||
574 | }, | ||
575 | /* QVGA */ | ||
576 | { | ||
577 | .width = QVGA_WIDTH, | ||
578 | .height = QVGA_HEIGHT, | ||
579 | .com7_bit = COM7_FMT_QVGA, | ||
580 | .hstart = 164, /* Empirically determined */ | ||
581 | .hstop = 20, | ||
582 | .vstart = 14, | ||
583 | .vstop = 494, | ||
584 | .regs = NULL, | ||
585 | }, | ||
586 | /* QCIF */ | ||
587 | { | ||
588 | .width = QCIF_WIDTH, | ||
589 | .height = QCIF_HEIGHT, | ||
590 | .com7_bit = COM7_FMT_VGA, /* see comment above */ | ||
591 | .hstart = 456, /* Empirically determined */ | ||
592 | .hstop = 24, | ||
593 | .vstart = 14, | ||
594 | .vstop = 494, | ||
595 | .regs = ov7670_qcif_regs, | ||
596 | }, | ||
597 | }; | ||
598 | |||
599 | #define N_WIN_SIZES (sizeof(ov7670_win_sizes)/sizeof(ov7670_win_sizes[0])) | ||
600 | |||
601 | |||
602 | /* | ||
603 | * Store a set of start/stop values into the camera. | ||
604 | */ | ||
605 | static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop, | ||
606 | int vstart, int vstop) | ||
607 | { | ||
608 | int ret; | ||
609 | unsigned char v; | ||
610 | /* | ||
611 | * Horizontal: 11 bits, top 8 live in hstart and hstop. Bottom 3 of | ||
612 | * hstart are in href[2:0], bottom 3 of hstop in href[5:3]. There is | ||
613 | * a mystery "edge offset" value in the top two bits of href. | ||
614 | */ | ||
615 | ret = ov7670_write(client, REG_HSTART, (hstart >> 3) & 0xff); | ||
616 | ret += ov7670_write(client, REG_HSTOP, (hstop >> 3) & 0xff); | ||
617 | ret += ov7670_read(client, REG_HREF, &v); | ||
618 | v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7); | ||
619 | msleep(10); | ||
620 | ret += ov7670_write(client, REG_HREF, v); | ||
621 | /* | ||
622 | * Vertical: similar arrangement, but only 10 bits. | ||
623 | */ | ||
624 | ret += ov7670_write(client, REG_VSTART, (vstart >> 2) & 0xff); | ||
625 | ret += ov7670_write(client, REG_VSTOP, (vstop >> 2) & 0xff); | ||
626 | ret += ov7670_read(client, REG_VREF, &v); | ||
627 | v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3); | ||
628 | msleep(10); | ||
629 | ret += ov7670_write(client, REG_VREF, v); | ||
630 | return ret; | ||
631 | } | ||
632 | |||
633 | |||
634 | static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt) | ||
635 | { | ||
636 | struct ov7670_format_struct *ofmt; | ||
637 | |||
638 | if (fmt->index >= N_OV7670_FMTS) | ||
639 | return -EINVAL; | ||
640 | |||
641 | ofmt = ov7670_formats + fmt->index; | ||
642 | fmt->flags = 0; | ||
643 | strcpy(fmt->description, ofmt->desc); | ||
644 | fmt->pixelformat = ofmt->pixelformat; | ||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | |||
649 | static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt, | ||
650 | struct ov7670_format_struct **ret_fmt, | ||
651 | struct ov7670_win_size **ret_wsize) | ||
652 | { | ||
653 | int index; | ||
654 | struct ov7670_win_size *wsize; | ||
655 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
656 | |||
657 | for (index = 0; index < N_OV7670_FMTS; index++) | ||
658 | if (ov7670_formats[index].pixelformat == pix->pixelformat) | ||
659 | break; | ||
660 | if (index >= N_OV7670_FMTS) | ||
661 | return -EINVAL; | ||
662 | if (ret_fmt != NULL) | ||
663 | *ret_fmt = ov7670_formats + index; | ||
664 | /* | ||
665 | * Fields: the OV devices claim to be progressive. | ||
666 | */ | ||
667 | if (pix->field == V4L2_FIELD_ANY) | ||
668 | pix->field = V4L2_FIELD_NONE; | ||
669 | else if (pix->field != V4L2_FIELD_NONE) | ||
670 | return -EINVAL; | ||
671 | /* | ||
672 | * Round requested image size down to the nearest | ||
673 | * we support, but not below the smallest. | ||
674 | */ | ||
675 | for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES; | ||
676 | wsize++) | ||
677 | if (pix->width >= wsize->width && pix->height >= wsize->height) | ||
678 | break; | ||
679 | if (wsize >= ov7670_win_sizes + N_WIN_SIZES) | ||
680 | wsize--; /* Take the smallest one */ | ||
681 | if (ret_wsize != NULL) | ||
682 | *ret_wsize = wsize; | ||
683 | /* | ||
684 | * Note the size we'll actually handle. | ||
685 | */ | ||
686 | pix->width = wsize->width; | ||
687 | pix->height = wsize->height; | ||
688 | pix->bytesperline = pix->width*BYTES_PER_PIXEL; | ||
689 | pix->sizeimage = pix->height*pix->bytesperline; | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | /* | ||
694 | * Set a format. | ||
695 | */ | ||
696 | static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) | ||
697 | { | ||
698 | int ret; | ||
699 | struct ov7670_format_struct *ovfmt; | ||
700 | struct ov7670_win_size *wsize; | ||
701 | struct ov7670_info *info = i2c_get_clientdata(c); | ||
702 | unsigned char com7; | ||
703 | |||
704 | ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize); | ||
705 | if (ret) | ||
706 | return ret; | ||
707 | /* | ||
708 | * COM7 is a pain in the ass, it doesn't like to be read then | ||
709 | * quickly written afterward. But we have everything we need | ||
710 | * to set it absolutely here, as long as the format-specific | ||
711 | * register sets list it first. | ||
712 | */ | ||
713 | com7 = ovfmt->regs[0].value; | ||
714 | com7 |= wsize->com7_bit; | ||
715 | ov7670_write(c, REG_COM7, com7); | ||
716 | /* | ||
717 | * Now write the rest of the array. Also store start/stops | ||
718 | */ | ||
719 | ov7670_write_array(c, ovfmt->regs + 1); | ||
720 | ov7670_set_hw(c, wsize->hstart, wsize->hstop, wsize->vstart, | ||
721 | wsize->vstop); | ||
722 | ret = 0; | ||
723 | if (wsize->regs) | ||
724 | ret = ov7670_write_array(c, wsize->regs); | ||
725 | info->fmt = ovfmt; | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | /* | ||
730 | * Implement G/S_PARM. There is a "high quality" mode we could try | ||
731 | * to do someday; for now, we just do the frame rate tweak. | ||
732 | */ | ||
733 | static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms) | ||
734 | { | ||
735 | struct v4l2_captureparm *cp = &parms->parm.capture; | ||
736 | unsigned char clkrc; | ||
737 | int ret; | ||
738 | |||
739 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
740 | return -EINVAL; | ||
741 | ret = ov7670_read(c, REG_CLKRC, &clkrc); | ||
742 | if (ret < 0) | ||
743 | return ret; | ||
744 | memset(cp, 0, sizeof(struct v4l2_captureparm)); | ||
745 | cp->capability = V4L2_CAP_TIMEPERFRAME; | ||
746 | cp->timeperframe.numerator = 1; | ||
747 | cp->timeperframe.denominator = OV7670_FRAME_RATE; | ||
748 | if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1) | ||
749 | cp->timeperframe.denominator /= (clkrc & CLK_SCALE); | ||
750 | return 0; | ||
751 | } | ||
752 | |||
753 | static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) | ||
754 | { | ||
755 | struct v4l2_captureparm *cp = &parms->parm.capture; | ||
756 | struct v4l2_fract *tpf = &cp->timeperframe; | ||
757 | unsigned char clkrc; | ||
758 | int ret, div; | ||
759 | |||
760 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
761 | return -EINVAL; | ||
762 | if (cp->extendedmode != 0) | ||
763 | return -EINVAL; | ||
764 | /* | ||
765 | * CLKRC has a reserved bit, so let's preserve it. | ||
766 | */ | ||
767 | ret = ov7670_read(c, REG_CLKRC, &clkrc); | ||
768 | if (ret < 0) | ||
769 | return ret; | ||
770 | if (tpf->numerator == 0 || tpf->denominator == 0) | ||
771 | div = 1; /* Reset to full rate */ | ||
772 | else | ||
773 | div = (tpf->numerator*OV7670_FRAME_RATE)/tpf->denominator; | ||
774 | if (div == 0) | ||
775 | div = 1; | ||
776 | else if (div > CLK_SCALE) | ||
777 | div = CLK_SCALE; | ||
778 | clkrc = (clkrc & 0x80) | div; | ||
779 | tpf->numerator = 1; | ||
780 | tpf->denominator = OV7670_FRAME_RATE/div; | ||
781 | return ov7670_write(c, REG_CLKRC, clkrc); | ||
782 | } | ||
783 | |||
784 | |||
785 | |||
786 | /* | ||
787 | * Code for dealing with controls. | ||
788 | */ | ||
789 | |||
790 | |||
791 | |||
792 | |||
793 | |||
794 | static int ov7670_store_cmatrix(struct i2c_client *client, | ||
795 | int matrix[CMATRIX_LEN]) | ||
796 | { | ||
797 | int i, ret; | ||
798 | unsigned char signbits; | ||
799 | |||
800 | /* | ||
801 | * Weird crap seems to exist in the upper part of | ||
802 | * the sign bits register, so let's preserve it. | ||
803 | */ | ||
804 | ret = ov7670_read(client, REG_CMATRIX_SIGN, &signbits); | ||
805 | signbits &= 0xc0; | ||
806 | |||
807 | for (i = 0; i < CMATRIX_LEN; i++) { | ||
808 | unsigned char raw; | ||
809 | |||
810 | if (matrix[i] < 0) { | ||
811 | signbits |= (1 << i); | ||
812 | if (matrix[i] < -255) | ||
813 | raw = 0xff; | ||
814 | else | ||
815 | raw = (-1 * matrix[i]) & 0xff; | ||
816 | } | ||
817 | else { | ||
818 | if (matrix[i] > 255) | ||
819 | raw = 0xff; | ||
820 | else | ||
821 | raw = matrix[i] & 0xff; | ||
822 | } | ||
823 | ret += ov7670_write(client, REG_CMATRIX_BASE + i, raw); | ||
824 | } | ||
825 | ret += ov7670_write(client, REG_CMATRIX_SIGN, signbits); | ||
826 | return ret; | ||
827 | } | ||
828 | |||
829 | |||
830 | /* | ||
831 | * Hue also requires messing with the color matrix. It also requires | ||
832 | * trig functions, which tend not to be well supported in the kernel. | ||
833 | * So here is a simple table of sine values, 0-90 degrees, in steps | ||
834 | * of five degrees. Values are multiplied by 1000. | ||
835 | * | ||
836 | * The following naive approximate trig functions require an argument | ||
837 | * carefully limited to -180 <= theta <= 180. | ||
838 | */ | ||
839 | #define SIN_STEP 5 | ||
840 | static const int ov7670_sin_table[] = { | ||
841 | 0, 87, 173, 258, 342, 422, | ||
842 | 499, 573, 642, 707, 766, 819, | ||
843 | 866, 906, 939, 965, 984, 996, | ||
844 | 1000 | ||
845 | }; | ||
846 | |||
847 | static int ov7670_sine(int theta) | ||
848 | { | ||
849 | int chs = 1; | ||
850 | int sine; | ||
851 | |||
852 | if (theta < 0) { | ||
853 | theta = -theta; | ||
854 | chs = -1; | ||
855 | } | ||
856 | if (theta <= 90) | ||
857 | sine = ov7670_sin_table[theta/SIN_STEP]; | ||
858 | else { | ||
859 | theta -= 90; | ||
860 | sine = 1000 - ov7670_sin_table[theta/SIN_STEP]; | ||
861 | } | ||
862 | return sine*chs; | ||
863 | } | ||
864 | |||
865 | static int ov7670_cosine(int theta) | ||
866 | { | ||
867 | theta = 90 - theta; | ||
868 | if (theta > 180) | ||
869 | theta -= 360; | ||
870 | else if (theta < -180) | ||
871 | theta += 360; | ||
872 | return ov7670_sine(theta); | ||
873 | } | ||
874 | |||
875 | |||
876 | |||
877 | |||
878 | static void ov7670_calc_cmatrix(struct ov7670_info *info, | ||
879 | int matrix[CMATRIX_LEN]) | ||
880 | { | ||
881 | int i; | ||
882 | /* | ||
883 | * Apply the current saturation setting first. | ||
884 | */ | ||
885 | for (i = 0; i < CMATRIX_LEN; i++) | ||
886 | matrix[i] = (info->fmt->cmatrix[i]*info->sat) >> 7; | ||
887 | /* | ||
888 | * Then, if need be, rotate the hue value. | ||
889 | */ | ||
890 | if (info->hue != 0) { | ||
891 | int sinth, costh, tmpmatrix[CMATRIX_LEN]; | ||
892 | |||
893 | memcpy(tmpmatrix, matrix, CMATRIX_LEN*sizeof(int)); | ||
894 | sinth = ov7670_sine(info->hue); | ||
895 | costh = ov7670_cosine(info->hue); | ||
896 | |||
897 | matrix[0] = (matrix[3]*sinth + matrix[0]*costh)/1000; | ||
898 | matrix[1] = (matrix[4]*sinth + matrix[1]*costh)/1000; | ||
899 | matrix[2] = (matrix[5]*sinth + matrix[2]*costh)/1000; | ||
900 | matrix[3] = (matrix[3]*costh - matrix[0]*sinth)/1000; | ||
901 | matrix[4] = (matrix[4]*costh - matrix[1]*sinth)/1000; | ||
902 | matrix[5] = (matrix[5]*costh - matrix[2]*sinth)/1000; | ||
903 | } | ||
904 | } | ||
905 | |||
906 | |||
907 | |||
908 | static int ov7670_t_sat(struct i2c_client *client, int value) | ||
909 | { | ||
910 | struct ov7670_info *info = i2c_get_clientdata(client); | ||
911 | int matrix[CMATRIX_LEN]; | ||
912 | int ret; | ||
913 | |||
914 | info->sat = value; | ||
915 | ov7670_calc_cmatrix(info, matrix); | ||
916 | ret = ov7670_store_cmatrix(client, matrix); | ||
917 | return ret; | ||
918 | } | ||
919 | |||
920 | static int ov7670_q_sat(struct i2c_client *client, __s32 *value) | ||
921 | { | ||
922 | struct ov7670_info *info = i2c_get_clientdata(client); | ||
923 | |||
924 | *value = info->sat; | ||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | static int ov7670_t_hue(struct i2c_client *client, int value) | ||
929 | { | ||
930 | struct ov7670_info *info = i2c_get_clientdata(client); | ||
931 | int matrix[CMATRIX_LEN]; | ||
932 | int ret; | ||
933 | |||
934 | if (value < -180 || value > 180) | ||
935 | return -EINVAL; | ||
936 | info->hue = value; | ||
937 | ov7670_calc_cmatrix(info, matrix); | ||
938 | ret = ov7670_store_cmatrix(client, matrix); | ||
939 | return ret; | ||
940 | } | ||
941 | |||
942 | |||
943 | static int ov7670_q_hue(struct i2c_client *client, __s32 *value) | ||
944 | { | ||
945 | struct ov7670_info *info = i2c_get_clientdata(client); | ||
946 | |||
947 | *value = info->hue; | ||
948 | return 0; | ||
949 | } | ||
950 | |||
951 | |||
952 | /* | ||
953 | * Some weird registers seem to store values in a sign/magnitude format! | ||
954 | */ | ||
955 | static unsigned char ov7670_sm_to_abs(unsigned char v) | ||
956 | { | ||
957 | if ((v & 0x80) == 0) | ||
958 | return v + 128; | ||
959 | else | ||
960 | return 128 - (v & 0x7f); | ||
961 | } | ||
962 | |||
963 | |||
964 | static unsigned char ov7670_abs_to_sm(unsigned char v) | ||
965 | { | ||
966 | if (v > 127) | ||
967 | return v & 0x7f; | ||
968 | else | ||
969 | return (128 - v) | 0x80; | ||
970 | } | ||
971 | |||
972 | static int ov7670_t_brightness(struct i2c_client *client, int value) | ||
973 | { | ||
974 | unsigned char com8, v; | ||
975 | int ret; | ||
976 | |||
977 | ov7670_read(client, REG_COM8, &com8); | ||
978 | com8 &= ~COM8_AEC; | ||
979 | ov7670_write(client, REG_COM8, com8); | ||
980 | v = ov7670_abs_to_sm(value); | ||
981 | ret = ov7670_write(client, REG_BRIGHT, v); | ||
982 | return ret; | ||
983 | } | ||
984 | |||
985 | static int ov7670_q_brightness(struct i2c_client *client, __s32 *value) | ||
986 | { | ||
987 | unsigned char v; | ||
988 | int ret = ov7670_read(client, REG_BRIGHT, &v); | ||
989 | |||
990 | *value = ov7670_sm_to_abs(v); | ||
991 | return ret; | ||
992 | } | ||
993 | |||
994 | static int ov7670_t_contrast(struct i2c_client *client, int value) | ||
995 | { | ||
996 | return ov7670_write(client, REG_CONTRAS, (unsigned char) value); | ||
997 | } | ||
998 | |||
999 | static int ov7670_q_contrast(struct i2c_client *client, __s32 *value) | ||
1000 | { | ||
1001 | unsigned char v; | ||
1002 | int ret = ov7670_read(client, REG_CONTRAS, &v); | ||
1003 | |||
1004 | *value = v; | ||
1005 | return ret; | ||
1006 | } | ||
1007 | |||
1008 | static int ov7670_q_hflip(struct i2c_client *client, __s32 *value) | ||
1009 | { | ||
1010 | int ret; | ||
1011 | unsigned char v; | ||
1012 | |||
1013 | ret = ov7670_read(client, REG_MVFP, &v); | ||
1014 | *value = (v & MVFP_MIRROR) == MVFP_MIRROR; | ||
1015 | return ret; | ||
1016 | } | ||
1017 | |||
1018 | |||
1019 | static int ov7670_t_hflip(struct i2c_client *client, int value) | ||
1020 | { | ||
1021 | unsigned char v; | ||
1022 | int ret; | ||
1023 | |||
1024 | ret = ov7670_read(client, REG_MVFP, &v); | ||
1025 | if (value) | ||
1026 | v |= MVFP_MIRROR; | ||
1027 | else | ||
1028 | v &= ~MVFP_MIRROR; | ||
1029 | msleep(10); /* FIXME */ | ||
1030 | ret += ov7670_write(client, REG_MVFP, v); | ||
1031 | return ret; | ||
1032 | } | ||
1033 | |||
1034 | |||
1035 | |||
1036 | static int ov7670_q_vflip(struct i2c_client *client, __s32 *value) | ||
1037 | { | ||
1038 | int ret; | ||
1039 | unsigned char v; | ||
1040 | |||
1041 | ret = ov7670_read(client, REG_MVFP, &v); | ||
1042 | *value = (v & MVFP_FLIP) == MVFP_FLIP; | ||
1043 | return ret; | ||
1044 | } | ||
1045 | |||
1046 | |||
1047 | static int ov7670_t_vflip(struct i2c_client *client, int value) | ||
1048 | { | ||
1049 | unsigned char v; | ||
1050 | int ret; | ||
1051 | |||
1052 | ret = ov7670_read(client, REG_MVFP, &v); | ||
1053 | if (value) | ||
1054 | v |= MVFP_FLIP; | ||
1055 | else | ||
1056 | v &= ~MVFP_FLIP; | ||
1057 | msleep(10); /* FIXME */ | ||
1058 | ret += ov7670_write(client, REG_MVFP, v); | ||
1059 | return ret; | ||
1060 | } | ||
1061 | |||
1062 | |||
1063 | static struct ov7670_control { | ||
1064 | struct v4l2_queryctrl qc; | ||
1065 | int (*query)(struct i2c_client *c, __s32 *value); | ||
1066 | int (*tweak)(struct i2c_client *c, int value); | ||
1067 | } ov7670_controls[] = | ||
1068 | { | ||
1069 | { | ||
1070 | .qc = { | ||
1071 | .id = V4L2_CID_BRIGHTNESS, | ||
1072 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1073 | .name = "Brightness", | ||
1074 | .minimum = 0, | ||
1075 | .maximum = 255, | ||
1076 | .step = 1, | ||
1077 | .default_value = 0x80, | ||
1078 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
1079 | }, | ||
1080 | .tweak = ov7670_t_brightness, | ||
1081 | .query = ov7670_q_brightness, | ||
1082 | }, | ||
1083 | { | ||
1084 | .qc = { | ||
1085 | .id = V4L2_CID_CONTRAST, | ||
1086 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1087 | .name = "Contrast", | ||
1088 | .minimum = 0, | ||
1089 | .maximum = 127, | ||
1090 | .step = 1, | ||
1091 | .default_value = 0x40, /* XXX ov7670 spec */ | ||
1092 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
1093 | }, | ||
1094 | .tweak = ov7670_t_contrast, | ||
1095 | .query = ov7670_q_contrast, | ||
1096 | }, | ||
1097 | { | ||
1098 | .qc = { | ||
1099 | .id = V4L2_CID_SATURATION, | ||
1100 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1101 | .name = "Saturation", | ||
1102 | .minimum = 0, | ||
1103 | .maximum = 256, | ||
1104 | .step = 1, | ||
1105 | .default_value = 0x80, | ||
1106 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
1107 | }, | ||
1108 | .tweak = ov7670_t_sat, | ||
1109 | .query = ov7670_q_sat, | ||
1110 | }, | ||
1111 | { | ||
1112 | .qc = { | ||
1113 | .id = V4L2_CID_HUE, | ||
1114 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1115 | .name = "HUE", | ||
1116 | .minimum = -180, | ||
1117 | .maximum = 180, | ||
1118 | .step = 5, | ||
1119 | .default_value = 0, | ||
1120 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
1121 | }, | ||
1122 | .tweak = ov7670_t_hue, | ||
1123 | .query = ov7670_q_hue, | ||
1124 | }, | ||
1125 | { | ||
1126 | .qc = { | ||
1127 | .id = V4L2_CID_VFLIP, | ||
1128 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
1129 | .name = "Vertical flip", | ||
1130 | .minimum = 0, | ||
1131 | .maximum = 1, | ||
1132 | .step = 1, | ||
1133 | .default_value = 0, | ||
1134 | }, | ||
1135 | .tweak = ov7670_t_vflip, | ||
1136 | .query = ov7670_q_vflip, | ||
1137 | }, | ||
1138 | { | ||
1139 | .qc = { | ||
1140 | .id = V4L2_CID_HFLIP, | ||
1141 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
1142 | .name = "Horizontal mirror", | ||
1143 | .minimum = 0, | ||
1144 | .maximum = 1, | ||
1145 | .step = 1, | ||
1146 | .default_value = 0, | ||
1147 | }, | ||
1148 | .tweak = ov7670_t_hflip, | ||
1149 | .query = ov7670_q_hflip, | ||
1150 | }, | ||
1151 | }; | ||
1152 | #define N_CONTROLS (sizeof(ov7670_controls)/sizeof(ov7670_controls[0])) | ||
1153 | |||
1154 | static struct ov7670_control *ov7670_find_control(__u32 id) | ||
1155 | { | ||
1156 | int i; | ||
1157 | |||
1158 | for (i = 0; i < N_CONTROLS; i++) | ||
1159 | if (ov7670_controls[i].qc.id == id) | ||
1160 | return ov7670_controls + i; | ||
1161 | return NULL; | ||
1162 | } | ||
1163 | |||
1164 | |||
1165 | static int ov7670_queryctrl(struct i2c_client *client, | ||
1166 | struct v4l2_queryctrl *qc) | ||
1167 | { | ||
1168 | struct ov7670_control *ctrl = ov7670_find_control(qc->id); | ||
1169 | |||
1170 | if (ctrl == NULL) | ||
1171 | return -EINVAL; | ||
1172 | *qc = ctrl->qc; | ||
1173 | return 0; | ||
1174 | } | ||
1175 | |||
1176 | static int ov7670_g_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
1177 | { | ||
1178 | struct ov7670_control *octrl = ov7670_find_control(ctrl->id); | ||
1179 | int ret; | ||
1180 | |||
1181 | if (octrl == NULL) | ||
1182 | return -EINVAL; | ||
1183 | ret = octrl->query(client, &ctrl->value); | ||
1184 | if (ret >= 0) | ||
1185 | return 0; | ||
1186 | return ret; | ||
1187 | } | ||
1188 | |||
1189 | static int ov7670_s_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
1190 | { | ||
1191 | struct ov7670_control *octrl = ov7670_find_control(ctrl->id); | ||
1192 | int ret; | ||
1193 | |||
1194 | if (octrl == NULL) | ||
1195 | return -EINVAL; | ||
1196 | ret = octrl->tweak(client, ctrl->value); | ||
1197 | if (ret >= 0) | ||
1198 | return 0; | ||
1199 | return ret; | ||
1200 | } | ||
1201 | |||
1202 | |||
1203 | |||
1204 | |||
1205 | |||
1206 | |||
1207 | /* | ||
1208 | * Basic i2c stuff. | ||
1209 | */ | ||
1210 | static struct i2c_driver ov7670_driver; | ||
1211 | |||
1212 | static int ov7670_attach(struct i2c_adapter *adapter) | ||
1213 | { | ||
1214 | int ret; | ||
1215 | struct i2c_client *client; | ||
1216 | struct ov7670_info *info; | ||
1217 | |||
1218 | /* | ||
1219 | * For now: only deal with adapters we recognize. | ||
1220 | */ | ||
1221 | if (adapter->id != I2C_HW_SMBUS_CAFE) | ||
1222 | return -ENODEV; | ||
1223 | |||
1224 | client = kzalloc(sizeof (struct i2c_client), GFP_KERNEL); | ||
1225 | if (! client) | ||
1226 | return -ENOMEM; | ||
1227 | client->adapter = adapter; | ||
1228 | client->addr = OV7670_I2C_ADDR; | ||
1229 | client->driver = &ov7670_driver, | ||
1230 | strcpy(client->name, "OV7670"); | ||
1231 | /* | ||
1232 | * Set up our info structure. | ||
1233 | */ | ||
1234 | info = kzalloc(sizeof (struct ov7670_info), GFP_KERNEL); | ||
1235 | if (! info) { | ||
1236 | ret = -ENOMEM; | ||
1237 | goto out_free; | ||
1238 | } | ||
1239 | info->fmt = &ov7670_formats[0]; | ||
1240 | info->sat = 128; /* Review this */ | ||
1241 | i2c_set_clientdata(client, info); | ||
1242 | |||
1243 | /* | ||
1244 | * Make sure it's an ov7670 | ||
1245 | */ | ||
1246 | ret = ov7670_detect(client); | ||
1247 | if (ret) | ||
1248 | goto out_free_info; | ||
1249 | i2c_attach_client(client); | ||
1250 | return 0; | ||
1251 | |||
1252 | out_free_info: | ||
1253 | kfree(info); | ||
1254 | out_free: | ||
1255 | kfree(client); | ||
1256 | return ret; | ||
1257 | } | ||
1258 | |||
1259 | |||
1260 | static int ov7670_detach(struct i2c_client *client) | ||
1261 | { | ||
1262 | i2c_detach_client(client); | ||
1263 | kfree(i2c_get_clientdata(client)); | ||
1264 | kfree(client); | ||
1265 | return 0; | ||
1266 | } | ||
1267 | |||
1268 | |||
1269 | static int ov7670_command(struct i2c_client *client, unsigned int cmd, | ||
1270 | void *arg) | ||
1271 | { | ||
1272 | switch (cmd) { | ||
1273 | case VIDIOC_INT_G_CHIP_IDENT: | ||
1274 | * (enum v4l2_chip_ident *) arg = V4L2_IDENT_OV7670; | ||
1275 | return 0; | ||
1276 | |||
1277 | case VIDIOC_INT_RESET: | ||
1278 | ov7670_reset(client); | ||
1279 | return 0; | ||
1280 | |||
1281 | case VIDIOC_INT_INIT: | ||
1282 | return ov7670_init(client); | ||
1283 | |||
1284 | case VIDIOC_ENUM_FMT: | ||
1285 | return ov7670_enum_fmt(client, (struct v4l2_fmtdesc *) arg); | ||
1286 | case VIDIOC_TRY_FMT: | ||
1287 | return ov7670_try_fmt(client, (struct v4l2_format *) arg, NULL, NULL); | ||
1288 | case VIDIOC_S_FMT: | ||
1289 | return ov7670_s_fmt(client, (struct v4l2_format *) arg); | ||
1290 | case VIDIOC_QUERYCTRL: | ||
1291 | return ov7670_queryctrl(client, (struct v4l2_queryctrl *) arg); | ||
1292 | case VIDIOC_S_CTRL: | ||
1293 | return ov7670_s_ctrl(client, (struct v4l2_control *) arg); | ||
1294 | case VIDIOC_G_CTRL: | ||
1295 | return ov7670_g_ctrl(client, (struct v4l2_control *) arg); | ||
1296 | case VIDIOC_S_PARM: | ||
1297 | return ov7670_s_parm(client, (struct v4l2_streamparm *) arg); | ||
1298 | case VIDIOC_G_PARM: | ||
1299 | return ov7670_g_parm(client, (struct v4l2_streamparm *) arg); | ||
1300 | } | ||
1301 | return -EINVAL; | ||
1302 | } | ||
1303 | |||
1304 | |||
1305 | |||
1306 | static struct i2c_driver ov7670_driver = { | ||
1307 | .driver = { | ||
1308 | .name = "ov7670", | ||
1309 | }, | ||
1310 | .id = I2C_DRIVERID_OV7670, | ||
1311 | .class = I2C_CLASS_CAM_DIGITAL, | ||
1312 | .attach_adapter = ov7670_attach, | ||
1313 | .detach_client = ov7670_detach, | ||
1314 | .command = ov7670_command, | ||
1315 | }; | ||
1316 | |||
1317 | |||
1318 | /* | ||
1319 | * Module initialization | ||
1320 | */ | ||
1321 | static int __init ov7670_mod_init(void) | ||
1322 | { | ||
1323 | printk(KERN_NOTICE "OmniVision ov7670 sensor driver, at your service\n"); | ||
1324 | return i2c_add_driver(&ov7670_driver); | ||
1325 | } | ||
1326 | |||
1327 | static void __exit ov7670_mod_exit(void) | ||
1328 | { | ||
1329 | i2c_del_driver(&ov7670_driver); | ||
1330 | } | ||
1331 | |||
1332 | module_init(ov7670_mod_init); | ||
1333 | module_exit(ov7670_mod_exit); | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index c80c26be6e4d..848fb233d808 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | |||
@@ -260,6 +260,22 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, | |||
260 | sizeof(decoder_ops[0]))) - 1; | 260 | sizeof(decoder_ops[0]))) - 1; |
261 | hdw->decoder_ctrl = &ctxt->ctrl; | 261 | hdw->decoder_ctrl = &ctxt->ctrl; |
262 | cp->handler = &ctxt->handler; | 262 | cp->handler = &ctxt->handler; |
263 | { | ||
264 | /* | ||
265 | Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit | ||
266 | of nuttiness for cx25840 causes that module to | ||
267 | correctly set up its video scaling. This is really | ||
268 | a problem in the cx25840 module itself, but we work | ||
269 | around it here. The problem has not been seen in | ||
270 | ivtv because there VBI is supported and set up. We | ||
271 | don't do VBI here (at least not yet) and thus we | ||
272 | never attempted to even set it up. | ||
273 | */ | ||
274 | struct v4l2_format fmt; | ||
275 | memset(&fmt,0,sizeof(fmt)); | ||
276 | fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | ||
277 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt); | ||
278 | } | ||
263 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up", | 279 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up", |
264 | cp->client->addr); | 280 | cp->client->addr); |
265 | return !0; | 281 | return !0; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1f787333d18c..d2004965187b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -356,28 +356,6 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) | |||
356 | return 0; | 356 | return 0; |
357 | } | 357 | } |
358 | 358 | ||
359 | static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp) | ||
360 | { | ||
361 | /* If we're dealing with a 24xxx device, force the horizontal | ||
362 | maximum to be 720 no matter what, since we can't get the device | ||
363 | to work properly with any other value. Otherwise just return | ||
364 | the normal value. */ | ||
365 | *vp = cptr->info->def.type_int.max_value; | ||
366 | if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720; | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp) | ||
371 | { | ||
372 | /* If we're dealing with a 24xxx device, force the horizontal | ||
373 | minimum to be 720 no matter what, since we can't get the device | ||
374 | to work properly with any other value. Otherwise just return | ||
375 | the normal value. */ | ||
376 | *vp = cptr->info->def.type_int.min_value; | ||
377 | if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720; | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) | 359 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) |
382 | { | 360 | { |
383 | /* Actual maximum depends on the video standard in effect. */ | 361 | /* Actual maximum depends on the video standard in effect. */ |
@@ -758,10 +736,6 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
758 | .default_value = 720, | 736 | .default_value = 720, |
759 | DEFREF(res_hor), | 737 | DEFREF(res_hor), |
760 | DEFINT(19,720), | 738 | DEFINT(19,720), |
761 | /* Hook in check for clamp on horizontal resolution in | ||
762 | order to avoid unsolved problem involving cx25840. */ | ||
763 | .get_max_value = ctrl_hres_max_get, | ||
764 | .get_min_value = ctrl_hres_min_get, | ||
765 | },{ | 739 | },{ |
766 | .desc = "Vertical capture resolution", | 740 | .desc = "Vertical capture resolution", |
767 | .name = "resolution_ver", | 741 | .name = "resolution_ver", |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 3b9012f8e380..f9bb41d8f4f3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
@@ -185,6 +185,79 @@ static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw, | |||
185 | } | 185 | } |
186 | } | 186 | } |
187 | 187 | ||
188 | |||
189 | /* This is a special entry point for cases of I2C transaction attempts to | ||
190 | the IR receiver. The implementation here simulates the IR receiver by | ||
191 | issuing a command to the FX2 firmware and using that response to return | ||
192 | what the real I2C receiver would have returned. We use this for 24xxx | ||
193 | devices, where the IR receiver chip has been removed and replaced with | ||
194 | FX2 related logic. */ | ||
195 | static int i2c_24xxx_ir(struct pvr2_hdw *hdw, | ||
196 | u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) | ||
197 | { | ||
198 | u8 dat[4]; | ||
199 | unsigned int stat; | ||
200 | |||
201 | if (!(rlen || wlen)) { | ||
202 | /* This is a probe attempt. Just let it succeed. */ | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /* We don't understand this kind of transaction */ | ||
207 | if ((wlen != 0) || (rlen == 0)) return -EIO; | ||
208 | |||
209 | if (rlen < 3) { | ||
210 | /* Mike Isely <isely@pobox.com> Appears to be a probe | ||
211 | attempt from lirc. Just fill in zeroes and return. If | ||
212 | we try instead to do the full transaction here, then bad | ||
213 | things seem to happen within the lirc driver module | ||
214 | (version 0.8.0-7 sources from Debian, when run under | ||
215 | vanilla 2.6.17.6 kernel) - and I don't have the patience | ||
216 | to chase it down. */ | ||
217 | if (rlen > 0) rdata[0] = 0; | ||
218 | if (rlen > 1) rdata[1] = 0; | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | /* Issue a command to the FX2 to read the IR receiver. */ | ||
223 | LOCK_TAKE(hdw->ctl_lock); do { | ||
224 | hdw->cmd_buffer[0] = 0xec; | ||
225 | stat = pvr2_send_request(hdw, | ||
226 | hdw->cmd_buffer,1, | ||
227 | hdw->cmd_buffer,4); | ||
228 | dat[0] = hdw->cmd_buffer[0]; | ||
229 | dat[1] = hdw->cmd_buffer[1]; | ||
230 | dat[2] = hdw->cmd_buffer[2]; | ||
231 | dat[3] = hdw->cmd_buffer[3]; | ||
232 | } while (0); LOCK_GIVE(hdw->ctl_lock); | ||
233 | |||
234 | /* Give up if that operation failed. */ | ||
235 | if (stat != 0) return stat; | ||
236 | |||
237 | /* Mangle the results into something that looks like the real IR | ||
238 | receiver. */ | ||
239 | rdata[2] = 0xc1; | ||
240 | if (dat[0] != 1) { | ||
241 | /* No code received. */ | ||
242 | rdata[0] = 0; | ||
243 | rdata[1] = 0; | ||
244 | } else { | ||
245 | u16 val; | ||
246 | /* Mash the FX2 firmware-provided IR code into something | ||
247 | that the normal i2c chip-level driver expects. */ | ||
248 | val = dat[1]; | ||
249 | val <<= 8; | ||
250 | val |= dat[2]; | ||
251 | val >>= 1; | ||
252 | val &= ~0x0003; | ||
253 | val |= 0x8000; | ||
254 | rdata[0] = (val >> 8) & 0xffu; | ||
255 | rdata[1] = val & 0xffu; | ||
256 | } | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
188 | /* This is a special entry point that is entered if an I2C operation is | 261 | /* This is a special entry point that is entered if an I2C operation is |
189 | attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this | 262 | attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this |
190 | part doesn't work, but we know it is really there. So let's look for | 263 | part doesn't work, but we know it is really there. So let's look for |
@@ -887,17 +960,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) | |||
887 | { | 960 | { |
888 | unsigned int idx; | 961 | unsigned int idx; |
889 | 962 | ||
890 | // The default action for all possible I2C addresses is just to do | 963 | /* The default action for all possible I2C addresses is just to do |
891 | // the transfer normally. | 964 | the transfer normally. */ |
892 | for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) { | 965 | for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) { |
893 | hdw->i2c_func[idx] = pvr2_i2c_basic_op; | 966 | hdw->i2c_func[idx] = pvr2_i2c_basic_op; |
894 | } | 967 | } |
895 | 968 | ||
896 | // If however we're dealing with new hardware, insert some hacks in | 969 | /* However, deal with various special cases for 24xxx hardware. */ |
897 | // the I2C transfer stack to let things work better. | ||
898 | if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { | 970 | if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { |
899 | hdw->i2c_func[0x1b] = i2c_hack_wm8775; | 971 | hdw->i2c_func[0x1b] = i2c_hack_wm8775; |
900 | hdw->i2c_func[0x44] = i2c_hack_cx25840; | 972 | hdw->i2c_func[0x44] = i2c_hack_cx25840; |
973 | hdw->i2c_func[0x18] = i2c_24xxx_ir; | ||
901 | } | 974 | } |
902 | 975 | ||
903 | // Configure the adapter and set up everything else related to it. | 976 | // Configure the adapter and set up everything else related to it. |
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index f28398dd9d93..c2374ed7ba9f 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -851,7 +851,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) | |||
851 | 851 | ||
852 | /* On 60Hz, it is using a higher Vertical Output Size */ | 852 | /* On 60Hz, it is using a higher Vertical Output Size */ |
853 | if (!is_50hz) | 853 | if (!is_50hz) |
854 | res+=(VRES_60HZ-480)>>1; | 854 | res += (VRES_60HZ - 480) >> 1; |
855 | 855 | ||
856 | /* height */ | 856 | /* height */ |
857 | saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, | 857 | saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, |
@@ -907,7 +907,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) | |||
907 | 907 | ||
908 | /* Activates task "B" */ | 908 | /* Activates task "B" */ |
909 | saa711x_write(client, R_80_GLOBAL_CNTL_1, | 909 | saa711x_write(client, R_80_GLOBAL_CNTL_1, |
910 | saa711x_read(client,R_80_GLOBAL_CNTL_1)|0x20); | 910 | saa711x_read(client,R_80_GLOBAL_CNTL_1) | 0x20); |
911 | 911 | ||
912 | return 0; | 912 | return 0; |
913 | } | 913 | } |
@@ -932,11 +932,11 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) | |||
932 | if (std & V4L2_STD_525_60) { | 932 | if (std & V4L2_STD_525_60) { |
933 | v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n"); | 933 | v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n"); |
934 | saa711x_writeregs(client, saa7115_cfg_60hz_video); | 934 | saa711x_writeregs(client, saa7115_cfg_60hz_video); |
935 | saa711x_set_size(client,720,480); | 935 | saa711x_set_size(client, 720, 480); |
936 | } else { | 936 | } else { |
937 | v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n"); | 937 | v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n"); |
938 | saa711x_writeregs(client, saa7115_cfg_50hz_video); | 938 | saa711x_writeregs(client, saa7115_cfg_50hz_video); |
939 | saa711x_set_size(client,720,576); | 939 | saa711x_set_size(client, 720, 576); |
940 | } | 940 | } |
941 | 941 | ||
942 | /* Register 0E - Bits D6-D4 on NO-AUTO mode | 942 | /* Register 0E - Bits D6-D4 on NO-AUTO mode |
@@ -1464,13 +1464,13 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1464 | client->driver = &i2c_driver_saa711x; | 1464 | client->driver = &i2c_driver_saa711x; |
1465 | snprintf(client->name, sizeof(client->name) - 1, "saa7115"); | 1465 | snprintf(client->name, sizeof(client->name) - 1, "saa7115"); |
1466 | 1466 | ||
1467 | for (i=0;i<0x0f;i++) { | 1467 | for (i = 0; i < 0x0f; i++) { |
1468 | saa711x_write(client, 0, i); | 1468 | saa711x_write(client, 0, i); |
1469 | name[i] = (saa711x_read(client, 0) &0x0f) +'0'; | 1469 | name[i] = (saa711x_read(client, 0) & 0x0f) + '0'; |
1470 | if (name[i]>'9') | 1470 | if (name[i] > '9') |
1471 | name[i]+='a'-'9'-1; | 1471 | name[i] += 'a' - '9' - 1; |
1472 | } | 1472 | } |
1473 | name[i]='\0'; | 1473 | name[i] = '\0'; |
1474 | 1474 | ||
1475 | saa711x_write(client, 0, 5); | 1475 | saa711x_write(client, 0, 5); |
1476 | chip_id = saa711x_read(client, 0) & 0x0f; | 1476 | chip_id = saa711x_read(client, 0) & 0x0f; |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 4abf5c03a740..ffb0f647a86d 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -1,10 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * SAA713x ALSA support for V4L | 2 | * SAA713x ALSA support for V4L |
3 | * | 3 | * |
4 | * | ||
5 | * Caveats: | ||
6 | * - Volume doesn't work (it's always at max) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation, version 2 | 6 | * the Free Software Foundation, version 2 |
@@ -614,13 +610,18 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream) | |||
614 | snd_card_saa7134_pcm_t *pcm; | 610 | snd_card_saa7134_pcm_t *pcm; |
615 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | 611 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
616 | struct saa7134_dev *dev = saa7134->dev; | 612 | struct saa7134_dev *dev = saa7134->dev; |
617 | int err; | 613 | int amux, err; |
618 | 614 | ||
619 | mutex_lock(&dev->dmasound.lock); | 615 | mutex_lock(&dev->dmasound.lock); |
620 | 616 | ||
621 | dev->dmasound.read_count = 0; | 617 | dev->dmasound.read_count = 0; |
622 | dev->dmasound.read_offset = 0; | 618 | dev->dmasound.read_offset = 0; |
623 | 619 | ||
620 | amux = dev->input->amux; | ||
621 | if ((amux < 1) || (amux > 3)) | ||
622 | amux = 1; | ||
623 | dev->dmasound.input = amux - 1; | ||
624 | |||
624 | mutex_unlock(&dev->dmasound.lock); | 625 | mutex_unlock(&dev->dmasound.lock); |
625 | 626 | ||
626 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); | 627 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
@@ -713,6 +714,8 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol, | |||
713 | struct snd_ctl_elem_value * ucontrol) | 714 | struct snd_ctl_elem_value * ucontrol) |
714 | { | 715 | { |
715 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | 716 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); |
717 | struct saa7134_dev *dev = chip->dev; | ||
718 | |||
716 | int change, addr = kcontrol->private_value; | 719 | int change, addr = kcontrol->private_value; |
717 | int left, right; | 720 | int left, right; |
718 | 721 | ||
@@ -727,10 +730,52 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol, | |||
727 | if (right > 20) | 730 | if (right > 20) |
728 | right = 20; | 731 | right = 20; |
729 | spin_lock_irq(&chip->mixer_lock); | 732 | spin_lock_irq(&chip->mixer_lock); |
730 | change = chip->mixer_volume[addr][0] != left || | 733 | change = 0; |
731 | chip->mixer_volume[addr][1] != right; | 734 | if (chip->mixer_volume[addr][0] != left) { |
732 | chip->mixer_volume[addr][0] = left; | 735 | change = 1; |
733 | chip->mixer_volume[addr][1] = right; | 736 | right = left; |
737 | } | ||
738 | if (chip->mixer_volume[addr][1] != right) { | ||
739 | change = 1; | ||
740 | left = right; | ||
741 | } | ||
742 | if (change) { | ||
743 | switch (dev->pci->device) { | ||
744 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
745 | switch (addr) { | ||
746 | case MIXER_ADDR_TVTUNER: | ||
747 | left = 20; | ||
748 | break; | ||
749 | case MIXER_ADDR_LINE1: | ||
750 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x10, | ||
751 | (left > 10) ? 0x00 : 0x10); | ||
752 | break; | ||
753 | case MIXER_ADDR_LINE2: | ||
754 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x20, | ||
755 | (left > 10) ? 0x00 : 0x20); | ||
756 | break; | ||
757 | } | ||
758 | break; | ||
759 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
760 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
761 | switch (addr) { | ||
762 | case MIXER_ADDR_TVTUNER: | ||
763 | left = 20; | ||
764 | break; | ||
765 | case MIXER_ADDR_LINE1: | ||
766 | saa_andorb(0x0594, 0x10, | ||
767 | (left > 10) ? 0x00 : 0x10); | ||
768 | break; | ||
769 | case MIXER_ADDR_LINE2: | ||
770 | saa_andorb(0x0594, 0x20, | ||
771 | (left > 10) ? 0x00 : 0x20); | ||
772 | break; | ||
773 | } | ||
774 | break; | ||
775 | } | ||
776 | chip->mixer_volume[addr][0] = left; | ||
777 | chip->mixer_volume[addr][1] = right; | ||
778 | } | ||
734 | spin_unlock_irq(&chip->mixer_lock); | 779 | spin_unlock_irq(&chip->mixer_lock); |
735 | return change; | 780 | return change; |
736 | } | 781 | } |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 51f0cfdcb680..4dead84aff46 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -2462,14 +2462,17 @@ struct saa7134_board saa7134_boards[] = { | |||
2462 | .vmux = 1, | 2462 | .vmux = 1, |
2463 | .amux = TV, | 2463 | .amux = TV, |
2464 | .tv = 1, | 2464 | .tv = 1, |
2465 | .gpio = 0x0000000, | ||
2465 | },{ | 2466 | },{ |
2466 | .name = name_comp1, | 2467 | .name = name_comp1, |
2467 | .vmux = 3, | 2468 | .vmux = 3, |
2468 | .amux = LINE2, | 2469 | .amux = LINE2, |
2470 | .gpio = 0x0200000, | ||
2469 | },{ | 2471 | },{ |
2470 | .name = name_svideo, | 2472 | .name = name_svideo, |
2471 | .vmux = 8, | 2473 | .vmux = 8, |
2472 | .amux = LINE2, | 2474 | .amux = LINE2, |
2475 | .gpio = 0x0200000, | ||
2473 | }}, | 2476 | }}, |
2474 | .radio = { | 2477 | .radio = { |
2475 | .name = name_radio, | 2478 | .name = name_radio, |
@@ -3022,6 +3025,158 @@ struct saa7134_board saa7134_boards[] = { | |||
3022 | .amux = LINE1, | 3025 | .amux = LINE1, |
3023 | }, | 3026 | }, |
3024 | }, | 3027 | }, |
3028 | [SAA7134_BOARD_PINNACLE_PCTV_310i] = { | ||
3029 | .name = "Pinnacle PCTV 310i", | ||
3030 | .audio_clock = 0x00187de7, | ||
3031 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
3032 | .radio_type = UNSET, | ||
3033 | .tuner_addr = ADDR_UNSET, | ||
3034 | .radio_addr = ADDR_UNSET, | ||
3035 | .mpeg = SAA7134_MPEG_DVB, | ||
3036 | .gpiomask = 0x000200000, | ||
3037 | .inputs = {{ | ||
3038 | .name = name_tv, | ||
3039 | .vmux = 4, | ||
3040 | .amux = TV, | ||
3041 | .tv = 1, | ||
3042 | },{ | ||
3043 | .name = name_comp1, | ||
3044 | .vmux = 1, | ||
3045 | .amux = LINE2, | ||
3046 | },{ | ||
3047 | .name = name_comp2, | ||
3048 | .vmux = 0, | ||
3049 | .amux = LINE2, | ||
3050 | },{ | ||
3051 | .name = name_svideo, | ||
3052 | .vmux = 8, | ||
3053 | .amux = LINE2, | ||
3054 | }}, | ||
3055 | .radio = { | ||
3056 | .name = name_radio, | ||
3057 | .amux = TV, | ||
3058 | .gpio = 0x0200000, | ||
3059 | }, | ||
3060 | }, | ||
3061 | [SAA7134_BOARD_AVERMEDIA_STUDIO_507] = { | ||
3062 | /* Mikhail Fedotov <mo_fedotov@mail.ru> */ | ||
3063 | .name = "Avermedia AVerTV Studio 507", | ||
3064 | .audio_clock = 0x00187de7, | ||
3065 | .tuner_type = TUNER_PHILIPS_FM1256_IH3, | ||
3066 | .radio_type = UNSET, | ||
3067 | .tuner_addr = ADDR_UNSET, | ||
3068 | .radio_addr = ADDR_UNSET, | ||
3069 | .tda9887_conf = TDA9887_PRESENT, | ||
3070 | .gpiomask = 0x03, | ||
3071 | .inputs = {{ | ||
3072 | .name = name_tv, | ||
3073 | .vmux = 1, | ||
3074 | .amux = TV, | ||
3075 | .tv = 1, | ||
3076 | .gpio = 0x00, | ||
3077 | },{ | ||
3078 | .name = name_comp1, | ||
3079 | .vmux = 0, | ||
3080 | .amux = LINE2, | ||
3081 | .gpio = 0x00, | ||
3082 | },{ | ||
3083 | .name = name_comp2, | ||
3084 | .vmux = 3, | ||
3085 | .amux = LINE2, | ||
3086 | .gpio = 0x00, | ||
3087 | },{ | ||
3088 | .name = name_svideo, | ||
3089 | .vmux = 8, | ||
3090 | .amux = LINE2, | ||
3091 | .gpio = 0x00, | ||
3092 | }}, | ||
3093 | .radio = { | ||
3094 | .name = name_radio, | ||
3095 | .amux = LINE2, | ||
3096 | .gpio = 0x01, | ||
3097 | }, | ||
3098 | .mute = { | ||
3099 | .name = name_mute, | ||
3100 | .amux = LINE1, | ||
3101 | .gpio = 0x00, | ||
3102 | }, | ||
3103 | }, | ||
3104 | [SAA7134_BOARD_VIDEOMATE_DVBT_200A] = { | ||
3105 | /* Francis Barber <fedora@barber-family.id.au> */ | ||
3106 | .name = "Compro Videomate DVB-T200A", | ||
3107 | .audio_clock = 0x00187de7, | ||
3108 | .tuner_type = TUNER_ABSENT, | ||
3109 | .radio_type = UNSET, | ||
3110 | .tuner_addr = ADDR_UNSET, | ||
3111 | .radio_addr = ADDR_UNSET, | ||
3112 | .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, | ||
3113 | .mpeg = SAA7134_MPEG_DVB, | ||
3114 | .inputs = {{ | ||
3115 | .name = name_tv, | ||
3116 | .vmux = 3, | ||
3117 | .amux = TV, | ||
3118 | .tv = 1, | ||
3119 | },{ | ||
3120 | .name = name_comp1, | ||
3121 | .vmux = 1, | ||
3122 | .amux = LINE2, | ||
3123 | },{ | ||
3124 | .name = name_svideo, | ||
3125 | .vmux = 8, | ||
3126 | .amux = LINE2, | ||
3127 | }}, | ||
3128 | }, | ||
3129 | [SAA7134_BOARD_HAUPPAUGE_HVR1110] = { | ||
3130 | /* Thomas Genty <tomlohave@gmail.com> */ | ||
3131 | .name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid", | ||
3132 | .audio_clock = 0x00187de7, | ||
3133 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
3134 | .radio_type = UNSET, | ||
3135 | .tuner_addr = ADDR_UNSET, | ||
3136 | .radio_addr = ADDR_UNSET, | ||
3137 | .mpeg = SAA7134_MPEG_DVB, | ||
3138 | .inputs = {{ | ||
3139 | .name = name_tv, | ||
3140 | .vmux = 1, | ||
3141 | .amux = TV, | ||
3142 | .tv = 1, | ||
3143 | },{ | ||
3144 | .name = name_comp1, | ||
3145 | .vmux = 3, | ||
3146 | .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ | ||
3147 | },{ | ||
3148 | .name = name_svideo, | ||
3149 | .vmux = 8, | ||
3150 | .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ | ||
3151 | }}, | ||
3152 | .radio = { | ||
3153 | .name = name_radio, | ||
3154 | .amux = TV, | ||
3155 | }, | ||
3156 | }, | ||
3157 | [SAA7134_BOARD_CINERGY_HT_PCMCIA] = { | ||
3158 | .name = "Terratec Cinergy HT PCMCIA", | ||
3159 | .audio_clock = 0x00187de7, | ||
3160 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
3161 | .radio_type = UNSET, | ||
3162 | .tuner_addr = ADDR_UNSET, | ||
3163 | .radio_addr = ADDR_UNSET, | ||
3164 | .mpeg = SAA7134_MPEG_DVB, | ||
3165 | .inputs = {{ | ||
3166 | .name = name_tv, | ||
3167 | .vmux = 1, | ||
3168 | .amux = TV, | ||
3169 | .tv = 1, | ||
3170 | },{ | ||
3171 | .name = name_comp1, | ||
3172 | .vmux = 0, | ||
3173 | .amux = LINE1, | ||
3174 | },{ | ||
3175 | .name = name_svideo, | ||
3176 | .vmux = 6, | ||
3177 | .amux = LINE1, | ||
3178 | }}, | ||
3179 | }, | ||
3025 | }; | 3180 | }; |
3026 | 3181 | ||
3027 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); | 3182 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); |
@@ -3631,6 +3786,36 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
3631 | .subdevice = 0x4860, | 3786 | .subdevice = 0x4860, |
3632 | .driver_data = SAA7134_BOARD_ASUS_EUROPA2_HYBRID, | 3787 | .driver_data = SAA7134_BOARD_ASUS_EUROPA2_HYBRID, |
3633 | },{ | 3788 | },{ |
3789 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3790 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3791 | .subvendor = 0x11bd, | ||
3792 | .subdevice = 0x002f, | ||
3793 | .driver_data = SAA7134_BOARD_PINNACLE_PCTV_310i, | ||
3794 | },{ | ||
3795 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3796 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3797 | .subvendor = 0x1461, /* Avermedia Technologies Inc */ | ||
3798 | .subdevice = 0x9715, | ||
3799 | .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507, | ||
3800 | },{ | ||
3801 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3802 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3803 | .subvendor = 0x1043, | ||
3804 | .subdevice = 0x4876, | ||
3805 | .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, | ||
3806 | },{ | ||
3807 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3808 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3809 | .subvendor = 0x0070, | ||
3810 | .subdevice = 0x6701, | ||
3811 | .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, | ||
3812 | },{ | ||
3813 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3814 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3815 | .subvendor = 0x153b, | ||
3816 | .subdevice = 0x1172, | ||
3817 | .driver_data = SAA7134_BOARD_CINERGY_HT_PCMCIA, | ||
3818 | },{ | ||
3634 | /* --- boards without eeprom + subsystem ID --- */ | 3819 | /* --- boards without eeprom + subsystem ID --- */ |
3635 | .vendor = PCI_VENDOR_ID_PHILIPS, | 3820 | .vendor = PCI_VENDOR_ID_PHILIPS, |
3636 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 3821 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
@@ -3717,6 +3902,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
3717 | case SAA7134_BOARD_AVERMEDIA_305: | 3902 | case SAA7134_BOARD_AVERMEDIA_305: |
3718 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: | 3903 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: |
3719 | case SAA7134_BOARD_AVERMEDIA_307: | 3904 | case SAA7134_BOARD_AVERMEDIA_307: |
3905 | case SAA7134_BOARD_AVERMEDIA_STUDIO_507: | ||
3720 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: | 3906 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: |
3721 | case SAA7134_BOARD_AVERMEDIA_777: | 3907 | case SAA7134_BOARD_AVERMEDIA_777: |
3722 | /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ | 3908 | /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ |
@@ -3725,6 +3911,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
3725 | case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: | 3911 | case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: |
3726 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: | 3912 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: |
3727 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: | 3913 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: |
3914 | case SAA7134_BOARD_VIDEOMATE_DVBT_200A: | ||
3728 | case SAA7134_BOARD_MANLI_MTV001: | 3915 | case SAA7134_BOARD_MANLI_MTV001: |
3729 | case SAA7134_BOARD_MANLI_MTV002: | 3916 | case SAA7134_BOARD_MANLI_MTV002: |
3730 | case SAA7134_BOARD_BEHOLD_409FM: | 3917 | case SAA7134_BOARD_BEHOLD_409FM: |
@@ -3793,7 +3980,9 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
3793 | break; | 3980 | break; |
3794 | /* i2c remotes */ | 3981 | /* i2c remotes */ |
3795 | case SAA7134_BOARD_PINNACLE_PCTV_110i: | 3982 | case SAA7134_BOARD_PINNACLE_PCTV_110i: |
3983 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | ||
3796 | case SAA7134_BOARD_UPMOST_PURPLE_TV: | 3984 | case SAA7134_BOARD_UPMOST_PURPLE_TV: |
3985 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | ||
3797 | dev->has_remote = SAA7134_REMOTE_I2C; | 3986 | dev->has_remote = SAA7134_REMOTE_I2C; |
3798 | break; | 3987 | break; |
3799 | case SAA7134_BOARD_AVERMEDIA_A169_B: | 3988 | case SAA7134_BOARD_AVERMEDIA_A169_B: |
@@ -3924,9 +4113,11 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
3924 | } | 4113 | } |
3925 | break; | 4114 | break; |
3926 | case SAA7134_BOARD_PHILIPS_TIGER: | 4115 | case SAA7134_BOARD_PHILIPS_TIGER: |
4116 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | ||
3927 | case SAA7134_BOARD_TEVION_DVBT_220RF: | 4117 | case SAA7134_BOARD_TEVION_DVBT_220RF: |
3928 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | 4118 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: |
3929 | case SAA7134_BOARD_MEDION_MD8800_QUADRO: | 4119 | case SAA7134_BOARD_MEDION_MD8800_QUADRO: |
4120 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | ||
3930 | /* this is a hybrid board, initialize to analog mode | 4121 | /* this is a hybrid board, initialize to analog mode |
3931 | * and configure firmware eeprom address | 4122 | * and configure firmware eeprom address |
3932 | */ | 4123 | */ |
@@ -3952,6 +4143,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
3952 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 4143 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
3953 | } | 4144 | } |
3954 | break; | 4145 | break; |
4146 | case SAA7134_BOARD_CINERGY_HT_PCMCIA: | ||
4147 | /* make the tda10046 find its eeprom */ | ||
4148 | { | ||
4149 | u8 data[] = { 0x3c, 0x33, 0x60}; | ||
4150 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; | ||
4151 | i2c_transfer(&dev->i2c_adap, &msg, 1); | ||
4152 | } | ||
4153 | break; | ||
3955 | case SAA7134_BOARD_KWORLD_ATSC110: | 4154 | case SAA7134_BOARD_KWORLD_ATSC110: |
3956 | { | 4155 | { |
3957 | /* enable tuner */ | 4156 | /* enable tuner */ |
@@ -3964,6 +4163,29 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
3964 | dev->name, i); | 4163 | dev->name, i); |
3965 | } | 4164 | } |
3966 | break; | 4165 | break; |
4166 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: | ||
4167 | case SAA7134_BOARD_VIDEOMATE_DVBT_200A: | ||
4168 | /* The T200 and the T200A share the same pci id. Consequently, | ||
4169 | * we are going to query eeprom to try to find out which one we | ||
4170 | * are actually looking at. */ | ||
4171 | |||
4172 | /* Don't do this if the board was specifically selected with an | ||
4173 | * insmod option or if we have the default configuration T200*/ | ||
4174 | if(!dev->autodetected || (dev->eedata[0x41] == 0xd0)) | ||
4175 | break; | ||
4176 | if(dev->eedata[0x41] == 0x02) { | ||
4177 | /* Reconfigure board as T200A */ | ||
4178 | dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A; | ||
4179 | dev->tuner_type = saa7134_boards[dev->board].tuner_type; | ||
4180 | dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; | ||
4181 | printk(KERN_INFO "%s: Reconfigured board as %s\n", | ||
4182 | dev->name, saa7134_boards[dev->board].name); | ||
4183 | } else { | ||
4184 | printk(KERN_WARNING "%s: Unexpected tuner type info: %x in eeprom\n", | ||
4185 | dev->name, dev->eedata[0x41]); | ||
4186 | break; | ||
4187 | } | ||
4188 | break; | ||
3967 | } | 4189 | } |
3968 | return 0; | 4190 | return 0; |
3969 | } | 4191 | } |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 5c9e63dfbea6..ed038fff3b4f 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -889,15 +889,16 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
889 | must_configure_manually(); | 889 | must_configure_manually(); |
890 | dev->board = SAA7134_BOARD_UNKNOWN; | 890 | dev->board = SAA7134_BOARD_UNKNOWN; |
891 | } | 891 | } |
892 | dev->autodetected = card[dev->nr] != dev->board; | ||
892 | dev->tuner_type = saa7134_boards[dev->board].tuner_type; | 893 | dev->tuner_type = saa7134_boards[dev->board].tuner_type; |
893 | dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; | 894 | dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; |
894 | if (UNSET != tuner[dev->nr]) | 895 | if (UNSET != tuner[dev->nr]) |
895 | dev->tuner_type = tuner[dev->nr]; | 896 | dev->tuner_type = tuner[dev->nr]; |
896 | printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", | 897 | printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", |
897 | dev->name,pci_dev->subsystem_vendor, | 898 | dev->name,pci_dev->subsystem_vendor, |
898 | pci_dev->subsystem_device,saa7134_boards[dev->board].name, | 899 | pci_dev->subsystem_device,saa7134_boards[dev->board].name, |
899 | dev->board, card[dev->nr] == dev->board ? | 900 | dev->board, dev->autodetected ? |
900 | "insmod option" : "autodetected"); | 901 | "autodetected" : "insmod option"); |
901 | 902 | ||
902 | /* get mmio */ | 903 | /* get mmio */ |
903 | if (!request_mem_region(pci_resource_start(pci_dev,0), | 904 | if (!request_mem_region(pci_resource_start(pci_dev,0), |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 6b61d9b2fcb5..fa8339879095 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -50,6 +50,10 @@ static unsigned int antenna_pwr = 0; | |||
50 | module_param(antenna_pwr, int, 0444); | 50 | module_param(antenna_pwr, int, 0444); |
51 | MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)"); | 51 | MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)"); |
52 | 52 | ||
53 | static int use_frontent = 0; | ||
54 | module_param(use_frontent, int, 0644); | ||
55 | MODULE_PARM_DESC(use_frontent,"for cards with multiple frontends (0: terrestrial, 1: satellite)"); | ||
56 | |||
53 | /* ------------------------------------------------------------------ */ | 57 | /* ------------------------------------------------------------------ */ |
54 | static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on) | 58 | static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on) |
55 | { | 59 | { |
@@ -293,7 +297,7 @@ static int philips_tu1216_tuner_60_set_params(struct dvb_frontend *fe, struct dv | |||
293 | return philips_tda6651_pll_set(0x60, fe, params); | 297 | return philips_tda6651_pll_set(0x60, fe, params); |
294 | } | 298 | } |
295 | 299 | ||
296 | static int philips_tu1216_request_firmware(struct dvb_frontend *fe, | 300 | static int philips_tda1004x_request_firmware(struct dvb_frontend *fe, |
297 | const struct firmware **fw, char *name) | 301 | const struct firmware **fw, char *name) |
298 | { | 302 | { |
299 | struct saa7134_dev *dev = fe->dvb->priv; | 303 | struct saa7134_dev *dev = fe->dvb->priv; |
@@ -308,7 +312,7 @@ static struct tda1004x_config philips_tu1216_60_config = { | |||
308 | .xtal_freq = TDA10046_XTAL_4M, | 312 | .xtal_freq = TDA10046_XTAL_4M, |
309 | .agc_config = TDA10046_AGC_DEFAULT, | 313 | .agc_config = TDA10046_AGC_DEFAULT, |
310 | .if_freq = TDA10046_FREQ_3617, | 314 | .if_freq = TDA10046_FREQ_3617, |
311 | .request_firmware = philips_tu1216_request_firmware, | 315 | .request_firmware = philips_tda1004x_request_firmware, |
312 | }; | 316 | }; |
313 | 317 | ||
314 | /* ------------------------------------------------------------------ */ | 318 | /* ------------------------------------------------------------------ */ |
@@ -331,12 +335,12 @@ static struct tda1004x_config philips_tu1216_61_config = { | |||
331 | .xtal_freq = TDA10046_XTAL_4M, | 335 | .xtal_freq = TDA10046_XTAL_4M, |
332 | .agc_config = TDA10046_AGC_DEFAULT, | 336 | .agc_config = TDA10046_AGC_DEFAULT, |
333 | .if_freq = TDA10046_FREQ_3617, | 337 | .if_freq = TDA10046_FREQ_3617, |
334 | .request_firmware = philips_tu1216_request_firmware, | 338 | .request_firmware = philips_tda1004x_request_firmware, |
335 | }; | 339 | }; |
336 | 340 | ||
337 | /* ------------------------------------------------------------------ */ | 341 | /* ------------------------------------------------------------------ */ |
338 | 342 | ||
339 | static int philips_europa_tuner_init(struct dvb_frontend *fe) | 343 | static int philips_td1316_tuner_init(struct dvb_frontend *fe) |
340 | { | 344 | { |
341 | struct saa7134_dev *dev = fe->dvb->priv; | 345 | struct saa7134_dev *dev = fe->dvb->priv; |
342 | static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab }; | 346 | static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab }; |
@@ -347,18 +351,8 @@ static int philips_europa_tuner_init(struct dvb_frontend *fe) | |||
347 | fe->ops.i2c_gate_ctrl(fe, 1); | 351 | fe->ops.i2c_gate_ctrl(fe, 1); |
348 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) | 352 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) |
349 | return -EIO; | 353 | return -EIO; |
350 | msleep(1); | ||
351 | |||
352 | /* switch the board to dvb mode */ | ||
353 | init_msg.addr = 0x43; | ||
354 | init_msg.len = 0x02; | ||
355 | msg[0] = 0x00; | ||
356 | msg[1] = 0x40; | ||
357 | if (fe->ops.i2c_gate_ctrl) | 354 | if (fe->ops.i2c_gate_ctrl) |
358 | fe->ops.i2c_gate_ctrl(fe, 1); | 355 | fe->ops.i2c_gate_ctrl(fe, 0); |
359 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) | ||
360 | return -EIO; | ||
361 | |||
362 | return 0; | 356 | return 0; |
363 | } | 357 | } |
364 | 358 | ||
@@ -367,6 +361,22 @@ static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_f | |||
367 | return philips_tda6651_pll_set(0x61, fe, params); | 361 | return philips_tda6651_pll_set(0x61, fe, params); |
368 | } | 362 | } |
369 | 363 | ||
364 | static int philips_europa_tuner_init(struct dvb_frontend *fe) | ||
365 | { | ||
366 | struct saa7134_dev *dev = fe->dvb->priv; | ||
367 | static u8 msg[] = { 0x00, 0x40}; | ||
368 | struct i2c_msg init_msg = {.addr = 0x43,.flags = 0,.buf = msg,.len = sizeof(msg) }; | ||
369 | |||
370 | |||
371 | if (philips_td1316_tuner_init(fe)) | ||
372 | return -EIO; | ||
373 | msleep(1); | ||
374 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) | ||
375 | return -EIO; | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
370 | static int philips_europa_tuner_sleep(struct dvb_frontend *fe) | 380 | static int philips_europa_tuner_sleep(struct dvb_frontend *fe) |
371 | { | 381 | { |
372 | struct saa7134_dev *dev = fe->dvb->priv; | 382 | struct saa7134_dev *dev = fe->dvb->priv; |
@@ -671,7 +681,7 @@ static struct tda1004x_config tda827x_lifeview_config = { | |||
671 | .invert = 1, | 681 | .invert = 1, |
672 | .invert_oclk = 0, | 682 | .invert_oclk = 0, |
673 | .xtal_freq = TDA10046_XTAL_16M, | 683 | .xtal_freq = TDA10046_XTAL_16M, |
674 | .agc_config = TDA10046_AGC_TDA827X, | 684 | .agc_config = TDA10046_AGC_TDA827X_GP11, |
675 | .if_freq = TDA10046_FREQ_045, | 685 | .if_freq = TDA10046_FREQ_045, |
676 | .request_firmware = NULL, | 686 | .request_firmware = NULL, |
677 | }; | 687 | }; |
@@ -812,32 +822,40 @@ static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe) | |||
812 | if (fe->ops.i2c_gate_ctrl) | 822 | if (fe->ops.i2c_gate_ctrl) |
813 | fe->ops.i2c_gate_ctrl(fe, 1); | 823 | fe->ops.i2c_gate_ctrl(fe, 1); |
814 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); | 824 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); |
825 | if (fe->ops.i2c_gate_ctrl) | ||
826 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
815 | return 0; | 827 | return 0; |
816 | } | 828 | } |
817 | 829 | ||
818 | /* ------------------------------------------------------------------ */ | 830 | /* ------------------------------------------------------------------ */ |
819 | 831 | ||
820 | static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 832 | static int tda8290_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) |
821 | { | 833 | { |
822 | int ret; | ||
823 | struct saa7134_dev *dev = fe->dvb->priv; | 834 | struct saa7134_dev *dev = fe->dvb->priv; |
824 | static u8 tda8290_close[] = { 0x21, 0xc0}; | 835 | static u8 tda8290_close[] = { 0x21, 0xc0}; |
825 | static u8 tda8290_open[] = { 0x21, 0x80}; | 836 | static u8 tda8290_open[] = { 0x21, 0x80}; |
826 | struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2}; | 837 | struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2}; |
827 | 838 | if (enable) { | |
828 | /* close tda8290 i2c bridge */ | 839 | tda8290_msg.buf = tda8290_close; |
829 | tda8290_msg.buf = tda8290_close; | 840 | } else { |
830 | ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); | 841 | tda8290_msg.buf = tda8290_open; |
831 | if (ret != 1) | 842 | } |
843 | if (i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1) != 1) | ||
832 | return -EIO; | 844 | return -EIO; |
833 | msleep(20); | 845 | msleep(20); |
846 | return 0; | ||
847 | } | ||
848 | |||
849 | /* ------------------------------------------------------------------ */ | ||
850 | |||
851 | static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | ||
852 | { | ||
853 | int ret; | ||
854 | |||
834 | ret = philips_tda827xa_pll_set(0x61, fe, params); | 855 | ret = philips_tda827xa_pll_set(0x61, fe, params); |
835 | if (ret != 0) | 856 | if (ret != 0) |
836 | return ret; | 857 | return ret; |
837 | /* open tda8290 i2c bridge */ | 858 | return 0; |
838 | tda8290_msg.buf = tda8290_open; | ||
839 | i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); | ||
840 | return ret; | ||
841 | } | 859 | } |
842 | 860 | ||
843 | static int philips_tiger_tuner_init(struct dvb_frontend *fe) | 861 | static int philips_tiger_tuner_init(struct dvb_frontend *fe) |
@@ -867,13 +885,80 @@ static struct tda1004x_config philips_tiger_config = { | |||
867 | .invert = 1, | 885 | .invert = 1, |
868 | .invert_oclk = 0, | 886 | .invert_oclk = 0, |
869 | .xtal_freq = TDA10046_XTAL_16M, | 887 | .xtal_freq = TDA10046_XTAL_16M, |
870 | .agc_config = TDA10046_AGC_TDA827X, | 888 | .agc_config = TDA10046_AGC_TDA827X_GP11, |
889 | .if_freq = TDA10046_FREQ_045, | ||
890 | .request_firmware = NULL, | ||
891 | }; | ||
892 | /* ------------------------------------------------------------------ */ | ||
893 | |||
894 | static int cinergy_ht_tuner_init(struct dvb_frontend *fe) | ||
895 | { | ||
896 | struct saa7134_dev *dev = fe->dvb->priv; | ||
897 | static u8 data[] = { 0x3c, 0x33, 0x62}; | ||
898 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; | ||
899 | |||
900 | if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) | ||
901 | return -EIO; | ||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | static int cinergy_ht_tuner_sleep(struct dvb_frontend *fe) | ||
906 | { | ||
907 | struct saa7134_dev *dev = fe->dvb->priv; | ||
908 | static u8 data[] = { 0x3c, 0x33, 0x60}; | ||
909 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; | ||
910 | |||
911 | i2c_transfer(&dev->i2c_adap, &msg, 1); | ||
912 | philips_tda827xa_tuner_sleep( 0x61, fe); | ||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | static struct tda1004x_config cinergy_ht_config = { | ||
917 | .demod_address = 0x08, | ||
918 | .invert = 1, | ||
919 | .invert_oclk = 0, | ||
920 | .xtal_freq = TDA10046_XTAL_16M, | ||
921 | .agc_config = TDA10046_AGC_TDA827X_GP01, | ||
871 | .if_freq = TDA10046_FREQ_045, | 922 | .if_freq = TDA10046_FREQ_045, |
872 | .request_firmware = NULL, | 923 | .request_firmware = NULL, |
873 | }; | 924 | }; |
874 | 925 | ||
875 | /* ------------------------------------------------------------------ */ | 926 | /* ------------------------------------------------------------------ */ |
876 | 927 | ||
928 | static struct tda1004x_config pinnacle_pctv_310i_config = { | ||
929 | .demod_address = 0x08, | ||
930 | .invert = 1, | ||
931 | .invert_oclk = 0, | ||
932 | .xtal_freq = TDA10046_XTAL_16M, | ||
933 | .agc_config = TDA10046_AGC_TDA827X_GP11, | ||
934 | .if_freq = TDA10046_FREQ_045, | ||
935 | .request_firmware = philips_tda1004x_request_firmware, | ||
936 | }; | ||
937 | |||
938 | /* ------------------------------------------------------------------ */ | ||
939 | |||
940 | static struct tda1004x_config hauppauge_hvr_1110_config = { | ||
941 | .demod_address = 0x08, | ||
942 | .invert = 1, | ||
943 | .invert_oclk = 0, | ||
944 | .xtal_freq = TDA10046_XTAL_16M, | ||
945 | .agc_config = TDA10046_AGC_TDA827X_GP11, | ||
946 | .if_freq = TDA10046_FREQ_045, | ||
947 | .request_firmware = philips_tda1004x_request_firmware, | ||
948 | }; | ||
949 | |||
950 | /* ------------------------------------------------------------------ */ | ||
951 | |||
952 | static struct tda1004x_config asus_p7131_dual_config = { | ||
953 | .demod_address = 0x08, | ||
954 | .invert = 1, | ||
955 | .invert_oclk = 0, | ||
956 | .xtal_freq = TDA10046_XTAL_16M, | ||
957 | .agc_config = TDA10046_AGC_TDA827X_GP11, | ||
958 | .if_freq = TDA10046_FREQ_045, | ||
959 | .request_firmware = philips_tda1004x_request_firmware, | ||
960 | }; | ||
961 | |||
877 | static int asus_p7131_dual_tuner_init(struct dvb_frontend *fe) | 962 | static int asus_p7131_dual_tuner_init(struct dvb_frontend *fe) |
878 | { | 963 | { |
879 | struct saa7134_dev *dev = fe->dvb->priv; | 964 | struct saa7134_dev *dev = fe->dvb->priv; |
@@ -921,7 +1006,7 @@ static struct tda1004x_config lifeview_trio_config = { | |||
921 | .invert = 1, | 1006 | .invert = 1, |
922 | .invert_oclk = 0, | 1007 | .invert_oclk = 0, |
923 | .xtal_freq = TDA10046_XTAL_16M, | 1008 | .xtal_freq = TDA10046_XTAL_16M, |
924 | .agc_config = TDA10046_AGC_TDA827X_GPL, | 1009 | .agc_config = TDA10046_AGC_TDA827X_GP00, |
925 | .if_freq = TDA10046_FREQ_045, | 1010 | .if_freq = TDA10046_FREQ_045, |
926 | .request_firmware = NULL, | 1011 | .request_firmware = NULL, |
927 | }; | 1012 | }; |
@@ -958,7 +1043,7 @@ static struct tda1004x_config ads_tech_duo_config = { | |||
958 | .invert = 1, | 1043 | .invert = 1, |
959 | .invert_oclk = 0, | 1044 | .invert_oclk = 0, |
960 | .xtal_freq = TDA10046_XTAL_16M, | 1045 | .xtal_freq = TDA10046_XTAL_16M, |
961 | .agc_config = TDA10046_AGC_TDA827X_GPL, | 1046 | .agc_config = TDA10046_AGC_TDA827X_GP00, |
962 | .if_freq = TDA10046_FREQ_045, | 1047 | .if_freq = TDA10046_FREQ_045, |
963 | .request_firmware = NULL, | 1048 | .request_firmware = NULL, |
964 | }; | 1049 | }; |
@@ -983,7 +1068,7 @@ static struct tda1004x_config tevion_dvbt220rf_config = { | |||
983 | .invert = 1, | 1068 | .invert = 1, |
984 | .invert_oclk = 0, | 1069 | .invert_oclk = 0, |
985 | .xtal_freq = TDA10046_XTAL_16M, | 1070 | .xtal_freq = TDA10046_XTAL_16M, |
986 | .agc_config = TDA10046_AGC_TDA827X, | 1071 | .agc_config = TDA10046_AGC_TDA827X_GP11, |
987 | .if_freq = TDA10046_FREQ_045, | 1072 | .if_freq = TDA10046_FREQ_045, |
988 | .request_firmware = NULL, | 1073 | .request_firmware = NULL, |
989 | }; | 1074 | }; |
@@ -1028,7 +1113,7 @@ static struct tda1004x_config md8800_dvbt_config = { | |||
1028 | .invert = 1, | 1113 | .invert = 1, |
1029 | .invert_oclk = 0, | 1114 | .invert_oclk = 0, |
1030 | .xtal_freq = TDA10046_XTAL_16M, | 1115 | .xtal_freq = TDA10046_XTAL_16M, |
1031 | .agc_config = TDA10046_AGC_TDA827X, | 1116 | .agc_config = TDA10046_AGC_TDA827X_GP11, |
1032 | .if_freq = TDA10046_FREQ_045, | 1117 | .if_freq = TDA10046_FREQ_045, |
1033 | .request_firmware = NULL, | 1118 | .request_firmware = NULL, |
1034 | }; | 1119 | }; |
@@ -1168,6 +1253,29 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1168 | &philips_tiger_config, | 1253 | &philips_tiger_config, |
1169 | &dev->i2c_adap); | 1254 | &dev->i2c_adap); |
1170 | if (dev->dvb.frontend) { | 1255 | if (dev->dvb.frontend) { |
1256 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1257 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; | ||
1258 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; | ||
1259 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | ||
1260 | } | ||
1261 | break; | ||
1262 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | ||
1263 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1264 | &pinnacle_pctv_310i_config, | ||
1265 | &dev->i2c_adap); | ||
1266 | if (dev->dvb.frontend) { | ||
1267 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1268 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; | ||
1269 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; | ||
1270 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | ||
1271 | } | ||
1272 | break; | ||
1273 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | ||
1274 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1275 | &hauppauge_hvr_1110_config, | ||
1276 | &dev->i2c_adap); | ||
1277 | if (dev->dvb.frontend) { | ||
1278 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1171 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; | 1279 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; |
1172 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; | 1280 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; |
1173 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | 1281 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; |
@@ -1175,9 +1283,10 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1175 | break; | 1283 | break; |
1176 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | 1284 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: |
1177 | dev->dvb.frontend = dvb_attach(tda10046_attach, | 1285 | dev->dvb.frontend = dvb_attach(tda10046_attach, |
1178 | &philips_tiger_config, | 1286 | &asus_p7131_dual_config, |
1179 | &dev->i2c_adap); | 1287 | &dev->i2c_adap); |
1180 | if (dev->dvb.frontend) { | 1288 | if (dev->dvb.frontend) { |
1289 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1181 | dev->dvb.frontend->ops.tuner_ops.init = asus_p7131_dual_tuner_init; | 1290 | dev->dvb.frontend->ops.tuner_ops.init = asus_p7131_dual_tuner_init; |
1182 | dev->dvb.frontend->ops.tuner_ops.sleep = asus_p7131_dual_tuner_sleep; | 1291 | dev->dvb.frontend->ops.tuner_ops.sleep = asus_p7131_dual_tuner_sleep; |
1183 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | 1292 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; |
@@ -1194,12 +1303,27 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1194 | } | 1303 | } |
1195 | break; | 1304 | break; |
1196 | case SAA7134_BOARD_FLYDVB_TRIO: | 1305 | case SAA7134_BOARD_FLYDVB_TRIO: |
1197 | dev->dvb.frontend = dvb_attach(tda10046_attach, | 1306 | if(! use_frontent) { //terrestrial |
1198 | &lifeview_trio_config, | 1307 | dev->dvb.frontend = dvb_attach(tda10046_attach, |
1199 | &dev->i2c_adap); | 1308 | &lifeview_trio_config, |
1200 | if (dev->dvb.frontend) { | 1309 | &dev->i2c_adap); |
1201 | dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep; | 1310 | if (dev->dvb.frontend) { |
1202 | dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params; | 1311 | dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep; |
1312 | dev->dvb.frontend->ops.tuner_ops.set_params = | ||
1313 | lifeview_trio_tuner_set_params; | ||
1314 | } | ||
1315 | } else { //satellite | ||
1316 | dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); | ||
1317 | if (dev->dvb.frontend) { | ||
1318 | if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, | ||
1319 | &dev->i2c_adap, 0) == NULL) { | ||
1320 | printk("%s: Lifeview Trio, No tda826x found!\n", __FUNCTION__); | ||
1321 | } | ||
1322 | if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap, | ||
1323 | 0x08, 0, 0) == NULL) { | ||
1324 | printk("%s: Lifeview Trio, No ISL6421 found!\n", __FUNCTION__); | ||
1325 | } | ||
1326 | } | ||
1203 | } | 1327 | } |
1204 | break; | 1328 | break; |
1205 | case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: | 1329 | case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: |
@@ -1281,7 +1405,27 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1281 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; | 1405 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; |
1282 | } | 1406 | } |
1283 | break; | 1407 | break; |
1408 | case SAA7134_BOARD_VIDEOMATE_DVBT_200A: | ||
1409 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1410 | &philips_europa_config, | ||
1411 | &dev->i2c_adap); | ||
1412 | if (dev->dvb.frontend) { | ||
1413 | dev->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init; | ||
1414 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; | ||
1415 | } | ||
1416 | break; | ||
1417 | case SAA7134_BOARD_CINERGY_HT_PCMCIA: | ||
1418 | dev->dvb.frontend = dvb_attach(tda10046_attach, | ||
1419 | &cinergy_ht_config, | ||
1420 | &dev->i2c_adap); | ||
1421 | if (dev->dvb.frontend) { | ||
1422 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | ||
1423 | dev->dvb.frontend->ops.tuner_ops.init = cinergy_ht_tuner_init; | ||
1424 | dev->dvb.frontend->ops.tuner_ops.sleep = cinergy_ht_tuner_sleep; | ||
1425 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | ||
1284 | 1426 | ||
1427 | } | ||
1428 | break; | ||
1285 | default: | 1429 | default: |
1286 | printk("%s: Huh? unknown DVB card?\n",dev->name); | 1430 | printk("%s: Huh? unknown DVB card?\n",dev->name); |
1287 | break; | 1431 | break; |
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 6162550c4136..6f9fe86fed98 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c | |||
@@ -341,6 +341,7 @@ static int attach_inform(struct i2c_client *client) | |||
341 | switch (client->addr) { | 341 | switch (client->addr) { |
342 | case 0x7a: | 342 | case 0x7a: |
343 | case 0x47: | 343 | case 0x47: |
344 | case 0x71: | ||
344 | { | 345 | { |
345 | struct IR_i2c *ir = i2c_get_clientdata(client); | 346 | struct IR_i2c *ir = i2c_get_clientdata(client); |
346 | d1printk("%s i2c IR detected (%s).\n", | 347 | d1printk("%s i2c IR detected (%s).\n", |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index dee83552e681..60b38defd9bc 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -112,6 +112,27 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
112 | return 1; | 112 | return 1; |
113 | } | 113 | } |
114 | 114 | ||
115 | static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
116 | { | ||
117 | unsigned char buf[5], cod4, code3, code4; | ||
118 | |||
119 | /* poll IR chip */ | ||
120 | if (5 != i2c_master_recv(&ir->c,buf,5)) | ||
121 | return -EIO; | ||
122 | |||
123 | cod4 = buf[4]; | ||
124 | code4 = (cod4 >> 2); | ||
125 | code3 = buf[3]; | ||
126 | if (code3 == 0) | ||
127 | /* no key pressed */ | ||
128 | return 0; | ||
129 | |||
130 | /* return key */ | ||
131 | *ir_key = code4; | ||
132 | *ir_raw = code4; | ||
133 | return 1; | ||
134 | } | ||
135 | |||
115 | void saa7134_input_irq(struct saa7134_dev *dev) | 136 | void saa7134_input_irq(struct saa7134_dev *dev) |
116 | { | 137 | { |
117 | struct saa7134_ir *ir = dev->remote; | 138 | struct saa7134_ir *ir = dev->remote; |
@@ -131,6 +152,23 @@ static void saa7134_input_timer(unsigned long data) | |||
131 | mod_timer(&ir->timer, timeout); | 152 | mod_timer(&ir->timer, timeout); |
132 | } | 153 | } |
133 | 154 | ||
155 | static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir) | ||
156 | { | ||
157 | if (ir->polling) { | ||
158 | init_timer(&ir->timer); | ||
159 | ir->timer.function = saa7134_input_timer; | ||
160 | ir->timer.data = (unsigned long)dev; | ||
161 | ir->timer.expires = jiffies + HZ; | ||
162 | add_timer(&ir->timer); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | static void saa7134_ir_stop(struct saa7134_dev *dev) | ||
167 | { | ||
168 | if (dev->remote->polling) | ||
169 | del_timer_sync(&dev->remote->timer); | ||
170 | } | ||
171 | |||
134 | int saa7134_input_init1(struct saa7134_dev *dev) | 172 | int saa7134_input_init1(struct saa7134_dev *dev) |
135 | { | 173 | { |
136 | struct saa7134_ir *ir; | 174 | struct saa7134_ir *ir; |
@@ -141,6 +179,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
141 | u32 mask_keyup = 0; | 179 | u32 mask_keyup = 0; |
142 | int polling = 0; | 180 | int polling = 0; |
143 | int ir_type = IR_TYPE_OTHER; | 181 | int ir_type = IR_TYPE_OTHER; |
182 | int err; | ||
144 | 183 | ||
145 | if (dev->has_remote != SAA7134_REMOTE_GPIO) | 184 | if (dev->has_remote != SAA7134_REMOTE_GPIO) |
146 | return -ENODEV; | 185 | return -ENODEV; |
@@ -184,6 +223,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
184 | case SAA7134_BOARD_AVERMEDIA_307: | 223 | case SAA7134_BOARD_AVERMEDIA_307: |
185 | case SAA7134_BOARD_AVERMEDIA_STUDIO_305: | 224 | case SAA7134_BOARD_AVERMEDIA_STUDIO_305: |
186 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: | 225 | case SAA7134_BOARD_AVERMEDIA_STUDIO_307: |
226 | case SAA7134_BOARD_AVERMEDIA_STUDIO_507: | ||
187 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: | 227 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: |
188 | ir_codes = ir_codes_avermedia; | 228 | ir_codes = ir_codes_avermedia; |
189 | mask_keycode = 0x0007C8; | 229 | mask_keycode = 0x0007C8; |
@@ -266,9 +306,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
266 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | 306 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); |
267 | input_dev = input_allocate_device(); | 307 | input_dev = input_allocate_device(); |
268 | if (!ir || !input_dev) { | 308 | if (!ir || !input_dev) { |
269 | kfree(ir); | 309 | err = -ENOMEM; |
270 | input_free_device(input_dev); | 310 | goto err_out_free; |
271 | return -ENOMEM; | ||
272 | } | 311 | } |
273 | 312 | ||
274 | ir->dev = input_dev; | 313 | ir->dev = input_dev; |
@@ -299,18 +338,22 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
299 | } | 338 | } |
300 | input_dev->cdev.dev = &dev->pci->dev; | 339 | input_dev->cdev.dev = &dev->pci->dev; |
301 | 340 | ||
302 | /* all done */ | ||
303 | dev->remote = ir; | 341 | dev->remote = ir; |
304 | if (ir->polling) { | 342 | saa7134_ir_start(dev, ir); |
305 | init_timer(&ir->timer); | 343 | |
306 | ir->timer.function = saa7134_input_timer; | 344 | err = input_register_device(ir->dev); |
307 | ir->timer.data = (unsigned long)dev; | 345 | if (err) |
308 | ir->timer.expires = jiffies + HZ; | 346 | goto err_out_stop; |
309 | add_timer(&ir->timer); | ||
310 | } | ||
311 | 347 | ||
312 | input_register_device(ir->dev); | ||
313 | return 0; | 348 | return 0; |
349 | |||
350 | err_out_stop: | ||
351 | saa7134_ir_stop(dev); | ||
352 | dev->remote = NULL; | ||
353 | err_out_free: | ||
354 | input_free_device(input_dev); | ||
355 | kfree(ir); | ||
356 | return err; | ||
314 | } | 357 | } |
315 | 358 | ||
316 | void saa7134_input_fini(struct saa7134_dev *dev) | 359 | void saa7134_input_fini(struct saa7134_dev *dev) |
@@ -318,8 +361,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) | |||
318 | if (NULL == dev->remote) | 361 | if (NULL == dev->remote) |
319 | return; | 362 | return; |
320 | 363 | ||
321 | if (dev->remote->polling) | 364 | saa7134_ir_stop(dev); |
322 | del_timer_sync(&dev->remote->timer); | ||
323 | input_unregister_device(dev->remote->dev); | 365 | input_unregister_device(dev->remote->dev); |
324 | kfree(dev->remote); | 366 | kfree(dev->remote); |
325 | dev->remote = NULL; | 367 | dev->remote = NULL; |
@@ -335,6 +377,7 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) | |||
335 | 377 | ||
336 | switch (dev->board) { | 378 | switch (dev->board) { |
337 | case SAA7134_BOARD_PINNACLE_PCTV_110i: | 379 | case SAA7134_BOARD_PINNACLE_PCTV_110i: |
380 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | ||
338 | snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); | 381 | snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); |
339 | if (pinnacle_remote == 0) { | 382 | if (pinnacle_remote == 0) { |
340 | ir->get_key = get_key_pinnacle_color; | 383 | ir->get_key = get_key_pinnacle_color; |
@@ -349,6 +392,11 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) | |||
349 | ir->get_key = get_key_purpletv; | 392 | ir->get_key = get_key_purpletv; |
350 | ir->ir_codes = ir_codes_purpletv; | 393 | ir->ir_codes = ir_codes_purpletv; |
351 | break; | 394 | break; |
395 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | ||
396 | snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); | ||
397 | ir->get_key = get_key_hvr1110; | ||
398 | ir->ir_codes = ir_codes_hauppauge_new; | ||
399 | break; | ||
352 | default: | 400 | default: |
353 | dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board); | 401 | dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board); |
354 | break; | 402 | break; |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 7cf96b430250..e88ad7b40c47 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -227,6 +227,11 @@ struct saa7134_format { | |||
227 | #define SAA7134_BOARD_PROTEUS_2309 98 | 227 | #define SAA7134_BOARD_PROTEUS_2309 98 |
228 | #define SAA7134_BOARD_AVERMEDIA_A16AR 99 | 228 | #define SAA7134_BOARD_AVERMEDIA_A16AR 99 |
229 | #define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100 | 229 | #define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100 |
230 | #define SAA7134_BOARD_PINNACLE_PCTV_310i 101 | ||
231 | #define SAA7134_BOARD_AVERMEDIA_STUDIO_507 102 | ||
232 | #define SAA7134_BOARD_VIDEOMATE_DVBT_200A 103 | ||
233 | #define SAA7134_BOARD_HAUPPAUGE_HVR1110 104 | ||
234 | #define SAA7134_BOARD_CINERGY_HT_PCMCIA 105 | ||
230 | 235 | ||
231 | #define SAA7134_MAXBOARDS 8 | 236 | #define SAA7134_MAXBOARDS 8 |
232 | #define SAA7134_INPUT_MAX 8 | 237 | #define SAA7134_INPUT_MAX 8 |
@@ -446,6 +451,9 @@ struct saa7134_dev { | |||
446 | struct v4l2_prio_state prio; | 451 | struct v4l2_prio_state prio; |
447 | #endif | 452 | #endif |
448 | 453 | ||
454 | /* insmod option/autodetected */ | ||
455 | int autodetected; | ||
456 | |||
449 | /* various device info */ | 457 | /* various device info */ |
450 | unsigned int resources; | 458 | unsigned int resources; |
451 | struct video_device *video_dev; | 459 | struct video_device *video_dev; |
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index 6d1ef1e2e8ef..a1ec3aca3f91 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c | |||
@@ -687,7 +687,7 @@ static int stv680_start_stream (struct usb_stv *stv680) | |||
687 | stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); | 687 | stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); |
688 | if (stv680->sbuf[i].data == NULL) { | 688 | if (stv680->sbuf[i].data == NULL) { |
689 | PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i); | 689 | PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i); |
690 | return -1; | 690 | goto nomem_err; |
691 | } | 691 | } |
692 | } | 692 | } |
693 | 693 | ||
@@ -698,7 +698,7 @@ static int stv680_start_stream (struct usb_stv *stv680) | |||
698 | stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); | 698 | stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); |
699 | if (stv680->scratch[i].data == NULL) { | 699 | if (stv680->scratch[i].data == NULL) { |
700 | PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i); | 700 | PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i); |
701 | return -1; | 701 | goto nomem_err; |
702 | } | 702 | } |
703 | stv680->scratch[i].state = BUFFER_UNUSED; | 703 | stv680->scratch[i].state = BUFFER_UNUSED; |
704 | } | 704 | } |
@@ -706,7 +706,7 @@ static int stv680_start_stream (struct usb_stv *stv680) | |||
706 | for (i = 0; i < STV680_NUMSBUF; i++) { | 706 | for (i = 0; i < STV680_NUMSBUF; i++) { |
707 | urb = usb_alloc_urb (0, GFP_KERNEL); | 707 | urb = usb_alloc_urb (0, GFP_KERNEL); |
708 | if (!urb) | 708 | if (!urb) |
709 | return -ENOMEM; | 709 | goto nomem_err; |
710 | 710 | ||
711 | /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */ | 711 | /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */ |
712 | usb_fill_bulk_urb (urb, stv680->udev, | 712 | usb_fill_bulk_urb (urb, stv680->udev, |
@@ -721,6 +721,21 @@ static int stv680_start_stream (struct usb_stv *stv680) | |||
721 | 721 | ||
722 | stv680->framecount = 0; | 722 | stv680->framecount = 0; |
723 | return 0; | 723 | return 0; |
724 | |||
725 | nomem_err: | ||
726 | for (i = 0; i < STV680_NUMSCRATCH; i++) { | ||
727 | kfree(stv680->scratch[i].data); | ||
728 | stv680->scratch[i].data = NULL; | ||
729 | } | ||
730 | for (i = 0; i < STV680_NUMSBUF; i++) { | ||
731 | usb_kill_urb(stv680->urb[i]); | ||
732 | usb_free_urb(stv680->urb[i]); | ||
733 | stv680->urb[i] = NULL; | ||
734 | kfree(stv680->sbuf[i].data); | ||
735 | stv680->sbuf[i].data = NULL; | ||
736 | } | ||
737 | return -ENOMEM; | ||
738 | |||
724 | } | 739 | } |
725 | 740 | ||
726 | static int stv680_stop_stream (struct usb_stv *stv680) | 741 | static int stv680_stop_stream (struct usb_stv *stv680) |
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 87ffb0e84a7a..fde576f1101c 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c | |||
@@ -482,6 +482,12 @@ static int tda9887_set_config(struct tuner *t, char *buf) | |||
482 | buf[1] &= ~cQSS; | 482 | buf[1] &= ~cQSS; |
483 | if (t->tda9887_config & TDA9887_GATING_18) | 483 | if (t->tda9887_config & TDA9887_GATING_18) |
484 | buf[3] &= ~cGating_36; | 484 | buf[3] &= ~cGating_36; |
485 | |||
486 | if (t->tda9887_config & TDA9887_GAIN_NORMAL) { | ||
487 | radio_stereo.e &= ~cTunerGainLow; | ||
488 | radio_mono.e &= ~cTunerGainLow; | ||
489 | } | ||
490 | |||
485 | return 0; | 491 | return 0; |
486 | } | 492 | } |
487 | 493 | ||
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 40590bae5ff7..705daaa2a4ff 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -443,6 +443,10 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
443 | printk("%02x ",buffer[i]); | 443 | printk("%02x ",buffer[i]); |
444 | printk("\n"); | 444 | printk("\n"); |
445 | } | 445 | } |
446 | /* HACK: This test were added to avoid tuner to probe tda9840 and tea6415c on the MXB card */ | ||
447 | if (adap->id == I2C_HW_SAA7146 && addr < 0x4a) | ||
448 | return -ENODEV; | ||
449 | |||
446 | /* autodetection code based on the i2c addr */ | 450 | /* autodetection code based on the i2c addr */ |
447 | if (!no_autodetect) { | 451 | if (!no_autodetect) { |
448 | switch (addr) { | 452 | switch (addr) { |
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 63db4e97ae6c..1b9b0742f753 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c | |||
@@ -108,6 +108,7 @@ static int tuner_stereo(struct i2c_client *c) | |||
108 | case TUNER_PHILIPS_FM1216ME_MK3: | 108 | case TUNER_PHILIPS_FM1216ME_MK3: |
109 | case TUNER_PHILIPS_FM1236_MK3: | 109 | case TUNER_PHILIPS_FM1236_MK3: |
110 | case TUNER_PHILIPS_FM1256_IH3: | 110 | case TUNER_PHILIPS_FM1256_IH3: |
111 | case TUNER_LG_NTSC_TAPE: | ||
111 | stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); | 112 | stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); |
112 | break; | 113 | break; |
113 | default: | 114 | default: |
@@ -421,6 +422,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) | |||
421 | case TUNER_PHILIPS_FM1216ME_MK3: | 422 | case TUNER_PHILIPS_FM1216ME_MK3: |
422 | case TUNER_PHILIPS_FM1236_MK3: | 423 | case TUNER_PHILIPS_FM1236_MK3: |
423 | case TUNER_PHILIPS_FMD1216ME_MK3: | 424 | case TUNER_PHILIPS_FMD1216ME_MK3: |
425 | case TUNER_LG_NTSC_TAPE: | ||
424 | buffer[3] = 0x19; | 426 | buffer[3] = 0x19; |
425 | break; | 427 | break; |
426 | case TUNER_TNF_5335MF: | 428 | case TUNER_TNF_5335MF: |
@@ -465,6 +467,8 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) | |||
465 | config |= TDA9887_INTERCARRIER; | 467 | config |= TDA9887_INTERCARRIER; |
466 | /* if (params->port1_set_for_fm_mono) | 468 | /* if (params->port1_set_for_fm_mono) |
467 | config &= ~TDA9887_PORT1_ACTIVE;*/ | 469 | config &= ~TDA9887_PORT1_ACTIVE;*/ |
470 | if (params->fm_gain_normal) | ||
471 | config |= TDA9887_GAIN_NORMAL; | ||
468 | i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config); | 472 | i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config); |
469 | } | 473 | } |
470 | if (4 != (rc = i2c_master_send(c,buffer,4))) | 474 | if (4 != (rc = i2c_master_send(c,buffer,4))) |
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 781682373b61..74c3e6f96f1a 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c | |||
@@ -651,6 +651,7 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = { | |||
651 | .has_tda9887 = 1, | 651 | .has_tda9887 = 1, |
652 | .port1_invert_for_secam_lc = 1, | 652 | .port1_invert_for_secam_lc = 1, |
653 | .default_pll_gating_18 = 1, | 653 | .default_pll_gating_18 = 1, |
654 | .fm_gain_normal=1, | ||
654 | }, | 655 | }, |
655 | }; | 656 | }; |
656 | 657 | ||
@@ -672,16 +673,6 @@ static struct tuner_params tuner_panasonic_vp27_params[] = { | |||
672 | }, | 673 | }, |
673 | }; | 674 | }; |
674 | 675 | ||
675 | /* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */ | ||
676 | |||
677 | static struct tuner_params tuner_lg_ntsc_tape_params[] = { | ||
678 | { | ||
679 | .type = TUNER_PARAM_TYPE_NTSC, | ||
680 | .ranges = tuner_fm1236_mk3_ntsc_ranges, | ||
681 | .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), | ||
682 | }, | ||
683 | }; | ||
684 | |||
685 | /* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ | 676 | /* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ |
686 | 677 | ||
687 | static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { | 678 | static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { |
@@ -1331,8 +1322,8 @@ struct tunertype tuners[] = { | |||
1331 | }, | 1322 | }, |
1332 | [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ | 1323 | [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ |
1333 | .name = "LG NTSC (TAPE series)", | 1324 | .name = "LG NTSC (TAPE series)", |
1334 | .params = tuner_lg_ntsc_tape_params, | 1325 | .params = tuner_fm1236_mk3_params, |
1335 | .count = ARRAY_SIZE(tuner_lg_ntsc_tape_params), | 1326 | .count = ARRAY_SIZE(tuner_fm1236_mk3_params), |
1336 | }, | 1327 | }, |
1337 | [TUNER_TNF_8831BGFF] = { /* Philips PAL */ | 1328 | [TUNER_TNF_8831BGFF] = { /* Philips PAL */ |
1338 | .name = "Tenna TNF 8831 BGFF)", | 1329 | .name = "Tenna TNF 8831 BGFF)", |
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 6b9ef731b83a..2624e3f7dd29 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
@@ -430,7 +430,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, | |||
430 | tvee->has_radio = eeprom_data[i+len-1]; | 430 | tvee->has_radio = eeprom_data[i+len-1]; |
431 | /* old style tag, don't know how to detect | 431 | /* old style tag, don't know how to detect |
432 | IR presence, mark as unknown. */ | 432 | IR presence, mark as unknown. */ |
433 | tvee->has_ir = 2; | 433 | tvee->has_ir = -1; |
434 | tvee->model = | 434 | tvee->model = |
435 | eeprom_data[i+8] + | 435 | eeprom_data[i+8] + |
436 | (eeprom_data[i+9] << 8); | 436 | (eeprom_data[i+9] << 8); |
@@ -653,13 +653,14 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, | |||
653 | STRM(decoderIC, tvee->decoder_processor), | 653 | STRM(decoderIC, tvee->decoder_processor), |
654 | tvee->decoder_processor); | 654 | tvee->decoder_processor); |
655 | } | 655 | } |
656 | if (tvee->has_ir == 2) | 656 | if (tvee->has_ir == -1) |
657 | tveeprom_info("has %sradio\n", | 657 | tveeprom_info("has %sradio\n", |
658 | tvee->has_radio ? "" : "no "); | 658 | tvee->has_radio ? "" : "no "); |
659 | else | 659 | else |
660 | tveeprom_info("has %sradio, has %sIR remote\n", | 660 | tveeprom_info("has %sradio, has %sIR receiver, has %sIR transmitter\n", |
661 | tvee->has_radio ? "" : "no ", | 661 | tvee->has_radio ? "" : "no ", |
662 | tvee->has_ir ? "" : "no "); | 662 | (tvee->has_ir & 1) ? "" : "no ", |
663 | (tvee->has_ir & 2) ? "" : "no "); | ||
663 | } | 664 | } |
664 | EXPORT_SYMBOL(tveeprom_hauppauge_analog); | 665 | EXPORT_SYMBOL(tveeprom_hauppauge_analog); |
665 | 666 | ||
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index bbf2beeeb449..ec0ff2247f06 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c | |||
@@ -86,6 +86,7 @@ MODULE_DEVICE_TABLE(usb, qcm_table); | |||
86 | static void qcm_register_input(struct qcm *cam, struct usb_device *dev) | 86 | static void qcm_register_input(struct qcm *cam, struct usb_device *dev) |
87 | { | 87 | { |
88 | struct input_dev *input_dev; | 88 | struct input_dev *input_dev; |
89 | int error; | ||
89 | 90 | ||
90 | usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); | 91 | usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); |
91 | strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); | 92 | strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); |
@@ -106,7 +107,13 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev) | |||
106 | 107 | ||
107 | input_dev->private = cam; | 108 | input_dev->private = cam; |
108 | 109 | ||
109 | input_register_device(cam->input); | 110 | error = input_register_device(cam->input); |
111 | if (error) { | ||
112 | warn("Failed to register camera's input device, err: %d\n", | ||
113 | error); | ||
114 | input_free_device(cam->input); | ||
115 | cam->input = NULL; | ||
116 | } | ||
110 | } | 117 | } |
111 | 118 | ||
112 | static void qcm_unregister_input(struct qcm *cam) | 119 | static void qcm_unregister_input(struct qcm *cam) |
diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig new file mode 100644 index 000000000000..fc24ef05b3f3 --- /dev/null +++ b/drivers/media/video/usbvision/Kconfig | |||
@@ -0,0 +1,12 @@ | |||
1 | config VIDEO_USBVISION | ||
2 | tristate "USB video devices based on Nogatech NT1003/1004/1005" | ||
3 | depends on I2C && VIDEO_V4L2 | ||
4 | select VIDEO_TUNER | ||
5 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO | ||
6 | ---help--- | ||
7 | There are more than 50 different USB video devices based on | ||
8 | NT1003/1004/1005 USB Bridges. This driver enables using those | ||
9 | devices. | ||
10 | |||
11 | To compile this driver as a module, choose M here: the | ||
12 | module will be called usbvision. | ||
diff --git a/drivers/media/video/usbvision/Makefile b/drivers/media/video/usbvision/Makefile new file mode 100644 index 000000000000..9ac92a80c645 --- /dev/null +++ b/drivers/media/video/usbvision/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-cards.o | ||
2 | |||
3 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o | ||
4 | |||
5 | EXTRA_CFLAGS += -Idrivers/media/video | ||
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c new file mode 100644 index 000000000000..134eb9865df6 --- /dev/null +++ b/drivers/media/video/usbvision/usbvision-cards.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * USBVISION.H | ||
3 | * usbvision header file | ||
4 | * | ||
5 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
6 | * | ||
7 | * This module is part of usbvision driver project. | ||
8 | * Updates to driver completed by Dwaine P. Garden | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | |||
26 | #include <linux/list.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <media/v4l2-dev.h> | ||
29 | #include <media/tuner.h> | ||
30 | #include "usbvision.h" | ||
31 | |||
32 | /* Supported Devices: A table for usbvision.c*/ | ||
33 | struct usbvision_device_data_st usbvision_device_data[] = { | ||
34 | {0xFFF0, 0xFFF0, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Custom Dummy USBVision Device"}, | ||
35 | {0x0A6F, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "Xanboo"}, | ||
36 | {0x050D, 0x0208, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Belkin USBView II"}, | ||
37 | {0x0571, 0x0002, 0, CODEC_SAA7111, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, -1, -1, 7, "echoFX InterView Lite"}, | ||
38 | {0x0573, 0x0003, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "USBGear USBG-V1 resp. HAMA USB"}, | ||
39 | {0x0573, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "D-Link V100"}, | ||
40 | {0x0573, 0x2000, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "X10 USB Camera"}, | ||
41 | {0x0573, 0x2d00, -1, CODEC_SAA7111, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, -1, 3, 7, "Osprey 50"}, | ||
42 | {0x0573, 0x2d01, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Hauppauge USB-Live Model 600"}, | ||
43 | {0x0573, 0x2101, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 2, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Zoran Co. PMD (Nogatech) AV-grabber Manhattan"}, | ||
44 | {0x0573, 0x4100, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Nogatech USB-TV (NTSC) FM"}, | ||
45 | {0x0573, 0x4110, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "PNY USB-TV (NTSC) FM"}, | ||
46 | {0x0573, 0x4450, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "PixelView PlayTv-USB PRO (PAL) FM"}, | ||
47 | {0x0573, 0x4550, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "ZTV ZT-721 2.4GHz USB A/V Receiver"}, | ||
48 | {0x0573, 0x4d00, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Hauppauge WinTv-USB USA"}, | ||
49 | {0x0573, 0x4d01, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"}, | ||
50 | {0x0573, 0x4d02, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC)"}, | ||
51 | {0x0573, 0x4d03, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (SECAM) "}, | ||
52 | {0x0573, 0x4d10, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC) FM"}, | ||
53 | {0x0573, 0x4d11, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"}, | ||
54 | {0x0573, 0x4d12, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"}, | ||
55 | {0x0573, 0x4d2a, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B285"}, | ||
56 | {0x0573, 0x4d2b, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B282"}, | ||
57 | {0x0573, 0x4d2c, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (PAL/SECAM) 40209 Rev E1A5"}, | ||
58 | {0x0573, 0x4d20, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226"}, | ||
59 | {0x0573, 0x4d21, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL)"}, | ||
60 | {0x0573, 0x4d22, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL) MODEL 566"}, | ||
61 | {0x0573, 0x4d23, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) 4D23"}, | ||
62 | {0x0573, 0x4d25, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B234"}, | ||
63 | {0x0573, 0x4d26, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B243"}, | ||
64 | {0x0573, 0x4d27, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40204 Rev B281"}, | ||
65 | {0x0573, 0x4d28, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40204 Rev B283"}, | ||
66 | {0x0573, 0x4d29, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40205 Rev B298"}, | ||
67 | {0x0573, 0x4d30, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB FM Model 40211 Rev B123"}, | ||
68 | {0x0573, 0x4d31, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 568"}, | ||
69 | {0x0573, 0x4d32, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 573"}, | ||
70 | {0x0573, 0x4d35, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 40219 Rev B252"}, | ||
71 | {0x0573, 0x4d37, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTV USB device Model 40219 Rev E189"}, | ||
72 | {0x0768, 0x0006, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 5, 5, -1, "Camtel Technology USB TV Genie Pro FM Model TVB330"}, | ||
73 | {0x07d0, 0x0001, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Digital Video Creator I"}, | ||
74 | {0x07d0, 0x0002, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 82, 20, 7, "Global Village GV-007 (NTSC)"}, | ||
75 | {0x07d0, 0x0003, 0, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)"}, | ||
76 | {0x07d0, 0x0004, 0, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-80 Rev 1 (PAL)"}, | ||
77 | {0x07d0, 0x0005, 0, CODEC_SAA7113, 2, V4L2_STD_SECAM, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)"}, | ||
78 | {0x2304, 0x010d, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 0, 1, TUNER_TEMIC_4066FY5_PAL_I, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (PAL)"}, | ||
79 | {0x2304, 0x0109, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (SECAM)"}, | ||
80 | {0x2304, 0x0110, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1,128, 23, -1, "Pinnacle Studio PCTV USB (PAL) FM"}, | ||
81 | {0x2304, 0x0111, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Miro PCTV USB"}, | ||
82 | {0x2304, 0x0112, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (NTSC) FM"}, | ||
83 | {0x2304, 0x0210, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"}, | ||
84 | {0x2304, 0x0212, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_TEMIC_4039FR5_NTSC, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (NTSC) FM"}, | ||
85 | {0x2304, 0x0214, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"}, | ||
86 | {0x2304, 0x0300, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (NTSC)"}, | ||
87 | {0x2304, 0x0301, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (PAL)"}, | ||
88 | {0x2304, 0x0419, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle PCTV Bungee USB (PAL) FM"}, | ||
89 | {0x2400, 0x4200, -1, CODEC_SAA7111, 3, VIDEO_MODE_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"}, | ||
90 | {} /* Terminating entry */ | ||
91 | }; | ||
92 | |||
93 | /* Supported Devices */ | ||
94 | |||
95 | struct usb_device_id usbvision_table [] = { | ||
96 | { USB_DEVICE(0xFFF0, 0xFFF0) }, /* Custom Dummy USBVision Device */ | ||
97 | { USB_DEVICE(0x0A6F, 0x0400) }, /* Xanboo */ | ||
98 | { USB_DEVICE(0x050d, 0x0208) }, /* Belkin USBView II */ | ||
99 | { USB_DEVICE(0x0571, 0x0002) }, /* echoFX InterView Lite */ | ||
100 | { USB_DEVICE(0x0573, 0x0003) }, /* USBGear USBG-V1 */ | ||
101 | { USB_DEVICE(0x0573, 0x0400) }, /* D-Link V100 */ | ||
102 | { USB_DEVICE(0x0573, 0x2000) }, /* X10 USB Camera */ | ||
103 | { USB_DEVICE(0x0573, 0x2d00) }, /* Osprey 50 */ | ||
104 | { USB_DEVICE(0x0573, 0x2d01) }, /* Hauppauge USB-Live Model 600 */ | ||
105 | { USB_DEVICE(0x0573, 0x2101) }, /* Zoran Co. PMD (Nogatech) AV-grabber Manhattan */ | ||
106 | { USB_DEVICE(0x0573, 0x4100) }, /* Nogatech USB-TV FM (NTSC) */ | ||
107 | { USB_DEVICE(0x0573, 0x4110) }, /* PNY USB-TV (NTSC) FM */ | ||
108 | { USB_DEVICE(0x0573, 0x4450) }, /* PixelView PlayTv-USB PRO (PAL) FM */ | ||
109 | { USB_DEVICE(0x0573, 0x4550) }, /* ZTV ZT-721 2.4GHz USB A/V Receiver */ | ||
110 | { USB_DEVICE(0x0573, 0x4d00) }, /* Hauppauge WinTv-USB USA */ | ||
111 | { USB_DEVICE(0x0573, 0x4d01) }, /* Hauppauge WinTv-USB */ | ||
112 | { USB_DEVICE(0x0573, 0x4d02) }, /* Hauppauge WinTv-USB UK */ | ||
113 | { USB_DEVICE(0x0573, 0x4d03) }, /* Hauppauge WinTv-USB France */ | ||
114 | { USB_DEVICE(0x0573, 0x4d10) }, /* Hauppauge WinTv-USB with FM USA radio */ | ||
115 | { USB_DEVICE(0x0573, 0x4d11) }, /* Hauppauge WinTv-USB (PAL) with FM radio */ | ||
116 | { USB_DEVICE(0x0573, 0x4d12) }, /* Hauppauge WinTv-USB UK with FM Radio */ | ||
117 | { USB_DEVICE(0x0573, 0x4d2a) }, /* Hauppague WinTv USB Model 602 40201 Rev B285 */ | ||
118 | { USB_DEVICE(0x0573, 0x4d2b) }, /* Hauppague WinTv USB Model 602 40201 Rev B282 */ | ||
119 | { USB_DEVICE(0x0573, 0x4d2c) }, /* Hauppague WinTv USB Model 40209 Rev. E1A5 PAL*/ | ||
120 | { USB_DEVICE(0x0573, 0x4d20) }, /* Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226 */ | ||
121 | { USB_DEVICE(0x0573, 0x4d21) }, /* Hauppauge WinTv-USB II (PAL) with FM radio*/ | ||
122 | { USB_DEVICE(0x0573, 0x4d22) }, /* Hauppauge WinTv-USB II (PAL) Model 566 */ | ||
123 | { USB_DEVICE(0x0573, 0x4d23) }, /* Hauppauge WinTv-USB France 4D23*/ | ||
124 | { USB_DEVICE(0x0573, 0x4d25) }, /* Hauppauge WinTv-USB Model 40209 rev B234 */ | ||
125 | { USB_DEVICE(0x0573, 0x4d26) }, /* Hauppauge WinTv-USB Model 40209 Rev B243 */ | ||
126 | { USB_DEVICE(0x0573, 0x4d27) }, /* Hauppauge WinTv-USB Model 40204 Rev B281 */ | ||
127 | { USB_DEVICE(0x0573, 0x4d28) }, /* Hauppauge WinTv-USB Model 40204 Rev B283 */ | ||
128 | { USB_DEVICE(0x0573, 0x4d29) }, /* Hauppauge WinTv-USB Model 40205 Rev B298 */ | ||
129 | { USB_DEVICE(0x0573, 0x4d30) }, /* Hauppauge WinTv-USB FM Model 40211 Rev B123 */ | ||
130 | { USB_DEVICE(0x0573, 0x4d31) }, /* Hauppauge WinTv-USB III (PAL) with FM radio Model 568 */ | ||
131 | { USB_DEVICE(0x0573, 0x4d32) }, /* Hauppauge WinTv-USB III (PAL) FM Model 573 */ | ||
132 | { USB_DEVICE(0x0573, 0x4d35) }, /* Hauppauge WinTv-USB III (SECAM) FM Model 40219 Rev B252 */ | ||
133 | { USB_DEVICE(0x0573, 0x4d37) }, /* Hauppauge WinTv-USB Model 40219 Rev E189 */ | ||
134 | { USB_DEVICE(0x0768, 0x0006) }, /* Camtel Technology USB TV Genie Pro FM Model TVB330 */ | ||
135 | { USB_DEVICE(0x07d0, 0x0001) }, /* Digital Video Creator I */ | ||
136 | { USB_DEVICE(0x07d0, 0x0002) }, /* Global Village GV-007 (NTSC) */ | ||
137 | { USB_DEVICE(0x07d0, 0x0003) }, /* Dazzle Fusion Model DVC-50 Rev 1 (NTSC) */ | ||
138 | { USB_DEVICE(0x07d0, 0x0004) }, /* Dazzle Fusion Model DVC-80 Rev 1 (PAL) */ | ||
139 | { USB_DEVICE(0x07d0, 0x0005) }, /* Dazzle Fusion Model DVC-90 Rev 1 (SECAM) */ | ||
140 | { USB_DEVICE(0x2304, 0x010d) }, /* Pinnacle Studio PCTV USB (PAL) */ | ||
141 | { USB_DEVICE(0x2304, 0x0109) }, /* Pinnacle Studio PCTV USB (SECAM) */ | ||
142 | { USB_DEVICE(0x2304, 0x0110) }, /* Pinnacle Studio PCTV USB (PAL) */ | ||
143 | { USB_DEVICE(0x2304, 0x0111) }, /* Miro PCTV USB */ | ||
144 | { USB_DEVICE(0x2304, 0x0112) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */ | ||
145 | { USB_DEVICE(0x2304, 0x0210) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */ | ||
146 | { USB_DEVICE(0x2304, 0x0212) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */ | ||
147 | { USB_DEVICE(0x2304, 0x0214) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */ | ||
148 | { USB_DEVICE(0x2304, 0x0300) }, /* Pinnacle Studio Linx Video input cable (NTSC) */ | ||
149 | { USB_DEVICE(0x2304, 0x0301) }, /* Pinnacle Studio Linx Video input cable (PAL) */ | ||
150 | { USB_DEVICE(0x2304, 0x0419) }, /* Pinnacle PCTV Bungee USB (PAL) FM */ | ||
151 | |||
152 | { USB_DEVICE(0x2400, 0x4200) }, /* Hauppauge WinTv-USB2 Model 42012 */ | ||
153 | |||
154 | { } /* Terminating entry */ | ||
155 | }; | ||
156 | |||
157 | MODULE_DEVICE_TABLE (usb, usbvision_table); | ||
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c new file mode 100644 index 000000000000..797b97baf9ed --- /dev/null +++ b/drivers/media/video/usbvision/usbvision-core.c | |||
@@ -0,0 +1,2554 @@ | |||
1 | /* | ||
2 | * usbvision-core.c - driver for NT100x USB video capture devices | ||
3 | * | ||
4 | * | ||
5 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
6 | * Dwaine Garden <dwainegarden@rogers.com> | ||
7 | * | ||
8 | * This module is part of usbvision driver project. | ||
9 | * Updates to driver completed by Dwaine P. Garden | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <linux/list.h> | ||
29 | #include <linux/timer.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/mm.h> | ||
32 | #include <linux/utsname.h> | ||
33 | #include <linux/highmem.h> | ||
34 | #include <linux/smp_lock.h> | ||
35 | #include <linux/videodev.h> | ||
36 | #include <linux/vmalloc.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/spinlock.h> | ||
40 | #include <asm/io.h> | ||
41 | #include <linux/videodev2.h> | ||
42 | #include <linux/video_decoder.h> | ||
43 | #include <linux/i2c.h> | ||
44 | |||
45 | #include <media/saa7115.h> | ||
46 | #include <media/v4l2-common.h> | ||
47 | #include <media/tuner.h> | ||
48 | #include <media/audiochip.h> | ||
49 | |||
50 | #include <linux/moduleparam.h> | ||
51 | #include <linux/workqueue.h> | ||
52 | |||
53 | #ifdef CONFIG_KMOD | ||
54 | #include <linux/kmod.h> | ||
55 | #endif | ||
56 | |||
57 | #include "usbvision.h" | ||
58 | |||
59 | static unsigned int core_debug = 0; | ||
60 | module_param(core_debug,int,0644); | ||
61 | MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); | ||
62 | |||
63 | static unsigned int force_testpattern = 0; | ||
64 | module_param(force_testpattern,int,0644); | ||
65 | MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]"); | ||
66 | |||
67 | static int adjustCompression = 1; // Set the compression to be adaptive | ||
68 | module_param(adjustCompression, int, 0444); | ||
69 | MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device. Default: 1 (On)"); | ||
70 | |||
71 | static int SwitchSVideoInput = 0; // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. | ||
72 | module_param(SwitchSVideoInput, int, 0444); | ||
73 | MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); | ||
74 | |||
75 | #define ENABLE_HEXDUMP 0 /* Enable if you need it */ | ||
76 | |||
77 | |||
78 | #ifdef USBVISION_DEBUG | ||
79 | #define PDEBUG(level, fmt, args...) \ | ||
80 | if (core_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) | ||
81 | #else | ||
82 | #define PDEBUG(level, fmt, args...) do {} while(0) | ||
83 | #endif | ||
84 | |||
85 | #define DBG_HEADER 1<<0 | ||
86 | #define DBG_IRQ 1<<1 | ||
87 | #define DBG_ISOC 1<<2 | ||
88 | #define DBG_PARSE 1<<3 | ||
89 | #define DBG_SCRATCH 1<<4 | ||
90 | #define DBG_FUNC 1<<5 | ||
91 | |||
92 | static const int max_imgwidth = MAX_FRAME_WIDTH; | ||
93 | static const int max_imgheight = MAX_FRAME_HEIGHT; | ||
94 | static const int min_imgwidth = MIN_FRAME_WIDTH; | ||
95 | static const int min_imgheight = MIN_FRAME_HEIGHT; | ||
96 | |||
97 | /* The value of 'scratch_buf_size' affects quality of the picture | ||
98 | * in many ways. Shorter buffers may cause loss of data when client | ||
99 | * is too slow. Larger buffers are memory-consuming and take longer | ||
100 | * to work with. This setting can be adjusted, but the default value | ||
101 | * should be OK for most desktop users. | ||
102 | */ | ||
103 | #define DEFAULT_SCRATCH_BUF_SIZE (0x20000) // 128kB memory scratch buffer | ||
104 | static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE; | ||
105 | |||
106 | // Function prototypes | ||
107 | static int usbvision_request_intra (struct usb_usbvision *usbvision); | ||
108 | static int usbvision_unrequest_intra (struct usb_usbvision *usbvision); | ||
109 | static int usbvision_adjust_compression (struct usb_usbvision *usbvision); | ||
110 | static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision); | ||
111 | |||
112 | /*******************************/ | ||
113 | /* Memory management functions */ | ||
114 | /*******************************/ | ||
115 | |||
116 | /* | ||
117 | * Here we want the physical address of the memory. | ||
118 | * This is used when initializing the contents of the area. | ||
119 | */ | ||
120 | |||
121 | void *usbvision_rvmalloc(unsigned long size) | ||
122 | { | ||
123 | void *mem; | ||
124 | unsigned long adr; | ||
125 | |||
126 | size = PAGE_ALIGN(size); | ||
127 | mem = vmalloc_32(size); | ||
128 | if (!mem) | ||
129 | return NULL; | ||
130 | |||
131 | memset(mem, 0, size); /* Clear the ram out, no junk to the user */ | ||
132 | adr = (unsigned long) mem; | ||
133 | while (size > 0) { | ||
134 | SetPageReserved(vmalloc_to_page((void *)adr)); | ||
135 | adr += PAGE_SIZE; | ||
136 | size -= PAGE_SIZE; | ||
137 | } | ||
138 | |||
139 | return mem; | ||
140 | } | ||
141 | |||
142 | void usbvision_rvfree(void *mem, unsigned long size) | ||
143 | { | ||
144 | unsigned long adr; | ||
145 | |||
146 | if (!mem) | ||
147 | return; | ||
148 | |||
149 | size = PAGE_ALIGN(size); | ||
150 | |||
151 | adr = (unsigned long) mem; | ||
152 | while ((long) size > 0) { | ||
153 | ClearPageReserved(vmalloc_to_page((void *)adr)); | ||
154 | adr += PAGE_SIZE; | ||
155 | size -= PAGE_SIZE; | ||
156 | } | ||
157 | |||
158 | vfree(mem); | ||
159 | } | ||
160 | |||
161 | |||
162 | |||
163 | #if ENABLE_HEXDUMP | ||
164 | static void usbvision_hexdump(const unsigned char *data, int len) | ||
165 | { | ||
166 | char tmp[80]; | ||
167 | int i, k; | ||
168 | |||
169 | for (i = k = 0; len > 0; i++, len--) { | ||
170 | if (i > 0 && (i % 16 == 0)) { | ||
171 | printk("%s\n", tmp); | ||
172 | k = 0; | ||
173 | } | ||
174 | k += sprintf(&tmp[k], "%02x ", data[i]); | ||
175 | } | ||
176 | if (k > 0) | ||
177 | printk("%s\n", tmp); | ||
178 | } | ||
179 | #endif | ||
180 | |||
181 | /******************************** | ||
182 | * scratch ring buffer handling | ||
183 | ********************************/ | ||
184 | int scratch_len(struct usb_usbvision *usbvision) /*This returns the amount of data actually in the buffer */ | ||
185 | { | ||
186 | int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr; | ||
187 | if (len < 0) { | ||
188 | len += scratch_buf_size; | ||
189 | } | ||
190 | PDEBUG(DBG_SCRATCH, "scratch_len() = %d\n", len); | ||
191 | |||
192 | return len; | ||
193 | } | ||
194 | |||
195 | |||
196 | /* This returns the free space left in the buffer */ | ||
197 | int scratch_free(struct usb_usbvision *usbvision) | ||
198 | { | ||
199 | int free = usbvision->scratch_read_ptr - usbvision->scratch_write_ptr; | ||
200 | if (free <= 0) { | ||
201 | free += scratch_buf_size; | ||
202 | } | ||
203 | if (free) { | ||
204 | free -= 1; /* at least one byte in the buffer must */ | ||
205 | /* left blank, otherwise there is no chance to differ between full and empty */ | ||
206 | } | ||
207 | PDEBUG(DBG_SCRATCH, "return %d\n", free); | ||
208 | |||
209 | return free; | ||
210 | } | ||
211 | |||
212 | |||
213 | /* This puts data into the buffer */ | ||
214 | int scratch_put(struct usb_usbvision *usbvision, unsigned char *data, int len) | ||
215 | { | ||
216 | int len_part; | ||
217 | |||
218 | if (usbvision->scratch_write_ptr + len < scratch_buf_size) { | ||
219 | memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len); | ||
220 | usbvision->scratch_write_ptr += len; | ||
221 | } | ||
222 | else { | ||
223 | len_part = scratch_buf_size - usbvision->scratch_write_ptr; | ||
224 | memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len_part); | ||
225 | if (len == len_part) { | ||
226 | usbvision->scratch_write_ptr = 0; /* just set write_ptr to zero */ | ||
227 | } | ||
228 | else { | ||
229 | memcpy(usbvision->scratch, data + len_part, len - len_part); | ||
230 | usbvision->scratch_write_ptr = len - len_part; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | PDEBUG(DBG_SCRATCH, "len=%d, new write_ptr=%d\n", len, usbvision->scratch_write_ptr); | ||
235 | |||
236 | return len; | ||
237 | } | ||
238 | |||
239 | /* This marks the write_ptr as position of new frame header */ | ||
240 | void scratch_mark_header(struct usb_usbvision *usbvision) | ||
241 | { | ||
242 | PDEBUG(DBG_SCRATCH, "header at write_ptr=%d\n", usbvision->scratch_headermarker_write_ptr); | ||
243 | |||
244 | usbvision->scratch_headermarker[usbvision->scratch_headermarker_write_ptr] = | ||
245 | usbvision->scratch_write_ptr; | ||
246 | usbvision->scratch_headermarker_write_ptr += 1; | ||
247 | usbvision->scratch_headermarker_write_ptr %= USBVISION_NUM_HEADERMARKER; | ||
248 | } | ||
249 | |||
250 | /* This gets data from the buffer at the given "ptr" position */ | ||
251 | int scratch_get_extra(struct usb_usbvision *usbvision, unsigned char *data, int *ptr, int len) | ||
252 | { | ||
253 | int len_part; | ||
254 | if (*ptr + len < scratch_buf_size) { | ||
255 | memcpy(data, usbvision->scratch + *ptr, len); | ||
256 | *ptr += len; | ||
257 | } | ||
258 | else { | ||
259 | len_part = scratch_buf_size - *ptr; | ||
260 | memcpy(data, usbvision->scratch + *ptr, len_part); | ||
261 | if (len == len_part) { | ||
262 | *ptr = 0; /* just set the y_ptr to zero */ | ||
263 | } | ||
264 | else { | ||
265 | memcpy(data + len_part, usbvision->scratch, len - len_part); | ||
266 | *ptr = len - len_part; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | PDEBUG(DBG_SCRATCH, "len=%d, new ptr=%d\n", len, *ptr); | ||
271 | |||
272 | return len; | ||
273 | } | ||
274 | |||
275 | |||
276 | /* This sets the scratch extra read pointer */ | ||
277 | void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr, int len) | ||
278 | { | ||
279 | *ptr = (usbvision->scratch_read_ptr + len)%scratch_buf_size; | ||
280 | |||
281 | PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr); | ||
282 | } | ||
283 | |||
284 | |||
285 | /*This increments the scratch extra read pointer */ | ||
286 | void scratch_inc_extra_ptr(int *ptr, int len) | ||
287 | { | ||
288 | *ptr = (*ptr + len) % scratch_buf_size; | ||
289 | |||
290 | PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr); | ||
291 | } | ||
292 | |||
293 | |||
294 | /* This gets data from the buffer */ | ||
295 | int scratch_get(struct usb_usbvision *usbvision, unsigned char *data, int len) | ||
296 | { | ||
297 | int len_part; | ||
298 | if (usbvision->scratch_read_ptr + len < scratch_buf_size) { | ||
299 | memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len); | ||
300 | usbvision->scratch_read_ptr += len; | ||
301 | } | ||
302 | else { | ||
303 | len_part = scratch_buf_size - usbvision->scratch_read_ptr; | ||
304 | memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len_part); | ||
305 | if (len == len_part) { | ||
306 | usbvision->scratch_read_ptr = 0; /* just set the read_ptr to zero */ | ||
307 | } | ||
308 | else { | ||
309 | memcpy(data + len_part, usbvision->scratch, len - len_part); | ||
310 | usbvision->scratch_read_ptr = len - len_part; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | PDEBUG(DBG_SCRATCH, "len=%d, new read_ptr=%d\n", len, usbvision->scratch_read_ptr); | ||
315 | |||
316 | return len; | ||
317 | } | ||
318 | |||
319 | |||
320 | /* This sets read pointer to next header and returns it */ | ||
321 | int scratch_get_header(struct usb_usbvision *usbvision,struct usbvision_frame_header *header) | ||
322 | { | ||
323 | int errCode = 0; | ||
324 | |||
325 | PDEBUG(DBG_SCRATCH, "from read_ptr=%d", usbvision->scratch_headermarker_read_ptr); | ||
326 | |||
327 | while (usbvision->scratch_headermarker_write_ptr - | ||
328 | usbvision->scratch_headermarker_read_ptr != 0) { | ||
329 | usbvision->scratch_read_ptr = | ||
330 | usbvision->scratch_headermarker[usbvision->scratch_headermarker_read_ptr]; | ||
331 | usbvision->scratch_headermarker_read_ptr += 1; | ||
332 | usbvision->scratch_headermarker_read_ptr %= USBVISION_NUM_HEADERMARKER; | ||
333 | scratch_get(usbvision, (unsigned char *)header, USBVISION_HEADER_LENGTH); | ||
334 | if ((header->magic_1 == USBVISION_MAGIC_1) | ||
335 | && (header->magic_2 == USBVISION_MAGIC_2) | ||
336 | && (header->headerLength == USBVISION_HEADER_LENGTH)) { | ||
337 | errCode = USBVISION_HEADER_LENGTH; | ||
338 | header->frameWidth = header->frameWidthLo + (header->frameWidthHi << 8); | ||
339 | header->frameHeight = header->frameHeightLo + (header->frameHeightHi << 8); | ||
340 | break; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | return errCode; | ||
345 | } | ||
346 | |||
347 | |||
348 | /*This removes len bytes of old data from the buffer */ | ||
349 | void scratch_rm_old(struct usb_usbvision *usbvision, int len) | ||
350 | { | ||
351 | |||
352 | usbvision->scratch_read_ptr += len; | ||
353 | usbvision->scratch_read_ptr %= scratch_buf_size; | ||
354 | PDEBUG(DBG_SCRATCH, "read_ptr is now %d\n", usbvision->scratch_read_ptr); | ||
355 | } | ||
356 | |||
357 | |||
358 | /*This resets the buffer - kills all data in it too */ | ||
359 | void scratch_reset(struct usb_usbvision *usbvision) | ||
360 | { | ||
361 | PDEBUG(DBG_SCRATCH, "\n"); | ||
362 | |||
363 | usbvision->scratch_read_ptr = 0; | ||
364 | usbvision->scratch_write_ptr = 0; | ||
365 | usbvision->scratch_headermarker_read_ptr = 0; | ||
366 | usbvision->scratch_headermarker_write_ptr = 0; | ||
367 | usbvision->isocstate = IsocState_NoFrame; | ||
368 | } | ||
369 | |||
370 | int usbvision_scratch_alloc(struct usb_usbvision *usbvision) | ||
371 | { | ||
372 | usbvision->scratch = vmalloc(scratch_buf_size); | ||
373 | scratch_reset(usbvision); | ||
374 | if(usbvision->scratch == NULL) { | ||
375 | err("%s: unable to allocate %d bytes for scratch", | ||
376 | __FUNCTION__, scratch_buf_size); | ||
377 | return -ENOMEM; | ||
378 | } | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | void usbvision_scratch_free(struct usb_usbvision *usbvision) | ||
383 | { | ||
384 | if (usbvision->scratch != NULL) { | ||
385 | vfree(usbvision->scratch); | ||
386 | usbvision->scratch = NULL; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | /* | ||
391 | * usbvision_testpattern() | ||
392 | * | ||
393 | * Procedure forms a test pattern (yellow grid on blue background). | ||
394 | * | ||
395 | * Parameters: | ||
396 | * fullframe: if TRUE then entire frame is filled, otherwise the procedure | ||
397 | * continues from the current scanline. | ||
398 | * pmode 0: fill the frame with solid blue color (like on VCR or TV) | ||
399 | * 1: Draw a colored grid | ||
400 | * | ||
401 | */ | ||
402 | void usbvision_testpattern(struct usb_usbvision *usbvision, int fullframe, | ||
403 | int pmode) | ||
404 | { | ||
405 | static const char proc[] = "usbvision_testpattern"; | ||
406 | struct usbvision_frame *frame; | ||
407 | unsigned char *f; | ||
408 | int num_cell = 0; | ||
409 | int scan_length = 0; | ||
410 | static int num_pass = 0; | ||
411 | |||
412 | if (usbvision == NULL) { | ||
413 | printk(KERN_ERR "%s: usbvision == NULL\n", proc); | ||
414 | return; | ||
415 | } | ||
416 | if (usbvision->curFrame == NULL) { | ||
417 | printk(KERN_ERR "%s: usbvision->curFrame is NULL.\n", proc); | ||
418 | return; | ||
419 | } | ||
420 | |||
421 | /* Grab the current frame */ | ||
422 | frame = usbvision->curFrame; | ||
423 | |||
424 | /* Optionally start at the beginning */ | ||
425 | if (fullframe) { | ||
426 | frame->curline = 0; | ||
427 | frame->scanlength = 0; | ||
428 | } | ||
429 | |||
430 | /* Form every scan line */ | ||
431 | for (; frame->curline < frame->frmheight; frame->curline++) { | ||
432 | int i; | ||
433 | |||
434 | f = frame->data + (usbvision->curwidth * 3 * frame->curline); | ||
435 | for (i = 0; i < usbvision->curwidth; i++) { | ||
436 | unsigned char cb = 0x80; | ||
437 | unsigned char cg = 0; | ||
438 | unsigned char cr = 0; | ||
439 | |||
440 | if (pmode == 1) { | ||
441 | if (frame->curline % 32 == 0) | ||
442 | cb = 0, cg = cr = 0xFF; | ||
443 | else if (i % 32 == 0) { | ||
444 | if (frame->curline % 32 == 1) | ||
445 | num_cell++; | ||
446 | cb = 0, cg = cr = 0xFF; | ||
447 | } else { | ||
448 | cb = | ||
449 | ((num_cell * 7) + | ||
450 | num_pass) & 0xFF; | ||
451 | cg = | ||
452 | ((num_cell * 5) + | ||
453 | num_pass * 2) & 0xFF; | ||
454 | cr = | ||
455 | ((num_cell * 3) + | ||
456 | num_pass * 3) & 0xFF; | ||
457 | } | ||
458 | } else { | ||
459 | /* Just the blue screen */ | ||
460 | } | ||
461 | |||
462 | *f++ = cb; | ||
463 | *f++ = cg; | ||
464 | *f++ = cr; | ||
465 | scan_length += 3; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | frame->grabstate = FrameState_Done; | ||
470 | frame->scanlength += scan_length; | ||
471 | ++num_pass; | ||
472 | |||
473 | } | ||
474 | |||
475 | /* | ||
476 | * usbvision_decompress_alloc() | ||
477 | * | ||
478 | * allocates intermediate buffer for decompression | ||
479 | */ | ||
480 | int usbvision_decompress_alloc(struct usb_usbvision *usbvision) | ||
481 | { | ||
482 | int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2; | ||
483 | usbvision->IntraFrameBuffer = vmalloc(IFB_size); | ||
484 | if (usbvision->IntraFrameBuffer == NULL) { | ||
485 | err("%s: unable to allocate %d for compr. frame buffer", __FUNCTION__, IFB_size); | ||
486 | return -ENOMEM; | ||
487 | } | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | /* | ||
492 | * usbvision_decompress_free() | ||
493 | * | ||
494 | * frees intermediate buffer for decompression | ||
495 | */ | ||
496 | void usbvision_decompress_free(struct usb_usbvision *usbvision) | ||
497 | { | ||
498 | if (usbvision->IntraFrameBuffer != NULL) { | ||
499 | vfree(usbvision->IntraFrameBuffer); | ||
500 | usbvision->IntraFrameBuffer = NULL; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | /************************************************************ | ||
505 | * Here comes the data parsing stuff that is run as interrupt | ||
506 | ************************************************************/ | ||
507 | /* | ||
508 | * usbvision_find_header() | ||
509 | * | ||
510 | * Locate one of supported header markers in the scratch buffer. | ||
511 | */ | ||
512 | static enum ParseState usbvision_find_header(struct usb_usbvision *usbvision) | ||
513 | { | ||
514 | struct usbvision_frame *frame; | ||
515 | int foundHeader = 0; | ||
516 | |||
517 | frame = usbvision->curFrame; | ||
518 | |||
519 | while (scratch_get_header(usbvision, &frame->isocHeader) == USBVISION_HEADER_LENGTH) { | ||
520 | // found header in scratch | ||
521 | PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u", | ||
522 | frame->isocHeader.magic_2, | ||
523 | frame->isocHeader.magic_1, | ||
524 | frame->isocHeader.headerLength, | ||
525 | frame->isocHeader.frameNum, | ||
526 | frame->isocHeader.framePhase, | ||
527 | frame->isocHeader.frameLatency, | ||
528 | frame->isocHeader.dataFormat, | ||
529 | frame->isocHeader.formatParam, | ||
530 | frame->isocHeader.frameWidth, | ||
531 | frame->isocHeader.frameHeight); | ||
532 | |||
533 | if (usbvision->requestIntra) { | ||
534 | if (frame->isocHeader.formatParam & 0x80) { | ||
535 | foundHeader = 1; | ||
536 | usbvision->lastIsocFrameNum = -1; // do not check for lost frames this time | ||
537 | usbvision_unrequest_intra(usbvision); | ||
538 | break; | ||
539 | } | ||
540 | } | ||
541 | else { | ||
542 | foundHeader = 1; | ||
543 | break; | ||
544 | } | ||
545 | } | ||
546 | |||
547 | if (foundHeader) { | ||
548 | frame->frmwidth = frame->isocHeader.frameWidth * usbvision->stretch_width; | ||
549 | frame->frmheight = frame->isocHeader.frameHeight * usbvision->stretch_height; | ||
550 | frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3; | ||
551 | } | ||
552 | else { // no header found | ||
553 | PDEBUG(DBG_HEADER, "skipping scratch data, no header"); | ||
554 | scratch_reset(usbvision); | ||
555 | return ParseState_EndParse; | ||
556 | } | ||
557 | |||
558 | // found header | ||
559 | if (frame->isocHeader.dataFormat==ISOC_MODE_COMPRESS) { | ||
560 | //check isocHeader.frameNum for lost frames | ||
561 | if (usbvision->lastIsocFrameNum >= 0) { | ||
562 | if (((usbvision->lastIsocFrameNum + 1) % 32) != frame->isocHeader.frameNum) { | ||
563 | // unexpected frame drop: need to request new intra frame | ||
564 | PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isocHeader.frameNum); | ||
565 | usbvision_request_intra(usbvision); | ||
566 | return ParseState_NextFrame; | ||
567 | } | ||
568 | } | ||
569 | usbvision->lastIsocFrameNum = frame->isocHeader.frameNum; | ||
570 | } | ||
571 | usbvision->header_count++; | ||
572 | frame->scanstate = ScanState_Lines; | ||
573 | frame->curline = 0; | ||
574 | |||
575 | if (force_testpattern) { | ||
576 | usbvision_testpattern(usbvision, 1, 1); | ||
577 | return ParseState_NextFrame; | ||
578 | } | ||
579 | return ParseState_Continue; | ||
580 | } | ||
581 | |||
582 | static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision, | ||
583 | long *pcopylen) | ||
584 | { | ||
585 | volatile struct usbvision_frame *frame; | ||
586 | unsigned char *f; | ||
587 | int len; | ||
588 | int i; | ||
589 | unsigned char yuyv[4]={180, 128, 10, 128}; // YUV components | ||
590 | unsigned char rv, gv, bv; // RGB components | ||
591 | int clipmask_index, bytes_per_pixel; | ||
592 | int stretch_bytes, clipmask_add; | ||
593 | |||
594 | frame = usbvision->curFrame; | ||
595 | f = frame->data + (frame->v4l2_linesize * frame->curline); | ||
596 | |||
597 | /* Make sure there's enough data for the entire line */ | ||
598 | len = (frame->isocHeader.frameWidth * 2)+5; | ||
599 | if (scratch_len(usbvision) < len) { | ||
600 | PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len); | ||
601 | return ParseState_Out; | ||
602 | } | ||
603 | |||
604 | if ((frame->curline + 1) >= frame->frmheight) { | ||
605 | return ParseState_NextFrame; | ||
606 | } | ||
607 | |||
608 | bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; | ||
609 | stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel; | ||
610 | clipmask_index = frame->curline * MAX_FRAME_WIDTH; | ||
611 | clipmask_add = usbvision->stretch_width; | ||
612 | |||
613 | for (i = 0; i < frame->frmwidth; i+=(2 * usbvision->stretch_width)) { | ||
614 | |||
615 | scratch_get(usbvision, &yuyv[0], 4); | ||
616 | |||
617 | if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
618 | *f++ = yuyv[0]; // Y | ||
619 | *f++ = yuyv[3]; // U | ||
620 | } | ||
621 | else { | ||
622 | |||
623 | YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv); | ||
624 | switch (frame->v4l2_format.format) { | ||
625 | case V4L2_PIX_FMT_RGB565: | ||
626 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); | ||
627 | *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); | ||
628 | break; | ||
629 | case V4L2_PIX_FMT_RGB24: | ||
630 | *f++ = bv; | ||
631 | *f++ = gv; | ||
632 | *f++ = rv; | ||
633 | break; | ||
634 | case V4L2_PIX_FMT_RGB32: | ||
635 | *f++ = bv; | ||
636 | *f++ = gv; | ||
637 | *f++ = rv; | ||
638 | f++; | ||
639 | break; | ||
640 | case V4L2_PIX_FMT_RGB555: | ||
641 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); | ||
642 | *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); | ||
643 | break; | ||
644 | } | ||
645 | } | ||
646 | clipmask_index += clipmask_add; | ||
647 | f += stretch_bytes; | ||
648 | |||
649 | if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
650 | *f++ = yuyv[2]; // Y | ||
651 | *f++ = yuyv[1]; // V | ||
652 | } | ||
653 | else { | ||
654 | |||
655 | YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv); | ||
656 | switch (frame->v4l2_format.format) { | ||
657 | case V4L2_PIX_FMT_RGB565: | ||
658 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); | ||
659 | *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); | ||
660 | break; | ||
661 | case V4L2_PIX_FMT_RGB24: | ||
662 | *f++ = bv; | ||
663 | *f++ = gv; | ||
664 | *f++ = rv; | ||
665 | break; | ||
666 | case V4L2_PIX_FMT_RGB32: | ||
667 | *f++ = bv; | ||
668 | *f++ = gv; | ||
669 | *f++ = rv; | ||
670 | f++; | ||
671 | break; | ||
672 | case V4L2_PIX_FMT_RGB555: | ||
673 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); | ||
674 | *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); | ||
675 | break; | ||
676 | } | ||
677 | } | ||
678 | clipmask_index += clipmask_add; | ||
679 | f += stretch_bytes; | ||
680 | } | ||
681 | |||
682 | frame->curline += usbvision->stretch_height; | ||
683 | *pcopylen += frame->v4l2_linesize * usbvision->stretch_height; | ||
684 | |||
685 | if (frame->curline >= frame->frmheight) { | ||
686 | return ParseState_NextFrame; | ||
687 | } | ||
688 | else { | ||
689 | return ParseState_Continue; | ||
690 | } | ||
691 | } | ||
692 | |||
693 | /* The decompression routine */ | ||
694 | static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *Compressed, | ||
695 | unsigned char *Decompressed, int *StartPos, | ||
696 | int *BlockTypeStartPos, int Len) | ||
697 | { | ||
698 | int RestPixel, Idx, MaxPos, Pos, ExtraPos, BlockLen, BlockTypePos, BlockTypeLen; | ||
699 | unsigned char BlockByte, BlockCode, BlockType, BlockTypeByte, Integrator; | ||
700 | |||
701 | Integrator = 0; | ||
702 | Pos = *StartPos; | ||
703 | BlockTypePos = *BlockTypeStartPos; | ||
704 | MaxPos = 396; //Pos + Len; | ||
705 | ExtraPos = Pos; | ||
706 | BlockLen = 0; | ||
707 | BlockByte = 0; | ||
708 | BlockCode = 0; | ||
709 | BlockType = 0; | ||
710 | BlockTypeByte = 0; | ||
711 | BlockTypeLen = 0; | ||
712 | RestPixel = Len; | ||
713 | |||
714 | for (Idx = 0; Idx < Len; Idx++) { | ||
715 | |||
716 | if (BlockLen == 0) { | ||
717 | if (BlockTypeLen==0) { | ||
718 | BlockTypeByte = Compressed[BlockTypePos]; | ||
719 | BlockTypePos++; | ||
720 | BlockTypeLen = 4; | ||
721 | } | ||
722 | BlockType = (BlockTypeByte & 0xC0) >> 6; | ||
723 | |||
724 | //statistic: | ||
725 | usbvision->ComprBlockTypes[BlockType]++; | ||
726 | |||
727 | Pos = ExtraPos; | ||
728 | if (BlockType == 0) { | ||
729 | if(RestPixel >= 24) { | ||
730 | Idx += 23; | ||
731 | RestPixel -= 24; | ||
732 | Integrator = Decompressed[Idx]; | ||
733 | } else { | ||
734 | Idx += RestPixel - 1; | ||
735 | RestPixel = 0; | ||
736 | } | ||
737 | } else { | ||
738 | BlockCode = Compressed[Pos]; | ||
739 | Pos++; | ||
740 | if (RestPixel >= 24) { | ||
741 | BlockLen = 24; | ||
742 | } else { | ||
743 | BlockLen = RestPixel; | ||
744 | } | ||
745 | RestPixel -= BlockLen; | ||
746 | ExtraPos = Pos + (BlockLen / 4); | ||
747 | } | ||
748 | BlockTypeByte <<= 2; | ||
749 | BlockTypeLen -= 1; | ||
750 | } | ||
751 | if (BlockLen > 0) { | ||
752 | if ((BlockLen%4) == 0) { | ||
753 | BlockByte = Compressed[Pos]; | ||
754 | Pos++; | ||
755 | } | ||
756 | if (BlockType == 1) { //inter Block | ||
757 | Integrator = Decompressed[Idx]; | ||
758 | } | ||
759 | switch (BlockByte & 0xC0) { | ||
760 | case 0x03<<6: | ||
761 | Integrator += Compressed[ExtraPos]; | ||
762 | ExtraPos++; | ||
763 | break; | ||
764 | case 0x02<<6: | ||
765 | Integrator += BlockCode; | ||
766 | break; | ||
767 | case 0x00: | ||
768 | Integrator -= BlockCode; | ||
769 | break; | ||
770 | } | ||
771 | Decompressed[Idx] = Integrator; | ||
772 | BlockByte <<= 2; | ||
773 | BlockLen -= 1; | ||
774 | } | ||
775 | } | ||
776 | *StartPos = ExtraPos; | ||
777 | *BlockTypeStartPos = BlockTypePos; | ||
778 | return Idx; | ||
779 | } | ||
780 | |||
781 | |||
782 | /* | ||
783 | * usbvision_parse_compress() | ||
784 | * | ||
785 | * Parse compressed frame from the scratch buffer, put | ||
786 | * decoded RGB value into the current frame buffer and add the written | ||
787 | * number of bytes (RGB) to the *pcopylen. | ||
788 | * | ||
789 | */ | ||
790 | static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, | ||
791 | long *pcopylen) | ||
792 | { | ||
793 | #define USBVISION_STRIP_MAGIC 0x5A | ||
794 | #define USBVISION_STRIP_LEN_MAX 400 | ||
795 | #define USBVISION_STRIP_HEADER_LEN 3 | ||
796 | |||
797 | struct usbvision_frame *frame; | ||
798 | unsigned char *f,*u = NULL ,*v = NULL; | ||
799 | unsigned char StripData[USBVISION_STRIP_LEN_MAX]; | ||
800 | unsigned char StripHeader[USBVISION_STRIP_HEADER_LEN]; | ||
801 | int Idx, IdxEnd, StripLen, StripPtr, StartBlockPos, BlockPos, BlockTypePos; | ||
802 | int clipmask_index, bytes_per_pixel, rc; | ||
803 | int imageSize; | ||
804 | unsigned char rv, gv, bv; | ||
805 | static unsigned char *Y, *U, *V; | ||
806 | |||
807 | frame = usbvision->curFrame; | ||
808 | imageSize = frame->frmwidth * frame->frmheight; | ||
809 | if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || | ||
810 | (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) { // this is a planar format | ||
811 | //... v4l2_linesize not used here. | ||
812 | f = frame->data + (frame->width * frame->curline); | ||
813 | } else | ||
814 | f = frame->data + (frame->v4l2_linesize * frame->curline); | ||
815 | |||
816 | if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV){ //initialise u and v pointers | ||
817 | // get base of u and b planes add halfoffset | ||
818 | |||
819 | u = frame->data | ||
820 | + imageSize | ||
821 | + (frame->frmwidth >>1) * frame->curline ; | ||
822 | v = u + (imageSize >>1 ); | ||
823 | |||
824 | } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420){ | ||
825 | |||
826 | v = frame->data + imageSize + ((frame->curline* (frame->width))>>2) ; | ||
827 | u = v + (imageSize >>2) ; | ||
828 | } | ||
829 | |||
830 | if (frame->curline == 0) { | ||
831 | usbvision_adjust_compression(usbvision); | ||
832 | } | ||
833 | |||
834 | if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) { | ||
835 | return ParseState_Out; | ||
836 | } | ||
837 | |||
838 | //get strip header without changing the scratch_read_ptr | ||
839 | scratch_set_extra_ptr(usbvision, &StripPtr, 0); | ||
840 | scratch_get_extra(usbvision, &StripHeader[0], &StripPtr, | ||
841 | USBVISION_STRIP_HEADER_LEN); | ||
842 | |||
843 | if (StripHeader[0] != USBVISION_STRIP_MAGIC) { | ||
844 | // wrong strip magic | ||
845 | usbvision->stripMagicErrors++; | ||
846 | return ParseState_NextFrame; | ||
847 | } | ||
848 | |||
849 | if (frame->curline != (int)StripHeader[2]) { | ||
850 | //line number missmatch error | ||
851 | usbvision->stripLineNumberErrors++; | ||
852 | } | ||
853 | |||
854 | StripLen = 2 * (unsigned int)StripHeader[1]; | ||
855 | if (StripLen > USBVISION_STRIP_LEN_MAX) { | ||
856 | // strip overrun | ||
857 | // I think this never happens | ||
858 | usbvision_request_intra(usbvision); | ||
859 | } | ||
860 | |||
861 | if (scratch_len(usbvision) < StripLen) { | ||
862 | //there is not enough data for the strip | ||
863 | return ParseState_Out; | ||
864 | } | ||
865 | |||
866 | if (usbvision->IntraFrameBuffer) { | ||
867 | Y = usbvision->IntraFrameBuffer + frame->frmwidth * frame->curline; | ||
868 | U = usbvision->IntraFrameBuffer + imageSize + (frame->frmwidth / 2) * (frame->curline / 2); | ||
869 | V = usbvision->IntraFrameBuffer + imageSize / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2); | ||
870 | } | ||
871 | else { | ||
872 | return ParseState_NextFrame; | ||
873 | } | ||
874 | |||
875 | bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; | ||
876 | clipmask_index = frame->curline * MAX_FRAME_WIDTH; | ||
877 | |||
878 | scratch_get(usbvision, StripData, StripLen); | ||
879 | |||
880 | IdxEnd = frame->frmwidth; | ||
881 | BlockTypePos = USBVISION_STRIP_HEADER_LEN; | ||
882 | StartBlockPos = BlockTypePos + (IdxEnd - 1) / 96 + (IdxEnd / 2 - 1) / 96 + 2; | ||
883 | BlockPos = StartBlockPos; | ||
884 | |||
885 | usbvision->BlockPos = BlockPos; | ||
886 | |||
887 | if ((rc = usbvision_decompress(usbvision, StripData, Y, &BlockPos, &BlockTypePos, IdxEnd)) != IdxEnd) { | ||
888 | //return ParseState_Continue; | ||
889 | } | ||
890 | if (StripLen > usbvision->maxStripLen) { | ||
891 | usbvision->maxStripLen = StripLen; | ||
892 | } | ||
893 | |||
894 | if (frame->curline%2) { | ||
895 | if ((rc = usbvision_decompress(usbvision, StripData, V, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) { | ||
896 | //return ParseState_Continue; | ||
897 | } | ||
898 | } | ||
899 | else { | ||
900 | if ((rc = usbvision_decompress(usbvision, StripData, U, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) { | ||
901 | //return ParseState_Continue; | ||
902 | } | ||
903 | } | ||
904 | |||
905 | if (BlockPos > usbvision->comprBlockPos) { | ||
906 | usbvision->comprBlockPos = BlockPos; | ||
907 | } | ||
908 | if (BlockPos > StripLen) { | ||
909 | usbvision->stripLenErrors++; | ||
910 | } | ||
911 | |||
912 | for (Idx = 0; Idx < IdxEnd; Idx++) { | ||
913 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
914 | *f++ = Y[Idx]; | ||
915 | *f++ = Idx & 0x01 ? U[Idx/2] : V[Idx/2]; | ||
916 | } | ||
917 | else if(frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) { | ||
918 | *f++ = Y[Idx]; | ||
919 | if ( Idx & 0x01) | ||
920 | *u++ = U[Idx>>1] ; | ||
921 | else | ||
922 | *v++ = V[Idx>>1]; | ||
923 | } | ||
924 | else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { | ||
925 | *f++ = Y [Idx]; | ||
926 | if ( !(( Idx & 0x01 ) | ( frame->curline & 0x01 )) ){ | ||
927 | |||
928 | /* only need do this for 1 in 4 pixels */ | ||
929 | /* intraframe buffer is YUV420 format */ | ||
930 | |||
931 | *u++ = U[Idx >>1]; | ||
932 | *v++ = V[Idx >>1]; | ||
933 | } | ||
934 | |||
935 | } | ||
936 | else { | ||
937 | YUV_TO_RGB_BY_THE_BOOK(Y[Idx], U[Idx/2], V[Idx/2], rv, gv, bv); | ||
938 | switch (frame->v4l2_format.format) { | ||
939 | case V4L2_PIX_FMT_GREY: | ||
940 | *f++ = Y[Idx]; | ||
941 | break; | ||
942 | case V4L2_PIX_FMT_RGB555: | ||
943 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); | ||
944 | *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); | ||
945 | break; | ||
946 | case V4L2_PIX_FMT_RGB565: | ||
947 | *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); | ||
948 | *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); | ||
949 | break; | ||
950 | case V4L2_PIX_FMT_RGB24: | ||
951 | *f++ = bv; | ||
952 | *f++ = gv; | ||
953 | *f++ = rv; | ||
954 | break; | ||
955 | case V4L2_PIX_FMT_RGB32: | ||
956 | *f++ = bv; | ||
957 | *f++ = gv; | ||
958 | *f++ = rv; | ||
959 | f++; | ||
960 | break; | ||
961 | } | ||
962 | } | ||
963 | clipmask_index++; | ||
964 | } | ||
965 | /* Deal with non-integer no. of bytes for YUV420P */ | ||
966 | if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420 ) | ||
967 | *pcopylen += frame->v4l2_linesize; | ||
968 | else | ||
969 | *pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1; | ||
970 | |||
971 | frame->curline += 1; | ||
972 | |||
973 | if (frame->curline >= frame->frmheight) { | ||
974 | return ParseState_NextFrame; | ||
975 | } | ||
976 | else { | ||
977 | return ParseState_Continue; | ||
978 | } | ||
979 | |||
980 | } | ||
981 | |||
982 | |||
983 | /* | ||
984 | * usbvision_parse_lines_420() | ||
985 | * | ||
986 | * Parse two lines from the scratch buffer, put | ||
987 | * decoded RGB value into the current frame buffer and add the written | ||
988 | * number of bytes (RGB) to the *pcopylen. | ||
989 | * | ||
990 | */ | ||
991 | static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision, | ||
992 | long *pcopylen) | ||
993 | { | ||
994 | struct usbvision_frame *frame; | ||
995 | unsigned char *f_even = NULL, *f_odd = NULL; | ||
996 | unsigned int pixel_per_line, block; | ||
997 | int pixel, block_split; | ||
998 | int y_ptr, u_ptr, v_ptr, y_odd_offset; | ||
999 | const int y_block_size = 128; | ||
1000 | const int uv_block_size = 64; | ||
1001 | const int sub_block_size = 32; | ||
1002 | const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4; | ||
1003 | const int uv_step[]= { 0, 0, 0, 4 }, uv_step_size = 4; | ||
1004 | unsigned char y[2], u, v; /* YUV components */ | ||
1005 | int y_, u_, v_, vb, uvg, ur; | ||
1006 | int r_, g_, b_; /* RGB components */ | ||
1007 | unsigned char g; | ||
1008 | int clipmask_even_index, clipmask_odd_index, bytes_per_pixel; | ||
1009 | int clipmask_add, stretch_bytes; | ||
1010 | |||
1011 | frame = usbvision->curFrame; | ||
1012 | f_even = frame->data + (frame->v4l2_linesize * frame->curline); | ||
1013 | f_odd = f_even + frame->v4l2_linesize * usbvision->stretch_height; | ||
1014 | |||
1015 | /* Make sure there's enough data for the entire line */ | ||
1016 | /* In this mode usbvision transfer 3 bytes for every 2 pixels */ | ||
1017 | /* I need two lines to decode the color */ | ||
1018 | bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; | ||
1019 | stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel; | ||
1020 | clipmask_even_index = frame->curline * MAX_FRAME_WIDTH; | ||
1021 | clipmask_odd_index = clipmask_even_index + MAX_FRAME_WIDTH; | ||
1022 | clipmask_add = usbvision->stretch_width; | ||
1023 | pixel_per_line = frame->isocHeader.frameWidth; | ||
1024 | |||
1025 | if (scratch_len(usbvision) < (int)pixel_per_line * 3) { | ||
1026 | //printk(KERN_DEBUG "out of data, need %d\n", len); | ||
1027 | return ParseState_Out; | ||
1028 | } | ||
1029 | |||
1030 | if ((frame->curline + 1) >= frame->frmheight) { | ||
1031 | return ParseState_NextFrame; | ||
1032 | } | ||
1033 | |||
1034 | block_split = (pixel_per_line%y_block_size) ? 1 : 0; //are some blocks splitted into different lines? | ||
1035 | |||
1036 | y_odd_offset = (pixel_per_line / y_block_size) * (y_block_size + uv_block_size) | ||
1037 | + block_split * uv_block_size; | ||
1038 | |||
1039 | scratch_set_extra_ptr(usbvision, &y_ptr, y_odd_offset); | ||
1040 | scratch_set_extra_ptr(usbvision, &u_ptr, y_block_size); | ||
1041 | scratch_set_extra_ptr(usbvision, &v_ptr, y_odd_offset | ||
1042 | + (4 - block_split) * sub_block_size); | ||
1043 | |||
1044 | for (block = 0; block < (pixel_per_line / sub_block_size); | ||
1045 | block++) { | ||
1046 | |||
1047 | |||
1048 | for (pixel = 0; pixel < sub_block_size; pixel +=2) { | ||
1049 | scratch_get(usbvision, &y[0], 2); | ||
1050 | scratch_get_extra(usbvision, &u, &u_ptr, 1); | ||
1051 | scratch_get_extra(usbvision, &v, &v_ptr, 1); | ||
1052 | |||
1053 | //I don't use the YUV_TO_RGB macro for better performance | ||
1054 | v_ = v - 128; | ||
1055 | u_ = u - 128; | ||
1056 | vb = 132252 * v_; | ||
1057 | uvg= -53281 * u_ - 25625 * v_; | ||
1058 | ur = 104595 * u_; | ||
1059 | |||
1060 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
1061 | *f_even++ = y[0]; | ||
1062 | *f_even++ = v; | ||
1063 | } | ||
1064 | else { | ||
1065 | y_ = 76284 * (y[0] - 16); | ||
1066 | |||
1067 | b_ = (y_ + vb) >> 16; | ||
1068 | g_ = (y_ + uvg)>> 16; | ||
1069 | r_ = (y_ + ur) >> 16; | ||
1070 | |||
1071 | switch (frame->v4l2_format.format) { | ||
1072 | case V4L2_PIX_FMT_RGB565: | ||
1073 | g = LIMIT_RGB(g_); | ||
1074 | *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); | ||
1075 | *f_even++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); | ||
1076 | break; | ||
1077 | case V4L2_PIX_FMT_RGB24: | ||
1078 | *f_even++ = LIMIT_RGB(b_); | ||
1079 | *f_even++ = LIMIT_RGB(g_); | ||
1080 | *f_even++ = LIMIT_RGB(r_); | ||
1081 | break; | ||
1082 | case V4L2_PIX_FMT_RGB32: | ||
1083 | *f_even++ = LIMIT_RGB(b_); | ||
1084 | *f_even++ = LIMIT_RGB(g_); | ||
1085 | *f_even++ = LIMIT_RGB(r_); | ||
1086 | f_even++; | ||
1087 | break; | ||
1088 | case V4L2_PIX_FMT_RGB555: | ||
1089 | g = LIMIT_RGB(g_); | ||
1090 | *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); | ||
1091 | *f_even++ = (0x03 & ( g >> 6)) | | ||
1092 | (0x7C & (LIMIT_RGB(r_) >> 1)); | ||
1093 | break; | ||
1094 | } | ||
1095 | } | ||
1096 | clipmask_even_index += clipmask_add; | ||
1097 | f_even += stretch_bytes; | ||
1098 | |||
1099 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
1100 | *f_even++ = y[1]; | ||
1101 | *f_even++ = u; | ||
1102 | } | ||
1103 | else { | ||
1104 | y_ = 76284 * (y[1] - 16); | ||
1105 | |||
1106 | b_ = (y_ + vb) >> 16; | ||
1107 | g_ = (y_ + uvg)>> 16; | ||
1108 | r_ = (y_ + ur) >> 16; | ||
1109 | |||
1110 | switch (frame->v4l2_format.format) { | ||
1111 | case V4L2_PIX_FMT_RGB565: | ||
1112 | g = LIMIT_RGB(g_); | ||
1113 | *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); | ||
1114 | *f_even++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); | ||
1115 | break; | ||
1116 | case V4L2_PIX_FMT_RGB24: | ||
1117 | *f_even++ = LIMIT_RGB(b_); | ||
1118 | *f_even++ = LIMIT_RGB(g_); | ||
1119 | *f_even++ = LIMIT_RGB(r_); | ||
1120 | break; | ||
1121 | case V4L2_PIX_FMT_RGB32: | ||
1122 | *f_even++ = LIMIT_RGB(b_); | ||
1123 | *f_even++ = LIMIT_RGB(g_); | ||
1124 | *f_even++ = LIMIT_RGB(r_); | ||
1125 | f_even++; | ||
1126 | break; | ||
1127 | case V4L2_PIX_FMT_RGB555: | ||
1128 | g = LIMIT_RGB(g_); | ||
1129 | *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); | ||
1130 | *f_even++ = (0x03 & ( g >> 6)) | | ||
1131 | (0x7C & (LIMIT_RGB(r_) >> 1)); | ||
1132 | break; | ||
1133 | } | ||
1134 | } | ||
1135 | clipmask_even_index += clipmask_add; | ||
1136 | f_even += stretch_bytes; | ||
1137 | |||
1138 | scratch_get_extra(usbvision, &y[0], &y_ptr, 2); | ||
1139 | |||
1140 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
1141 | *f_odd++ = y[0]; | ||
1142 | *f_odd++ = v; | ||
1143 | } | ||
1144 | else { | ||
1145 | y_ = 76284 * (y[0] - 16); | ||
1146 | |||
1147 | b_ = (y_ + vb) >> 16; | ||
1148 | g_ = (y_ + uvg)>> 16; | ||
1149 | r_ = (y_ + ur) >> 16; | ||
1150 | |||
1151 | switch (frame->v4l2_format.format) { | ||
1152 | case V4L2_PIX_FMT_RGB565: | ||
1153 | g = LIMIT_RGB(g_); | ||
1154 | *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); | ||
1155 | *f_odd++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); | ||
1156 | break; | ||
1157 | case V4L2_PIX_FMT_RGB24: | ||
1158 | *f_odd++ = LIMIT_RGB(b_); | ||
1159 | *f_odd++ = LIMIT_RGB(g_); | ||
1160 | *f_odd++ = LIMIT_RGB(r_); | ||
1161 | break; | ||
1162 | case V4L2_PIX_FMT_RGB32: | ||
1163 | *f_odd++ = LIMIT_RGB(b_); | ||
1164 | *f_odd++ = LIMIT_RGB(g_); | ||
1165 | *f_odd++ = LIMIT_RGB(r_); | ||
1166 | f_odd++; | ||
1167 | break; | ||
1168 | case V4L2_PIX_FMT_RGB555: | ||
1169 | g = LIMIT_RGB(g_); | ||
1170 | *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); | ||
1171 | *f_odd++ = (0x03 & ( g >> 6)) | | ||
1172 | (0x7C & (LIMIT_RGB(r_) >> 1)); | ||
1173 | break; | ||
1174 | } | ||
1175 | } | ||
1176 | clipmask_odd_index += clipmask_add; | ||
1177 | f_odd += stretch_bytes; | ||
1178 | |||
1179 | if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { | ||
1180 | *f_odd++ = y[1]; | ||
1181 | *f_odd++ = u; | ||
1182 | } | ||
1183 | else { | ||
1184 | y_ = 76284 * (y[1] - 16); | ||
1185 | |||
1186 | b_ = (y_ + vb) >> 16; | ||
1187 | g_ = (y_ + uvg)>> 16; | ||
1188 | r_ = (y_ + ur) >> 16; | ||
1189 | |||
1190 | switch (frame->v4l2_format.format) { | ||
1191 | case V4L2_PIX_FMT_RGB565: | ||
1192 | g = LIMIT_RGB(g_); | ||
1193 | *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); | ||
1194 | *f_odd++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); | ||
1195 | break; | ||
1196 | case V4L2_PIX_FMT_RGB24: | ||
1197 | *f_odd++ = LIMIT_RGB(b_); | ||
1198 | *f_odd++ = LIMIT_RGB(g_); | ||
1199 | *f_odd++ = LIMIT_RGB(r_); | ||
1200 | break; | ||
1201 | case V4L2_PIX_FMT_RGB32: | ||
1202 | *f_odd++ = LIMIT_RGB(b_); | ||
1203 | *f_odd++ = LIMIT_RGB(g_); | ||
1204 | *f_odd++ = LIMIT_RGB(r_); | ||
1205 | f_odd++; | ||
1206 | break; | ||
1207 | case V4L2_PIX_FMT_RGB555: | ||
1208 | g = LIMIT_RGB(g_); | ||
1209 | *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); | ||
1210 | *f_odd++ = (0x03 & ( g >> 6)) | | ||
1211 | (0x7C & (LIMIT_RGB(r_) >> 1)); | ||
1212 | break; | ||
1213 | } | ||
1214 | } | ||
1215 | clipmask_odd_index += clipmask_add; | ||
1216 | f_odd += stretch_bytes; | ||
1217 | } | ||
1218 | |||
1219 | scratch_rm_old(usbvision,y_step[block % y_step_size] * sub_block_size); | ||
1220 | scratch_inc_extra_ptr(&y_ptr, y_step[(block + 2 * block_split) % y_step_size] | ||
1221 | * sub_block_size); | ||
1222 | scratch_inc_extra_ptr(&u_ptr, uv_step[block % uv_step_size] | ||
1223 | * sub_block_size); | ||
1224 | scratch_inc_extra_ptr(&v_ptr, uv_step[(block + 2 * block_split) % uv_step_size] | ||
1225 | * sub_block_size); | ||
1226 | } | ||
1227 | |||
1228 | scratch_rm_old(usbvision, pixel_per_line * 3 / 2 | ||
1229 | + block_split * sub_block_size); | ||
1230 | |||
1231 | frame->curline += 2 * usbvision->stretch_height; | ||
1232 | *pcopylen += frame->v4l2_linesize * 2 * usbvision->stretch_height; | ||
1233 | |||
1234 | if (frame->curline >= frame->frmheight) | ||
1235 | return ParseState_NextFrame; | ||
1236 | else | ||
1237 | return ParseState_Continue; | ||
1238 | } | ||
1239 | |||
1240 | /* | ||
1241 | * usbvision_parse_data() | ||
1242 | * | ||
1243 | * Generic routine to parse the scratch buffer. It employs either | ||
1244 | * usbvision_find_header() or usbvision_parse_lines() to do most | ||
1245 | * of work. | ||
1246 | * | ||
1247 | */ | ||
1248 | static void usbvision_parse_data(struct usb_usbvision *usbvision) | ||
1249 | { | ||
1250 | struct usbvision_frame *frame; | ||
1251 | enum ParseState newstate; | ||
1252 | long copylen = 0; | ||
1253 | unsigned long lock_flags; | ||
1254 | |||
1255 | frame = usbvision->curFrame; | ||
1256 | |||
1257 | PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision)); | ||
1258 | |||
1259 | while (1) { | ||
1260 | |||
1261 | newstate = ParseState_Out; | ||
1262 | if (scratch_len(usbvision)) { | ||
1263 | if (frame->scanstate == ScanState_Scanning) { | ||
1264 | newstate = usbvision_find_header(usbvision); | ||
1265 | } | ||
1266 | else if (frame->scanstate == ScanState_Lines) { | ||
1267 | if (usbvision->isocMode == ISOC_MODE_YUV420) { | ||
1268 | newstate = usbvision_parse_lines_420(usbvision, ©len); | ||
1269 | } | ||
1270 | else if (usbvision->isocMode == ISOC_MODE_YUV422) { | ||
1271 | newstate = usbvision_parse_lines_422(usbvision, ©len); | ||
1272 | } | ||
1273 | else if (usbvision->isocMode == ISOC_MODE_COMPRESS) { | ||
1274 | newstate = usbvision_parse_compress(usbvision, ©len); | ||
1275 | } | ||
1276 | |||
1277 | } | ||
1278 | } | ||
1279 | if (newstate == ParseState_Continue) { | ||
1280 | continue; | ||
1281 | } | ||
1282 | else if ((newstate == ParseState_NextFrame) || (newstate == ParseState_Out)) { | ||
1283 | break; | ||
1284 | } | ||
1285 | else { | ||
1286 | return; /* ParseState_EndParse */ | ||
1287 | } | ||
1288 | } | ||
1289 | |||
1290 | if (newstate == ParseState_NextFrame) { | ||
1291 | frame->grabstate = FrameState_Done; | ||
1292 | do_gettimeofday(&(frame->timestamp)); | ||
1293 | frame->sequence = usbvision->frame_num; | ||
1294 | |||
1295 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
1296 | list_move_tail(&(frame->frame), &usbvision->outqueue); | ||
1297 | usbvision->curFrame = NULL; | ||
1298 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
1299 | |||
1300 | usbvision->frame_num++; | ||
1301 | |||
1302 | /* This will cause the process to request another frame. */ | ||
1303 | if (waitqueue_active(&usbvision->wait_frame)) { | ||
1304 | PDEBUG(DBG_PARSE, "Wake up !"); | ||
1305 | wake_up_interruptible(&usbvision->wait_frame); | ||
1306 | } | ||
1307 | } | ||
1308 | else | ||
1309 | frame->grabstate = FrameState_Grabbing; | ||
1310 | |||
1311 | |||
1312 | /* Update the frame's uncompressed length. */ | ||
1313 | frame->scanlength += copylen; | ||
1314 | } | ||
1315 | |||
1316 | |||
1317 | /* | ||
1318 | * Make all of the blocks of data contiguous | ||
1319 | */ | ||
1320 | static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, | ||
1321 | struct urb *urb) | ||
1322 | { | ||
1323 | unsigned char *packet_data; | ||
1324 | int i, totlen = 0; | ||
1325 | |||
1326 | for (i = 0; i < urb->number_of_packets; i++) { | ||
1327 | int packet_len = urb->iso_frame_desc[i].actual_length; | ||
1328 | int packet_stat = urb->iso_frame_desc[i].status; | ||
1329 | |||
1330 | packet_data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; | ||
1331 | |||
1332 | /* Detect and ignore errored packets */ | ||
1333 | if (packet_stat) { // packet_stat != 0 ????????????? | ||
1334 | PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat); | ||
1335 | usbvision->isocErrCount++; | ||
1336 | continue; | ||
1337 | } | ||
1338 | |||
1339 | /* Detect and ignore empty packets */ | ||
1340 | if (packet_len < 0) { | ||
1341 | PDEBUG(DBG_ISOC, "error packet [%d]", i); | ||
1342 | usbvision->isocSkipCount++; | ||
1343 | continue; | ||
1344 | } | ||
1345 | else if (packet_len == 0) { /* Frame end ????? */ | ||
1346 | PDEBUG(DBG_ISOC, "null packet [%d]", i); | ||
1347 | usbvision->isocstate=IsocState_NoFrame; | ||
1348 | usbvision->isocSkipCount++; | ||
1349 | continue; | ||
1350 | } | ||
1351 | else if (packet_len > usbvision->isocPacketSize) { | ||
1352 | PDEBUG(DBG_ISOC, "packet[%d] > isocPacketSize", i); | ||
1353 | usbvision->isocSkipCount++; | ||
1354 | continue; | ||
1355 | } | ||
1356 | |||
1357 | PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len); | ||
1358 | |||
1359 | if (usbvision->isocstate==IsocState_NoFrame) { //new frame begins | ||
1360 | usbvision->isocstate=IsocState_InFrame; | ||
1361 | scratch_mark_header(usbvision); | ||
1362 | usbvision_measure_bandwidth(usbvision); | ||
1363 | PDEBUG(DBG_ISOC, "packet with header"); | ||
1364 | } | ||
1365 | |||
1366 | /* | ||
1367 | * If usbvision continues to feed us with data but there is no | ||
1368 | * consumption (if, for example, V4L client fell asleep) we | ||
1369 | * may overflow the buffer. We have to move old data over to | ||
1370 | * free room for new data. This is bad for old data. If we | ||
1371 | * just drop new data then it's bad for new data... choose | ||
1372 | * your favorite evil here. | ||
1373 | */ | ||
1374 | if (scratch_free(usbvision) < packet_len) { | ||
1375 | |||
1376 | usbvision->scratch_ovf_count++; | ||
1377 | PDEBUG(DBG_ISOC, "scratch buf overflow! scr_len: %d, n: %d", | ||
1378 | scratch_len(usbvision), packet_len); | ||
1379 | scratch_rm_old(usbvision, packet_len - scratch_free(usbvision)); | ||
1380 | } | ||
1381 | |||
1382 | /* Now we know that there is enough room in scratch buffer */ | ||
1383 | scratch_put(usbvision, packet_data, packet_len); | ||
1384 | totlen += packet_len; | ||
1385 | usbvision->isocDataCount += packet_len; | ||
1386 | usbvision->isocPacketCount++; | ||
1387 | } | ||
1388 | #if ENABLE_HEXDUMP | ||
1389 | if (totlen > 0) { | ||
1390 | static int foo = 0; | ||
1391 | if (foo < 1) { | ||
1392 | printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen); | ||
1393 | usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen); | ||
1394 | ++foo; | ||
1395 | } | ||
1396 | } | ||
1397 | #endif | ||
1398 | return totlen; | ||
1399 | } | ||
1400 | |||
1401 | static void usbvision_isocIrq(struct urb *urb) | ||
1402 | { | ||
1403 | int errCode = 0; | ||
1404 | int len; | ||
1405 | struct usb_usbvision *usbvision = urb->context; | ||
1406 | int i; | ||
1407 | unsigned long startTime = jiffies; | ||
1408 | struct usbvision_frame **f; | ||
1409 | |||
1410 | /* We don't want to do anything if we are about to be removed! */ | ||
1411 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1412 | return; | ||
1413 | |||
1414 | f = &usbvision->curFrame; | ||
1415 | |||
1416 | /* Manage streaming interruption */ | ||
1417 | if (usbvision->streaming == Stream_Interrupt) { | ||
1418 | usbvision->streaming = Stream_Idle; | ||
1419 | if ((*f)) { | ||
1420 | (*f)->grabstate = FrameState_Ready; | ||
1421 | (*f)->scanstate = ScanState_Scanning; | ||
1422 | } | ||
1423 | PDEBUG(DBG_IRQ, "stream interrupted"); | ||
1424 | wake_up_interruptible(&usbvision->wait_stream); | ||
1425 | } | ||
1426 | |||
1427 | /* Copy the data received into our scratch buffer */ | ||
1428 | len = usbvision_compress_isochronous(usbvision, urb); | ||
1429 | |||
1430 | usbvision->isocUrbCount++; | ||
1431 | usbvision->urb_length = len; | ||
1432 | |||
1433 | if (usbvision->streaming == Stream_On) { | ||
1434 | |||
1435 | /* If we collected enough data let's parse! */ | ||
1436 | if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */ | ||
1437 | /*If we don't have a frame we're current working on, complain */ | ||
1438 | if(!list_empty(&(usbvision->inqueue))) { | ||
1439 | if (!(*f)) { | ||
1440 | (*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame); | ||
1441 | } | ||
1442 | usbvision_parse_data(usbvision); | ||
1443 | } | ||
1444 | else { | ||
1445 | PDEBUG(DBG_IRQ, "received data, but no one needs it"); | ||
1446 | scratch_reset(usbvision); | ||
1447 | } | ||
1448 | } | ||
1449 | } | ||
1450 | else { | ||
1451 | PDEBUG(DBG_IRQ, "received data, but no one needs it"); | ||
1452 | scratch_reset(usbvision); | ||
1453 | } | ||
1454 | |||
1455 | usbvision->timeInIrq += jiffies - startTime; | ||
1456 | |||
1457 | for (i = 0; i < USBVISION_URB_FRAMES; i++) { | ||
1458 | urb->iso_frame_desc[i].status = 0; | ||
1459 | urb->iso_frame_desc[i].actual_length = 0; | ||
1460 | } | ||
1461 | |||
1462 | urb->status = 0; | ||
1463 | urb->dev = usbvision->dev; | ||
1464 | errCode = usb_submit_urb (urb, GFP_ATOMIC); | ||
1465 | |||
1466 | /* Disable this warning. By design of the driver. */ | ||
1467 | // if(errCode) { | ||
1468 | // err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode); | ||
1469 | // } | ||
1470 | |||
1471 | return; | ||
1472 | } | ||
1473 | |||
1474 | /*************************************/ | ||
1475 | /* Low level usbvision access functions */ | ||
1476 | /*************************************/ | ||
1477 | |||
1478 | /* | ||
1479 | * usbvision_read_reg() | ||
1480 | * | ||
1481 | * return < 0 -> Error | ||
1482 | * >= 0 -> Data | ||
1483 | */ | ||
1484 | |||
1485 | int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg) | ||
1486 | { | ||
1487 | int errCode = 0; | ||
1488 | unsigned char buffer[1]; | ||
1489 | |||
1490 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1491 | return -1; | ||
1492 | |||
1493 | errCode = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1), | ||
1494 | USBVISION_OP_CODE, | ||
1495 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, | ||
1496 | 0, (__u16) reg, buffer, 1, HZ); | ||
1497 | |||
1498 | if (errCode < 0) { | ||
1499 | err("%s: failed: error %d", __FUNCTION__, errCode); | ||
1500 | return errCode; | ||
1501 | } | ||
1502 | return buffer[0]; | ||
1503 | } | ||
1504 | |||
1505 | /* | ||
1506 | * usbvision_write_reg() | ||
1507 | * | ||
1508 | * return 1 -> Reg written | ||
1509 | * 0 -> usbvision is not yet ready | ||
1510 | * -1 -> Something went wrong | ||
1511 | */ | ||
1512 | |||
1513 | int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, | ||
1514 | unsigned char value) | ||
1515 | { | ||
1516 | int errCode = 0; | ||
1517 | |||
1518 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1519 | return 0; | ||
1520 | |||
1521 | errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1522 | USBVISION_OP_CODE, | ||
1523 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1524 | USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ); | ||
1525 | |||
1526 | if (errCode < 0) { | ||
1527 | err("%s: failed: error %d", __FUNCTION__, errCode); | ||
1528 | } | ||
1529 | return errCode; | ||
1530 | } | ||
1531 | |||
1532 | |||
1533 | static void usbvision_ctrlUrb_complete(struct urb *urb) | ||
1534 | { | ||
1535 | struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context; | ||
1536 | |||
1537 | PDEBUG(DBG_IRQ, ""); | ||
1538 | usbvision->ctrlUrbBusy = 0; | ||
1539 | if (waitqueue_active(&usbvision->ctrlUrb_wq)) { | ||
1540 | wake_up_interruptible(&usbvision->ctrlUrb_wq); | ||
1541 | } | ||
1542 | } | ||
1543 | |||
1544 | |||
1545 | static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address, | ||
1546 | unsigned char *data, int len) | ||
1547 | { | ||
1548 | int errCode = 0; | ||
1549 | |||
1550 | PDEBUG(DBG_IRQ, ""); | ||
1551 | if (len > 8) { | ||
1552 | return -EFAULT; | ||
1553 | } | ||
1554 | // down(&usbvision->ctrlUrbLock); | ||
1555 | if (usbvision->ctrlUrbBusy) { | ||
1556 | // up(&usbvision->ctrlUrbLock); | ||
1557 | return -EBUSY; | ||
1558 | } | ||
1559 | usbvision->ctrlUrbBusy = 1; | ||
1560 | // up(&usbvision->ctrlUrbLock); | ||
1561 | |||
1562 | usbvision->ctrlUrbSetup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; | ||
1563 | usbvision->ctrlUrbSetup.bRequest = USBVISION_OP_CODE; | ||
1564 | usbvision->ctrlUrbSetup.wValue = 0; | ||
1565 | usbvision->ctrlUrbSetup.wIndex = cpu_to_le16(address); | ||
1566 | usbvision->ctrlUrbSetup.wLength = cpu_to_le16(len); | ||
1567 | usb_fill_control_urb (usbvision->ctrlUrb, usbvision->dev, | ||
1568 | usb_sndctrlpipe(usbvision->dev, 1), | ||
1569 | (unsigned char *)&usbvision->ctrlUrbSetup, | ||
1570 | (void *)usbvision->ctrlUrbBuffer, len, | ||
1571 | usbvision_ctrlUrb_complete, | ||
1572 | (void *)usbvision); | ||
1573 | |||
1574 | memcpy(usbvision->ctrlUrbBuffer, data, len); | ||
1575 | |||
1576 | errCode = usb_submit_urb(usbvision->ctrlUrb, GFP_ATOMIC); | ||
1577 | if (errCode < 0) { | ||
1578 | // error in usb_submit_urb() | ||
1579 | usbvision->ctrlUrbBusy = 0; | ||
1580 | } | ||
1581 | PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, errCode); | ||
1582 | return errCode; | ||
1583 | } | ||
1584 | |||
1585 | |||
1586 | static int usbvision_init_compression(struct usb_usbvision *usbvision) | ||
1587 | { | ||
1588 | int errCode = 0; | ||
1589 | |||
1590 | usbvision->lastIsocFrameNum = -1; | ||
1591 | usbvision->isocDataCount = 0; | ||
1592 | usbvision->isocPacketCount = 0; | ||
1593 | usbvision->isocSkipCount = 0; | ||
1594 | usbvision->comprLevel = 50; | ||
1595 | usbvision->lastComprLevel = -1; | ||
1596 | usbvision->isocUrbCount = 0; | ||
1597 | usbvision->requestIntra = 1; | ||
1598 | usbvision->isocMeasureBandwidthCount = 0; | ||
1599 | |||
1600 | return errCode; | ||
1601 | } | ||
1602 | |||
1603 | /* this function measures the used bandwidth since last call | ||
1604 | * return: 0 : no error | ||
1605 | * sets usedBandwidth to 1-100 : 1-100% of full bandwidth resp. to isocPacketSize | ||
1606 | */ | ||
1607 | static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision) | ||
1608 | { | ||
1609 | int errCode = 0; | ||
1610 | |||
1611 | if (usbvision->isocMeasureBandwidthCount < 2) { // this gives an average bandwidth of 3 frames | ||
1612 | usbvision->isocMeasureBandwidthCount++; | ||
1613 | return errCode; | ||
1614 | } | ||
1615 | if ((usbvision->isocPacketSize > 0) && (usbvision->isocPacketCount > 0)) { | ||
1616 | usbvision->usedBandwidth = usbvision->isocDataCount / | ||
1617 | (usbvision->isocPacketCount + usbvision->isocSkipCount) * | ||
1618 | 100 / usbvision->isocPacketSize; | ||
1619 | } | ||
1620 | usbvision->isocMeasureBandwidthCount = 0; | ||
1621 | usbvision->isocDataCount = 0; | ||
1622 | usbvision->isocPacketCount = 0; | ||
1623 | usbvision->isocSkipCount = 0; | ||
1624 | return errCode; | ||
1625 | } | ||
1626 | |||
1627 | static int usbvision_adjust_compression (struct usb_usbvision *usbvision) | ||
1628 | { | ||
1629 | int errCode = 0; | ||
1630 | unsigned char buffer[6]; | ||
1631 | |||
1632 | PDEBUG(DBG_IRQ, ""); | ||
1633 | if ((adjustCompression) && (usbvision->usedBandwidth > 0)) { | ||
1634 | usbvision->comprLevel += (usbvision->usedBandwidth - 90) / 2; | ||
1635 | RESTRICT_TO_RANGE(usbvision->comprLevel, 0, 100); | ||
1636 | if (usbvision->comprLevel != usbvision->lastComprLevel) { | ||
1637 | int distorsion; | ||
1638 | if (usbvision->bridgeType == BRIDGE_NT1004 || usbvision->bridgeType == BRIDGE_NT1005) { | ||
1639 | buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM Threshold 1 | ||
1640 | buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM Threshold 2 | ||
1641 | distorsion = 7 + 248 * usbvision->comprLevel / 100; | ||
1642 | buffer[2] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (inter) | ||
1643 | buffer[3] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (intra) | ||
1644 | distorsion = 1 + 42 * usbvision->comprLevel / 100; | ||
1645 | buffer[4] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (inter) | ||
1646 | buffer[5] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (intra) | ||
1647 | } | ||
1648 | else { //BRIDGE_NT1003 | ||
1649 | buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM threshold 1 | ||
1650 | buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM threshold 2 | ||
1651 | distorsion = 2 + 253 * usbvision->comprLevel / 100; | ||
1652 | buffer[2] = (unsigned char)(distorsion & 0xFF); // distorsion threshold bit0-7 | ||
1653 | buffer[3] = 0; //(unsigned char)((distorsion >> 8) & 0x0F); // distorsion threshold bit 8-11 | ||
1654 | distorsion = 0 + 43 * usbvision->comprLevel / 100; | ||
1655 | buffer[4] = (unsigned char)(distorsion & 0xFF); // maximum distorsion bit0-7 | ||
1656 | buffer[5] = 0; //(unsigned char)((distorsion >> 8) & 0x01); // maximum distorsion bit 8 | ||
1657 | } | ||
1658 | errCode = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6); | ||
1659 | if (errCode == 0){ | ||
1660 | PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0], | ||
1661 | buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); | ||
1662 | usbvision->lastComprLevel = usbvision->comprLevel; | ||
1663 | } | ||
1664 | } | ||
1665 | } | ||
1666 | return errCode; | ||
1667 | } | ||
1668 | |||
1669 | static int usbvision_request_intra (struct usb_usbvision *usbvision) | ||
1670 | { | ||
1671 | int errCode = 0; | ||
1672 | unsigned char buffer[1]; | ||
1673 | |||
1674 | PDEBUG(DBG_IRQ, ""); | ||
1675 | usbvision->requestIntra = 1; | ||
1676 | buffer[0] = 1; | ||
1677 | usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); | ||
1678 | return errCode; | ||
1679 | } | ||
1680 | |||
1681 | static int usbvision_unrequest_intra (struct usb_usbvision *usbvision) | ||
1682 | { | ||
1683 | int errCode = 0; | ||
1684 | unsigned char buffer[1]; | ||
1685 | |||
1686 | PDEBUG(DBG_IRQ, ""); | ||
1687 | usbvision->requestIntra = 0; | ||
1688 | buffer[0] = 0; | ||
1689 | usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); | ||
1690 | return errCode; | ||
1691 | } | ||
1692 | |||
1693 | /******************************* | ||
1694 | * usbvision utility functions | ||
1695 | *******************************/ | ||
1696 | |||
1697 | int usbvision_power_off(struct usb_usbvision *usbvision) | ||
1698 | { | ||
1699 | int errCode = 0; | ||
1700 | |||
1701 | PDEBUG(DBG_FUNC, ""); | ||
1702 | |||
1703 | errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); | ||
1704 | if (errCode == 1) { | ||
1705 | usbvision->power = 0; | ||
1706 | } | ||
1707 | PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode!=1)?"ERROR":"power is off", errCode); | ||
1708 | return errCode; | ||
1709 | } | ||
1710 | |||
1711 | /* | ||
1712 | * usbvision_set_video_format() | ||
1713 | * | ||
1714 | */ | ||
1715 | static int usbvision_set_video_format(struct usb_usbvision *usbvision, int format) | ||
1716 | { | ||
1717 | static const char proc[] = "usbvision_set_video_format"; | ||
1718 | int rc; | ||
1719 | unsigned char value[2]; | ||
1720 | |||
1721 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1722 | return 0; | ||
1723 | |||
1724 | PDEBUG(DBG_FUNC, "isocMode %#02x", format); | ||
1725 | |||
1726 | if ((format != ISOC_MODE_YUV422) | ||
1727 | && (format != ISOC_MODE_YUV420) | ||
1728 | && (format != ISOC_MODE_COMPRESS)) { | ||
1729 | printk(KERN_ERR "usbvision: unknown video format %02x, using default YUV420", | ||
1730 | format); | ||
1731 | format = ISOC_MODE_YUV420; | ||
1732 | } | ||
1733 | value[0] = 0x0A; //TODO: See the effect of the filter | ||
1734 | value[1] = format; | ||
1735 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1736 | USBVISION_OP_CODE, | ||
1737 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1738 | USB_RECIP_ENDPOINT, 0, | ||
1739 | (__u16) USBVISION_FILT_CONT, value, 2, HZ); | ||
1740 | |||
1741 | if (rc < 0) { | ||
1742 | printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - " | ||
1743 | "reconnect or reload driver.\n", proc, rc); | ||
1744 | } | ||
1745 | usbvision->isocMode = format; | ||
1746 | return rc; | ||
1747 | } | ||
1748 | |||
1749 | /* | ||
1750 | * usbvision_set_output() | ||
1751 | * | ||
1752 | */ | ||
1753 | |||
1754 | int usbvision_set_output(struct usb_usbvision *usbvision, int width, | ||
1755 | int height) | ||
1756 | { | ||
1757 | int errCode = 0; | ||
1758 | int UsbWidth, UsbHeight; | ||
1759 | unsigned int frameRate=0, frameDrop=0; | ||
1760 | unsigned char value[4]; | ||
1761 | |||
1762 | if (!USBVISION_IS_OPERATIONAL(usbvision)) { | ||
1763 | return 0; | ||
1764 | } | ||
1765 | |||
1766 | if (width > MAX_USB_WIDTH) { | ||
1767 | UsbWidth = width / 2; | ||
1768 | usbvision->stretch_width = 2; | ||
1769 | } | ||
1770 | else { | ||
1771 | UsbWidth = width; | ||
1772 | usbvision->stretch_width = 1; | ||
1773 | } | ||
1774 | |||
1775 | if (height > MAX_USB_HEIGHT) { | ||
1776 | UsbHeight = height / 2; | ||
1777 | usbvision->stretch_height = 2; | ||
1778 | } | ||
1779 | else { | ||
1780 | UsbHeight = height; | ||
1781 | usbvision->stretch_height = 1; | ||
1782 | } | ||
1783 | |||
1784 | RESTRICT_TO_RANGE(UsbWidth, MIN_FRAME_WIDTH, MAX_USB_WIDTH); | ||
1785 | UsbWidth &= ~(MIN_FRAME_WIDTH-1); | ||
1786 | RESTRICT_TO_RANGE(UsbHeight, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT); | ||
1787 | UsbHeight &= ~(1); | ||
1788 | |||
1789 | PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d", | ||
1790 | UsbWidth, UsbHeight, width, height, | ||
1791 | usbvision->stretch_width, usbvision->stretch_height); | ||
1792 | |||
1793 | /* I'll not rewrite the same values */ | ||
1794 | if ((UsbWidth != usbvision->curwidth) || (UsbHeight != usbvision->curheight)) { | ||
1795 | value[0] = UsbWidth & 0xff; //LSB | ||
1796 | value[1] = (UsbWidth >> 8) & 0x03; //MSB | ||
1797 | value[2] = UsbHeight & 0xff; //LSB | ||
1798 | value[3] = (UsbHeight >> 8) & 0x03; //MSB | ||
1799 | |||
1800 | errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1801 | USBVISION_OP_CODE, | ||
1802 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, | ||
1803 | 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ); | ||
1804 | |||
1805 | if (errCode < 0) { | ||
1806 | err("%s failed: error %d", __FUNCTION__, errCode); | ||
1807 | return errCode; | ||
1808 | } | ||
1809 | usbvision->curwidth = usbvision->stretch_width * UsbWidth; | ||
1810 | usbvision->curheight = usbvision->stretch_height * UsbHeight; | ||
1811 | } | ||
1812 | |||
1813 | if (usbvision->isocMode == ISOC_MODE_YUV422) { | ||
1814 | frameRate = (usbvision->isocPacketSize * 1000) / (UsbWidth * UsbHeight * 2); | ||
1815 | } | ||
1816 | else if (usbvision->isocMode == ISOC_MODE_YUV420) { | ||
1817 | frameRate = (usbvision->isocPacketSize * 1000) / ((UsbWidth * UsbHeight * 12) / 8); | ||
1818 | } | ||
1819 | else { | ||
1820 | frameRate = FRAMERATE_MAX; | ||
1821 | } | ||
1822 | |||
1823 | if (usbvision->tvnorm->id & V4L2_STD_625_50) { | ||
1824 | frameDrop = frameRate * 32 / 25 - 1; | ||
1825 | } | ||
1826 | else if (usbvision->tvnorm->id & V4L2_STD_525_60) { | ||
1827 | frameDrop = frameRate * 32 / 30 - 1; | ||
1828 | } | ||
1829 | |||
1830 | RESTRICT_TO_RANGE(frameDrop, FRAMERATE_MIN, FRAMERATE_MAX); | ||
1831 | |||
1832 | PDEBUG(DBG_FUNC, "frameRate %d fps, frameDrop %d", frameRate, frameDrop); | ||
1833 | |||
1834 | frameDrop = FRAMERATE_MAX; // We can allow the maximum here, because dropping is controlled | ||
1835 | |||
1836 | /* frameDrop = 7; => framePhase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... | ||
1837 | => frameSkip = 4; | ||
1838 | => frameRate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; | ||
1839 | |||
1840 | frameDrop = 9; => framePhase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ... | ||
1841 | => frameSkip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ... | ||
1842 | => frameRate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125; | ||
1843 | */ | ||
1844 | errCode = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frameDrop); | ||
1845 | return errCode; | ||
1846 | } | ||
1847 | |||
1848 | |||
1849 | /* | ||
1850 | * usbvision_frames_alloc | ||
1851 | * allocate the maximum frames this driver can manage | ||
1852 | */ | ||
1853 | int usbvision_frames_alloc(struct usb_usbvision *usbvision) | ||
1854 | { | ||
1855 | int i; | ||
1856 | |||
1857 | /* Allocate memory for the frame buffers */ | ||
1858 | usbvision->max_frame_size = MAX_FRAME_SIZE; | ||
1859 | usbvision->fbuf_size = USBVISION_NUMFRAMES * usbvision->max_frame_size; | ||
1860 | usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size); | ||
1861 | |||
1862 | if(usbvision->fbuf == NULL) { | ||
1863 | err("%s: unable to allocate %d bytes for fbuf ", | ||
1864 | __FUNCTION__, usbvision->fbuf_size); | ||
1865 | return -ENOMEM; | ||
1866 | } | ||
1867 | spin_lock_init(&usbvision->queue_lock); | ||
1868 | init_waitqueue_head(&usbvision->wait_frame); | ||
1869 | init_waitqueue_head(&usbvision->wait_stream); | ||
1870 | |||
1871 | /* Allocate all buffers */ | ||
1872 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | ||
1873 | usbvision->frame[i].index = i; | ||
1874 | usbvision->frame[i].grabstate = FrameState_Unused; | ||
1875 | usbvision->frame[i].data = usbvision->fbuf + | ||
1876 | i * usbvision->max_frame_size; | ||
1877 | /* | ||
1878 | * Set default sizes for read operation. | ||
1879 | */ | ||
1880 | usbvision->stretch_width = 1; | ||
1881 | usbvision->stretch_height = 1; | ||
1882 | usbvision->frame[i].width = usbvision->curwidth; | ||
1883 | usbvision->frame[i].height = usbvision->curheight; | ||
1884 | usbvision->frame[i].bytes_read = 0; | ||
1885 | } | ||
1886 | return 0; | ||
1887 | } | ||
1888 | |||
1889 | /* | ||
1890 | * usbvision_frames_free | ||
1891 | * frees memory allocated for the frames | ||
1892 | */ | ||
1893 | void usbvision_frames_free(struct usb_usbvision *usbvision) | ||
1894 | { | ||
1895 | /* Have to free all that memory */ | ||
1896 | if (usbvision->fbuf != NULL) { | ||
1897 | usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); | ||
1898 | usbvision->fbuf = NULL; | ||
1899 | } | ||
1900 | } | ||
1901 | /* | ||
1902 | * usbvision_empty_framequeues() | ||
1903 | * prepare queues for incoming and outgoing frames | ||
1904 | */ | ||
1905 | void usbvision_empty_framequeues(struct usb_usbvision *usbvision) | ||
1906 | { | ||
1907 | u32 i; | ||
1908 | |||
1909 | INIT_LIST_HEAD(&(usbvision->inqueue)); | ||
1910 | INIT_LIST_HEAD(&(usbvision->outqueue)); | ||
1911 | |||
1912 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | ||
1913 | usbvision->frame[i].grabstate = FrameState_Unused; | ||
1914 | usbvision->frame[i].bytes_read = 0; | ||
1915 | } | ||
1916 | } | ||
1917 | |||
1918 | /* | ||
1919 | * usbvision_stream_interrupt() | ||
1920 | * stops streaming | ||
1921 | */ | ||
1922 | int usbvision_stream_interrupt(struct usb_usbvision *usbvision) | ||
1923 | { | ||
1924 | int ret = 0; | ||
1925 | |||
1926 | /* stop reading from the device */ | ||
1927 | |||
1928 | usbvision->streaming = Stream_Interrupt; | ||
1929 | ret = wait_event_timeout(usbvision->wait_stream, | ||
1930 | (usbvision->streaming == Stream_Idle), | ||
1931 | msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES)); | ||
1932 | return ret; | ||
1933 | } | ||
1934 | |||
1935 | /* | ||
1936 | * usbvision_set_compress_params() | ||
1937 | * | ||
1938 | */ | ||
1939 | |||
1940 | static int usbvision_set_compress_params(struct usb_usbvision *usbvision) | ||
1941 | { | ||
1942 | static const char proc[] = "usbvision_set_compresion_params: "; | ||
1943 | int rc; | ||
1944 | unsigned char value[6]; | ||
1945 | |||
1946 | value[0] = 0x0F; // Intra-Compression cycle | ||
1947 | value[1] = 0x01; // Reg.45 one line per strip | ||
1948 | value[2] = 0x00; // Reg.46 Force intra mode on all new frames | ||
1949 | value[3] = 0x00; // Reg.47 FORCE_UP <- 0 normal operation (not force) | ||
1950 | value[4] = 0xA2; // Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. | ||
1951 | value[5] = 0x00; // Reg.49 DVI_YUV This has nothing to do with compression | ||
1952 | |||
1953 | //catched values for NT1004 | ||
1954 | // value[0] = 0xFF; // Never apply intra mode automatically | ||
1955 | // value[1] = 0xF1; // Use full frame height for virtual strip width; One line per strip | ||
1956 | // value[2] = 0x01; // Force intra mode on all new frames | ||
1957 | // value[3] = 0x00; // Strip size 400 Bytes; do not force up | ||
1958 | // value[4] = 0xA2; // | ||
1959 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1960 | return 0; | ||
1961 | |||
1962 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1963 | USBVISION_OP_CODE, | ||
1964 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1965 | USB_RECIP_ENDPOINT, 0, | ||
1966 | (__u16) USBVISION_INTRA_CYC, value, 5, HZ); | ||
1967 | |||
1968 | if (rc < 0) { | ||
1969 | printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " | ||
1970 | "reconnect or reload driver.\n", proc, rc); | ||
1971 | return rc; | ||
1972 | } | ||
1973 | |||
1974 | if (usbvision->bridgeType == BRIDGE_NT1004) { | ||
1975 | value[0] = 20; // PCM Threshold 1 | ||
1976 | value[1] = 12; // PCM Threshold 2 | ||
1977 | value[2] = 255; // Distorsion Threshold inter | ||
1978 | value[3] = 255; // Distorsion Threshold intra | ||
1979 | value[4] = 43; // Max Distorsion inter | ||
1980 | value[5] = 43; // Max Distorsion intra | ||
1981 | } | ||
1982 | else { | ||
1983 | value[0] = 20; // PCM Threshold 1 | ||
1984 | value[1] = 12; // PCM Threshold 2 | ||
1985 | value[2] = 255; // Distorsion Threshold d7-d0 | ||
1986 | value[3] = 0; // Distorsion Threshold d11-d8 | ||
1987 | value[4] = 43; // Max Distorsion d7-d0 | ||
1988 | value[5] = 0; // Max Distorsion d8 | ||
1989 | } | ||
1990 | |||
1991 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1992 | return 0; | ||
1993 | |||
1994 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
1995 | USBVISION_OP_CODE, | ||
1996 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1997 | USB_RECIP_ENDPOINT, 0, | ||
1998 | (__u16) USBVISION_PCM_THR1, value, 6, HZ); | ||
1999 | |||
2000 | if (rc < 0) { | ||
2001 | printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " | ||
2002 | "reconnect or reload driver.\n", proc, rc); | ||
2003 | return rc; | ||
2004 | } | ||
2005 | |||
2006 | |||
2007 | return rc; | ||
2008 | } | ||
2009 | |||
2010 | |||
2011 | /* | ||
2012 | * usbvision_set_input() | ||
2013 | * | ||
2014 | * Set the input (saa711x, ...) size x y and other misc input params | ||
2015 | * I've no idea if this parameters are right | ||
2016 | * | ||
2017 | */ | ||
2018 | int usbvision_set_input(struct usb_usbvision *usbvision) | ||
2019 | { | ||
2020 | static const char proc[] = "usbvision_set_input: "; | ||
2021 | int rc; | ||
2022 | unsigned char value[8]; | ||
2023 | unsigned char dvi_yuv_value; | ||
2024 | |||
2025 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
2026 | return 0; | ||
2027 | |||
2028 | /* Set input format expected from decoder*/ | ||
2029 | if (usbvision_device_data[usbvision->DevModel].Vin_Reg1 >= 0) { | ||
2030 | value[0] = usbvision_device_data[usbvision->DevModel].Vin_Reg1 & 0xff; | ||
2031 | } else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { | ||
2032 | /* SAA7113 uses 8 bit output */ | ||
2033 | value[0] = USBVISION_8_422_SYNC; | ||
2034 | } else { | ||
2035 | /* I'm sure only about d2-d0 [010] 16 bit 4:2:2 usin sync pulses | ||
2036 | * as that is how saa7111 is configured */ | ||
2037 | value[0] = USBVISION_16_422_SYNC; | ||
2038 | /* | USBVISION_VSNC_POL | USBVISION_VCLK_POL);*/ | ||
2039 | } | ||
2040 | |||
2041 | rc = usbvision_write_reg(usbvision, USBVISION_VIN_REG1, value[0]); | ||
2042 | if (rc < 0) { | ||
2043 | printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " | ||
2044 | "reconnect or reload driver.\n", proc, rc); | ||
2045 | return rc; | ||
2046 | } | ||
2047 | |||
2048 | |||
2049 | if (usbvision->tvnorm->id & V4L2_STD_PAL) { | ||
2050 | value[0] = 0xC0; | ||
2051 | value[1] = 0x02; //0x02C0 -> 704 Input video line length | ||
2052 | value[2] = 0x20; | ||
2053 | value[3] = 0x01; //0x0120 -> 288 Input video n. of lines | ||
2054 | value[4] = 0x60; | ||
2055 | value[5] = 0x00; //0x0060 -> 96 Input video h offset | ||
2056 | value[6] = 0x16; | ||
2057 | value[7] = 0x00; //0x0016 -> 22 Input video v offset | ||
2058 | } else if (usbvision->tvnorm->id & V4L2_STD_SECAM) { | ||
2059 | value[0] = 0xC0; | ||
2060 | value[1] = 0x02; //0x02C0 -> 704 Input video line length | ||
2061 | value[2] = 0x20; | ||
2062 | value[3] = 0x01; //0x0120 -> 288 Input video n. of lines | ||
2063 | value[4] = 0x01; | ||
2064 | value[5] = 0x00; //0x0001 -> 01 Input video h offset | ||
2065 | value[6] = 0x01; | ||
2066 | value[7] = 0x00; //0x0001 -> 01 Input video v offset | ||
2067 | } else { /* V4L2_STD_NTSC */ | ||
2068 | value[0] = 0xD0; | ||
2069 | value[1] = 0x02; //0x02D0 -> 720 Input video line length | ||
2070 | value[2] = 0xF0; | ||
2071 | value[3] = 0x00; //0x00F0 -> 240 Input video number of lines | ||
2072 | value[4] = 0x50; | ||
2073 | value[5] = 0x00; //0x0050 -> 80 Input video h offset | ||
2074 | value[6] = 0x10; | ||
2075 | value[7] = 0x00; //0x0010 -> 16 Input video v offset | ||
2076 | } | ||
2077 | |||
2078 | if (usbvision_device_data[usbvision->DevModel].X_Offset >= 0) { | ||
2079 | value[4]=usbvision_device_data[usbvision->DevModel].X_Offset & 0xff; | ||
2080 | value[5]=(usbvision_device_data[usbvision->DevModel].X_Offset & 0x0300) >> 8; | ||
2081 | } | ||
2082 | |||
2083 | if (usbvision_device_data[usbvision->DevModel].Y_Offset >= 0) { | ||
2084 | value[6]=usbvision_device_data[usbvision->DevModel].Y_Offset & 0xff; | ||
2085 | value[7]=(usbvision_device_data[usbvision->DevModel].Y_Offset & 0x0300) >> 8; | ||
2086 | } | ||
2087 | |||
2088 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
2089 | USBVISION_OP_CODE, /* USBVISION specific code */ | ||
2090 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, | ||
2091 | (__u16) USBVISION_LXSIZE_I, value, 8, HZ); | ||
2092 | if (rc < 0) { | ||
2093 | printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " | ||
2094 | "reconnect or reload driver.\n", proc, rc); | ||
2095 | return rc; | ||
2096 | } | ||
2097 | |||
2098 | |||
2099 | dvi_yuv_value = 0x00; /* U comes after V, Ya comes after U/V, Yb comes after Yb */ | ||
2100 | |||
2101 | if(usbvision_device_data[usbvision->DevModel].Dvi_yuv >= 0){ | ||
2102 | dvi_yuv_value = usbvision_device_data[usbvision->DevModel].Dvi_yuv & 0xff; | ||
2103 | } | ||
2104 | else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { | ||
2105 | /* This changes as the fine sync control changes. Further investigation necessary */ | ||
2106 | dvi_yuv_value = 0x06; | ||
2107 | } | ||
2108 | |||
2109 | return (usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value)); | ||
2110 | } | ||
2111 | |||
2112 | |||
2113 | /* | ||
2114 | * usbvision_set_dram_settings() | ||
2115 | * | ||
2116 | * Set the buffer address needed by the usbvision dram to operate | ||
2117 | * This values has been taken with usbsnoop. | ||
2118 | * | ||
2119 | */ | ||
2120 | |||
2121 | static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) | ||
2122 | { | ||
2123 | int rc; | ||
2124 | unsigned char value[8]; | ||
2125 | |||
2126 | if (usbvision->isocMode == ISOC_MODE_COMPRESS) { | ||
2127 | value[0] = 0x42; | ||
2128 | value[1] = 0x71; | ||
2129 | value[2] = 0xff; | ||
2130 | value[3] = 0x00; | ||
2131 | value[4] = 0x98; | ||
2132 | value[5] = 0xe0; | ||
2133 | value[6] = 0x71; | ||
2134 | value[7] = 0xff; | ||
2135 | // UR: 0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) | ||
2136 | // FDL: 0x00000-0x0E099 = 57498 Words | ||
2137 | // VDW: 0x0E3FF-0x3FFFF | ||
2138 | } | ||
2139 | else { | ||
2140 | value[0] = 0x42; | ||
2141 | value[1] = 0x00; | ||
2142 | value[2] = 0xff; | ||
2143 | value[3] = 0x00; | ||
2144 | value[4] = 0x00; | ||
2145 | value[5] = 0x00; | ||
2146 | value[6] = 0x00; | ||
2147 | value[7] = 0xff; | ||
2148 | } | ||
2149 | /* These are the values of the address of the video buffer, | ||
2150 | * they have to be loaded into the USBVISION_DRM_PRM1-8 | ||
2151 | * | ||
2152 | * Start address of video output buffer for read: drm_prm1-2 -> 0x00000 | ||
2153 | * End address of video output buffer for read: drm_prm1-3 -> 0x1ffff | ||
2154 | * Start address of video frame delay buffer: drm_prm1-4 -> 0x20000 | ||
2155 | * Only used in compressed mode | ||
2156 | * End address of video frame delay buffer: drm_prm1-5-6 -> 0x3ffff | ||
2157 | * Only used in compressed mode | ||
2158 | * Start address of video output buffer for write: drm_prm1-7 -> 0x00000 | ||
2159 | * End address of video output buffer for write: drm_prm1-8 -> 0x1ffff | ||
2160 | */ | ||
2161 | |||
2162 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
2163 | return 0; | ||
2164 | |||
2165 | rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), | ||
2166 | USBVISION_OP_CODE, /* USBVISION specific code */ | ||
2167 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
2168 | USB_RECIP_ENDPOINT, 0, | ||
2169 | (__u16) USBVISION_DRM_PRM1, value, 8, HZ); | ||
2170 | |||
2171 | if (rc < 0) { | ||
2172 | err("%sERROR=%d", __FUNCTION__, rc); | ||
2173 | return rc; | ||
2174 | } | ||
2175 | |||
2176 | /* Restart the video buffer logic */ | ||
2177 | if ((rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR | | ||
2178 | USBVISION_RES_FDL | USBVISION_RES_VDW)) < 0) | ||
2179 | return rc; | ||
2180 | rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00); | ||
2181 | |||
2182 | return rc; | ||
2183 | } | ||
2184 | |||
2185 | /* | ||
2186 | * () | ||
2187 | * | ||
2188 | * Power on the device, enables suspend-resume logic | ||
2189 | * & reset the isoc End-Point | ||
2190 | * | ||
2191 | */ | ||
2192 | |||
2193 | int usbvision_power_on(struct usb_usbvision *usbvision) | ||
2194 | { | ||
2195 | int errCode = 0; | ||
2196 | |||
2197 | PDEBUG(DBG_FUNC, ""); | ||
2198 | |||
2199 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); | ||
2200 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2201 | USBVISION_SSPND_EN | USBVISION_RES2); | ||
2202 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2203 | USBVISION_SSPND_EN | USBVISION_PWR_VID); | ||
2204 | errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2205 | USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); | ||
2206 | if (errCode == 1) { | ||
2207 | usbvision->power = 1; | ||
2208 | } | ||
2209 | PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode<0)?"ERROR":"power is on", errCode); | ||
2210 | return errCode; | ||
2211 | } | ||
2212 | |||
2213 | |||
2214 | /* | ||
2215 | * usbvision timer stuff | ||
2216 | */ | ||
2217 | |||
2218 | // to call usbvision_power_off from task queue | ||
2219 | static void call_usbvision_power_off(struct work_struct *work) | ||
2220 | { | ||
2221 | struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, powerOffWork); | ||
2222 | |||
2223 | PDEBUG(DBG_FUNC, ""); | ||
2224 | down_interruptible(&usbvision->lock); | ||
2225 | if(usbvision->user == 0) { | ||
2226 | usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); | ||
2227 | |||
2228 | usbvision_power_off(usbvision); | ||
2229 | usbvision->initialized = 0; | ||
2230 | } | ||
2231 | up(&usbvision->lock); | ||
2232 | } | ||
2233 | |||
2234 | static void usbvision_powerOffTimer(unsigned long data) | ||
2235 | { | ||
2236 | struct usb_usbvision *usbvision = (void *) data; | ||
2237 | |||
2238 | PDEBUG(DBG_FUNC, ""); | ||
2239 | del_timer(&usbvision->powerOffTimer); | ||
2240 | INIT_WORK(&usbvision->powerOffWork, call_usbvision_power_off); | ||
2241 | (void) schedule_work(&usbvision->powerOffWork); | ||
2242 | |||
2243 | } | ||
2244 | |||
2245 | void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision) | ||
2246 | { | ||
2247 | init_timer(&usbvision->powerOffTimer); | ||
2248 | usbvision->powerOffTimer.data = (long) usbvision; | ||
2249 | usbvision->powerOffTimer.function = usbvision_powerOffTimer; | ||
2250 | } | ||
2251 | |||
2252 | void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision) | ||
2253 | { | ||
2254 | mod_timer(&usbvision->powerOffTimer, jiffies + USBVISION_POWEROFF_TIME); | ||
2255 | } | ||
2256 | |||
2257 | void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision) | ||
2258 | { | ||
2259 | if (timer_pending(&usbvision->powerOffTimer)) { | ||
2260 | del_timer(&usbvision->powerOffTimer); | ||
2261 | } | ||
2262 | } | ||
2263 | |||
2264 | /* | ||
2265 | * usbvision_begin_streaming() | ||
2266 | * Sure you have to put bit 7 to 0, if not incoming frames are droped, but no | ||
2267 | * idea about the rest | ||
2268 | */ | ||
2269 | int usbvision_begin_streaming(struct usb_usbvision *usbvision) | ||
2270 | { | ||
2271 | int errCode = 0; | ||
2272 | |||
2273 | if (usbvision->isocMode == ISOC_MODE_COMPRESS) { | ||
2274 | usbvision_init_compression(usbvision); | ||
2275 | } | ||
2276 | errCode = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_NOHVALID | | ||
2277 | usbvision->Vin_Reg2_Preset); | ||
2278 | return errCode; | ||
2279 | } | ||
2280 | |||
2281 | /* | ||
2282 | * usbvision_restart_isoc() | ||
2283 | * Not sure yet if touching here PWR_REG make loose the config | ||
2284 | */ | ||
2285 | |||
2286 | int usbvision_restart_isoc(struct usb_usbvision *usbvision) | ||
2287 | { | ||
2288 | int ret; | ||
2289 | |||
2290 | if ( | ||
2291 | (ret = | ||
2292 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2293 | USBVISION_SSPND_EN | USBVISION_PWR_VID)) < 0) | ||
2294 | return ret; | ||
2295 | if ( | ||
2296 | (ret = | ||
2297 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | ||
2298 | USBVISION_SSPND_EN | USBVISION_PWR_VID | | ||
2299 | USBVISION_RES2)) < 0) | ||
2300 | return ret; | ||
2301 | if ( | ||
2302 | (ret = | ||
2303 | usbvision_write_reg(usbvision, USBVISION_VIN_REG2, | ||
2304 | USBVISION_KEEP_BLANK | USBVISION_NOHVALID | | ||
2305 | usbvision->Vin_Reg2_Preset)) < 0) return ret; | ||
2306 | |||
2307 | /* TODO: schedule timeout */ | ||
2308 | while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) && 0x01) != 1); | ||
2309 | |||
2310 | return 0; | ||
2311 | } | ||
2312 | |||
2313 | int usbvision_audio_off(struct usb_usbvision *usbvision) | ||
2314 | { | ||
2315 | if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_AUDIO_MUTE) < 0) { | ||
2316 | printk(KERN_ERR "usbvision_audio_off: can't wirte reg\n"); | ||
2317 | return -1; | ||
2318 | } | ||
2319 | usbvision->AudioMute = 0; | ||
2320 | usbvision->AudioChannel = USBVISION_AUDIO_MUTE; | ||
2321 | return 0; | ||
2322 | } | ||
2323 | |||
2324 | int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel) | ||
2325 | { | ||
2326 | if (!usbvision->AudioMute) { | ||
2327 | if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, AudioChannel) < 0) { | ||
2328 | printk(KERN_ERR "usbvision_set_audio: can't write iopin register for audio switching\n"); | ||
2329 | return -1; | ||
2330 | } | ||
2331 | } | ||
2332 | usbvision->AudioChannel = AudioChannel; | ||
2333 | return 0; | ||
2334 | } | ||
2335 | |||
2336 | int usbvision_setup(struct usb_usbvision *usbvision,int format) | ||
2337 | { | ||
2338 | usbvision_set_video_format(usbvision, format); | ||
2339 | usbvision_set_dram_settings(usbvision); | ||
2340 | usbvision_set_compress_params(usbvision); | ||
2341 | usbvision_set_input(usbvision); | ||
2342 | usbvision_set_output(usbvision, MAX_USB_WIDTH, MAX_USB_HEIGHT); | ||
2343 | usbvision_restart_isoc(usbvision); | ||
2344 | |||
2345 | /* cosas del PCM */ | ||
2346 | return USBVISION_IS_OPERATIONAL(usbvision); | ||
2347 | } | ||
2348 | |||
2349 | |||
2350 | int usbvision_sbuf_alloc(struct usb_usbvision *usbvision) | ||
2351 | { | ||
2352 | int i, errCode = 0; | ||
2353 | const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE; | ||
2354 | |||
2355 | /* Clean pointers so we know if we allocated something */ | ||
2356 | for (i = 0; i < USBVISION_NUMSBUF; i++) | ||
2357 | usbvision->sbuf[i].data = NULL; | ||
2358 | |||
2359 | for (i = 0; i < USBVISION_NUMSBUF; i++) { | ||
2360 | usbvision->sbuf[i].data = kzalloc(sb_size, GFP_KERNEL); | ||
2361 | if (usbvision->sbuf[i].data == NULL) { | ||
2362 | err("%s: unable to allocate %d bytes for sbuf", __FUNCTION__, sb_size); | ||
2363 | errCode = -ENOMEM; | ||
2364 | break; | ||
2365 | } | ||
2366 | } | ||
2367 | return errCode; | ||
2368 | } | ||
2369 | |||
2370 | |||
2371 | void usbvision_sbuf_free(struct usb_usbvision *usbvision) | ||
2372 | { | ||
2373 | int i; | ||
2374 | |||
2375 | for (i = 0; i < USBVISION_NUMSBUF; i++) { | ||
2376 | if (usbvision->sbuf[i].data != NULL) { | ||
2377 | kfree(usbvision->sbuf[i].data); | ||
2378 | usbvision->sbuf[i].data = NULL; | ||
2379 | } | ||
2380 | } | ||
2381 | } | ||
2382 | |||
2383 | /* | ||
2384 | * usbvision_init_isoc() | ||
2385 | * | ||
2386 | */ | ||
2387 | int usbvision_init_isoc(struct usb_usbvision *usbvision) | ||
2388 | { | ||
2389 | struct usb_device *dev = usbvision->dev; | ||
2390 | int bufIdx, errCode, regValue; | ||
2391 | |||
2392 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
2393 | return -EFAULT; | ||
2394 | |||
2395 | usbvision->curFrame = NULL; | ||
2396 | scratch_reset(usbvision); | ||
2397 | |||
2398 | /* Alternate interface 1 is is the biggest frame size */ | ||
2399 | errCode = usb_set_interface(dev, usbvision->iface, usbvision->ifaceAltActive); | ||
2400 | if (errCode < 0) { | ||
2401 | usbvision->last_error = errCode; | ||
2402 | return -EBUSY; | ||
2403 | } | ||
2404 | |||
2405 | regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; | ||
2406 | usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1; | ||
2407 | PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize); | ||
2408 | |||
2409 | usbvision->usb_bandwidth = regValue >> 1; | ||
2410 | PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); | ||
2411 | |||
2412 | |||
2413 | |||
2414 | /* We double buffer the Iso lists */ | ||
2415 | |||
2416 | for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { | ||
2417 | int j, k; | ||
2418 | struct urb *urb; | ||
2419 | |||
2420 | urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); | ||
2421 | if (urb == NULL) { | ||
2422 | err("%s: usb_alloc_urb() failed", __FUNCTION__); | ||
2423 | return -ENOMEM; | ||
2424 | } | ||
2425 | usbvision->sbuf[bufIdx].urb = urb; | ||
2426 | urb->dev = dev; | ||
2427 | urb->context = usbvision; | ||
2428 | urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); | ||
2429 | urb->transfer_flags = URB_ISO_ASAP; | ||
2430 | urb->interval = 1; | ||
2431 | urb->transfer_buffer = usbvision->sbuf[bufIdx].data; | ||
2432 | urb->complete = usbvision_isocIrq; | ||
2433 | urb->number_of_packets = USBVISION_URB_FRAMES; | ||
2434 | urb->transfer_buffer_length = | ||
2435 | usbvision->isocPacketSize * USBVISION_URB_FRAMES; | ||
2436 | for (j = k = 0; j < USBVISION_URB_FRAMES; j++, | ||
2437 | k += usbvision->isocPacketSize) { | ||
2438 | urb->iso_frame_desc[j].offset = k; | ||
2439 | urb->iso_frame_desc[j].length = usbvision->isocPacketSize; | ||
2440 | } | ||
2441 | } | ||
2442 | |||
2443 | |||
2444 | /* Submit all URBs */ | ||
2445 | for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { | ||
2446 | errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL); | ||
2447 | if (errCode) { | ||
2448 | err("%s: usb_submit_urb(%d) failed: error %d", __FUNCTION__, bufIdx, errCode); | ||
2449 | } | ||
2450 | } | ||
2451 | |||
2452 | usbvision->streaming = Stream_Idle; | ||
2453 | PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp); | ||
2454 | return 0; | ||
2455 | } | ||
2456 | |||
2457 | /* | ||
2458 | * usbvision_stop_isoc() | ||
2459 | * | ||
2460 | * This procedure stops streaming and deallocates URBs. Then it | ||
2461 | * activates zero-bandwidth alt. setting of the video interface. | ||
2462 | * | ||
2463 | */ | ||
2464 | void usbvision_stop_isoc(struct usb_usbvision *usbvision) | ||
2465 | { | ||
2466 | int bufIdx, errCode, regValue; | ||
2467 | |||
2468 | if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL)) | ||
2469 | return; | ||
2470 | |||
2471 | /* Unschedule all of the iso td's */ | ||
2472 | for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { | ||
2473 | usb_kill_urb(usbvision->sbuf[bufIdx].urb); | ||
2474 | usb_free_urb(usbvision->sbuf[bufIdx].urb); | ||
2475 | usbvision->sbuf[bufIdx].urb = NULL; | ||
2476 | } | ||
2477 | |||
2478 | |||
2479 | PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__); | ||
2480 | usbvision->streaming = Stream_Off; | ||
2481 | |||
2482 | if (!usbvision->remove_pending) { | ||
2483 | |||
2484 | /* Set packet size to 0 */ | ||
2485 | errCode = usb_set_interface(usbvision->dev, usbvision->iface, | ||
2486 | usbvision->ifaceAltInactive); | ||
2487 | if (errCode < 0) { | ||
2488 | err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode); | ||
2489 | usbvision->last_error = errCode; | ||
2490 | } | ||
2491 | regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; | ||
2492 | usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1; | ||
2493 | PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize); | ||
2494 | |||
2495 | usbvision->usb_bandwidth = regValue >> 1; | ||
2496 | PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); | ||
2497 | } | ||
2498 | } | ||
2499 | |||
2500 | int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) | ||
2501 | { | ||
2502 | int mode[4]; | ||
2503 | int audio[]= {1, 0, 0, 0}; | ||
2504 | struct v4l2_routing route; | ||
2505 | //channel 0 is TV with audiochannel 1 (tuner mono) | ||
2506 | //channel 1 is Composite with audio channel 0 (line in) | ||
2507 | //channel 2 is S-Video with audio channel 0 (line in) | ||
2508 | //channel 3 is additional video inputs to the device with audio channel 0 (line in) | ||
2509 | |||
2510 | RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); | ||
2511 | usbvision->ctl_input = channel; | ||
2512 | route.input = SAA7115_COMPOSITE1; | ||
2513 | call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); | ||
2514 | call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input); | ||
2515 | |||
2516 | // set the new channel | ||
2517 | // Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video | ||
2518 | // Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red | ||
2519 | |||
2520 | switch (usbvision_device_data[usbvision->DevModel].Codec) { | ||
2521 | case CODEC_SAA7113: | ||
2522 | if (SwitchSVideoInput) { // To handle problems with S-Video Input for some devices. Use SwitchSVideoInput parameter when loading the module. | ||
2523 | mode[2] = 1; | ||
2524 | } | ||
2525 | else { | ||
2526 | mode[2] = 7; | ||
2527 | } | ||
2528 | if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { | ||
2529 | mode[0] = 0; mode[1] = 2; mode[3] = 3; // Special for four input devices | ||
2530 | } | ||
2531 | else { | ||
2532 | mode[0] = 0; mode[1] = 2; //modes for regular saa7113 devices | ||
2533 | } | ||
2534 | break; | ||
2535 | case CODEC_SAA7111: | ||
2536 | mode[0] = 0; mode[1] = 1; mode[2] = 7; //modes for saa7111 | ||
2537 | break; | ||
2538 | default: | ||
2539 | mode[0] = 0; mode[1] = 1; mode[2] = 7; //default modes | ||
2540 | } | ||
2541 | route.input = mode[channel]; | ||
2542 | call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); | ||
2543 | usbvision->channel = channel; | ||
2544 | usbvision_set_audio(usbvision, audio[channel]); | ||
2545 | return 0; | ||
2546 | } | ||
2547 | |||
2548 | /* | ||
2549 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
2550 | * --------------------------------------------------------------------------- | ||
2551 | * Local variables: | ||
2552 | * c-basic-offset: 8 | ||
2553 | * End: | ||
2554 | */ | ||
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c new file mode 100644 index 000000000000..92bf9a1f1e2c --- /dev/null +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -0,0 +1,567 @@ | |||
1 | /* | ||
2 | * I2C_ALGO_USB.C | ||
3 | * i2c algorithm for USB-I2C Bridges | ||
4 | * | ||
5 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
6 | * Dwaine Garden <dwainegarden@rogers.com> | ||
7 | * | ||
8 | * This module is part of usbvision driver project. | ||
9 | * Updates to driver completed by Dwaine P. Garden | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/version.h> | ||
32 | #include <linux/utsname.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <asm/uaccess.h> | ||
35 | #include <linux/ioport.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/usb.h> | ||
39 | #include <linux/i2c.h> | ||
40 | #include "usbvision.h" | ||
41 | |||
42 | #define DBG_I2C 1<<0 | ||
43 | #define DBG_ALGO 1<<1 | ||
44 | |||
45 | static int i2c_debug = 0; | ||
46 | |||
47 | module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver | ||
48 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | ||
49 | |||
50 | #define PDEBUG(level, fmt, args...) \ | ||
51 | if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) | ||
52 | |||
53 | static inline int try_write_address(struct i2c_adapter *i2c_adap, | ||
54 | unsigned char addr, int retries) | ||
55 | { | ||
56 | struct i2c_algo_usb_data *adap = i2c_adap->algo_data; | ||
57 | void *data; | ||
58 | int i, ret = -1; | ||
59 | char buf[4]; | ||
60 | |||
61 | data = i2c_get_adapdata(i2c_adap); | ||
62 | buf[0] = 0x00; | ||
63 | for (i = 0; i <= retries; i++) { | ||
64 | ret = (adap->outb(data, addr, buf, 1)); | ||
65 | if (ret == 1) | ||
66 | break; /* success! */ | ||
67 | udelay(5 /*adap->udelay */ ); | ||
68 | if (i == retries) /* no success */ | ||
69 | break; | ||
70 | udelay(adap->udelay); | ||
71 | } | ||
72 | if (i) { | ||
73 | PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr); | ||
74 | PDEBUG(DBG_ALGO,"Maybe there's no device at this address"); | ||
75 | } | ||
76 | return ret; | ||
77 | } | ||
78 | |||
79 | static inline int try_read_address(struct i2c_adapter *i2c_adap, | ||
80 | unsigned char addr, int retries) | ||
81 | { | ||
82 | struct i2c_algo_usb_data *adap = i2c_adap->algo_data; | ||
83 | void *data; | ||
84 | int i, ret = -1; | ||
85 | char buf[4]; | ||
86 | |||
87 | data = i2c_get_adapdata(i2c_adap); | ||
88 | for (i = 0; i <= retries; i++) { | ||
89 | ret = (adap->inb(data, addr, buf, 1)); | ||
90 | if (ret == 1) | ||
91 | break; /* success! */ | ||
92 | udelay(5 /*adap->udelay */ ); | ||
93 | if (i == retries) /* no success */ | ||
94 | break; | ||
95 | udelay(adap->udelay); | ||
96 | } | ||
97 | if (i) { | ||
98 | PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr); | ||
99 | PDEBUG(DBG_ALGO,"Maybe there's no device at this address"); | ||
100 | } | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static inline int usb_find_address(struct i2c_adapter *i2c_adap, | ||
105 | struct i2c_msg *msg, int retries, | ||
106 | unsigned char *add) | ||
107 | { | ||
108 | unsigned short flags = msg->flags; | ||
109 | |||
110 | unsigned char addr; | ||
111 | int ret; | ||
112 | if ((flags & I2C_M_TEN)) { | ||
113 | /* a ten bit address */ | ||
114 | addr = 0xf0 | ((msg->addr >> 7) & 0x03); | ||
115 | /* try extended address code... */ | ||
116 | ret = try_write_address(i2c_adap, addr, retries); | ||
117 | if (ret != 1) { | ||
118 | err("died at extended address code, while writing"); | ||
119 | return -EREMOTEIO; | ||
120 | } | ||
121 | add[0] = addr; | ||
122 | if (flags & I2C_M_RD) { | ||
123 | /* okay, now switch into reading mode */ | ||
124 | addr |= 0x01; | ||
125 | ret = try_read_address(i2c_adap, addr, retries); | ||
126 | if (ret != 1) { | ||
127 | err("died at extended address code, while reading"); | ||
128 | return -EREMOTEIO; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | } else { /* normal 7bit address */ | ||
133 | addr = (msg->addr << 1); | ||
134 | if (flags & I2C_M_RD) | ||
135 | addr |= 1; | ||
136 | if (flags & I2C_M_REV_DIR_ADDR) | ||
137 | addr ^= 1; | ||
138 | |||
139 | add[0] = addr; | ||
140 | if (flags & I2C_M_RD) | ||
141 | ret = try_read_address(i2c_adap, addr, retries); | ||
142 | else | ||
143 | ret = try_write_address(i2c_adap, addr, retries); | ||
144 | |||
145 | if (ret != 1) { | ||
146 | return -EREMOTEIO; | ||
147 | } | ||
148 | } | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int | ||
153 | usb_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) | ||
154 | { | ||
155 | struct i2c_msg *pmsg; | ||
156 | struct i2c_algo_usb_data *adap = i2c_adap->algo_data; | ||
157 | void *data; | ||
158 | int i, ret; | ||
159 | unsigned char addr; | ||
160 | |||
161 | data = i2c_get_adapdata(i2c_adap); | ||
162 | |||
163 | for (i = 0; i < num; i++) { | ||
164 | pmsg = &msgs[i]; | ||
165 | ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr); | ||
166 | if (ret != 0) { | ||
167 | PDEBUG(DBG_ALGO,"got NAK from device, message #%d", i); | ||
168 | return (ret < 0) ? ret : -EREMOTEIO; | ||
169 | } | ||
170 | |||
171 | if (pmsg->flags & I2C_M_RD) { | ||
172 | /* read bytes into buffer */ | ||
173 | ret = (adap->inb(data, addr, pmsg->buf, pmsg->len)); | ||
174 | if (ret < pmsg->len) { | ||
175 | return (ret < 0) ? ret : -EREMOTEIO; | ||
176 | } | ||
177 | } else { | ||
178 | /* write bytes from buffer */ | ||
179 | ret = (adap->outb(data, addr, pmsg->buf, pmsg->len)); | ||
180 | if (ret < pmsg->len) { | ||
181 | return (ret < 0) ? ret : -EREMOTEIO; | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | return num; | ||
186 | } | ||
187 | |||
188 | static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg) | ||
189 | { | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static u32 usb_func(struct i2c_adapter *adap) | ||
194 | { | ||
195 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; | ||
196 | } | ||
197 | |||
198 | |||
199 | /* -----exported algorithm data: ------------------------------------- */ | ||
200 | |||
201 | static struct i2c_algorithm i2c_usb_algo = { | ||
202 | .master_xfer = usb_xfer, | ||
203 | .smbus_xfer = NULL, | ||
204 | .algo_control = algo_control, | ||
205 | .functionality = usb_func, | ||
206 | }; | ||
207 | |||
208 | |||
209 | /* | ||
210 | * registering functions to load algorithms at runtime | ||
211 | */ | ||
212 | int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap) | ||
213 | { | ||
214 | PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]"); | ||
215 | PDEBUG(DBG_ALGO, "ALGO debugging is enabled [i2c]"); | ||
216 | |||
217 | /* register new adapter to i2c module... */ | ||
218 | |||
219 | adap->algo = &i2c_usb_algo; | ||
220 | |||
221 | adap->timeout = 100; /* default values, should */ | ||
222 | adap->retries = 3; /* be replaced by defines */ | ||
223 | |||
224 | i2c_add_adapter(adap); | ||
225 | |||
226 | PDEBUG(DBG_ALGO,"i2c bus for %s registered", adap->name); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | |||
232 | int usbvision_i2c_usb_del_bus(struct i2c_adapter *adap) | ||
233 | { | ||
234 | |||
235 | i2c_del_adapter(adap); | ||
236 | |||
237 | PDEBUG(DBG_ALGO,"i2c bus for %s unregistered", adap->name); | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | |||
243 | /* ----------------------------------------------------------------------- */ | ||
244 | /* usbvision specific I2C functions */ | ||
245 | /* ----------------------------------------------------------------------- */ | ||
246 | static struct i2c_adapter i2c_adap_template; | ||
247 | static struct i2c_algo_usb_data i2c_algo_template; | ||
248 | static struct i2c_client i2c_client_template; | ||
249 | |||
250 | int usbvision_init_i2c(struct usb_usbvision *usbvision) | ||
251 | { | ||
252 | memcpy(&usbvision->i2c_adap, &i2c_adap_template, | ||
253 | sizeof(struct i2c_adapter)); | ||
254 | memcpy(&usbvision->i2c_algo, &i2c_algo_template, | ||
255 | sizeof(struct i2c_algo_usb_data)); | ||
256 | memcpy(&usbvision->i2c_client, &i2c_client_template, | ||
257 | sizeof(struct i2c_client)); | ||
258 | |||
259 | sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name), | ||
260 | " #%d", usbvision->vdev->minor & 0x1f); | ||
261 | PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name); | ||
262 | |||
263 | i2c_set_adapdata(&usbvision->i2c_adap, usbvision); | ||
264 | i2c_set_clientdata(&usbvision->i2c_client, usbvision); | ||
265 | i2c_set_algo_usb_data(&usbvision->i2c_algo, usbvision); | ||
266 | |||
267 | usbvision->i2c_adap.algo_data = &usbvision->i2c_algo; | ||
268 | usbvision->i2c_client.adapter = &usbvision->i2c_adap; | ||
269 | |||
270 | if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { | ||
271 | printk(KERN_ERR "usbvision_init_i2c: can't write reg\n"); | ||
272 | return -EBUSY; | ||
273 | } | ||
274 | |||
275 | #ifdef CONFIG_MODULES | ||
276 | /* Request the load of the i2c modules we need */ | ||
277 | switch (usbvision_device_data[usbvision->DevModel].Codec) { | ||
278 | case CODEC_SAA7113: | ||
279 | request_module("saa7115"); | ||
280 | break; | ||
281 | case CODEC_SAA7111: | ||
282 | request_module("saa7115"); | ||
283 | break; | ||
284 | } | ||
285 | if (usbvision_device_data[usbvision->DevModel].Tuner == 1) { | ||
286 | request_module("tuner"); | ||
287 | } | ||
288 | #endif | ||
289 | |||
290 | return usbvision_i2c_usb_add_bus(&usbvision->i2c_adap); | ||
291 | } | ||
292 | |||
293 | void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd, | ||
294 | void *arg) | ||
295 | { | ||
296 | BUG_ON(NULL == usbvision->i2c_adap.algo_data); | ||
297 | i2c_clients_command(&usbvision->i2c_adap, cmd, arg); | ||
298 | } | ||
299 | |||
300 | static int attach_inform(struct i2c_client *client) | ||
301 | { | ||
302 | struct usb_usbvision *usbvision; | ||
303 | |||
304 | usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); | ||
305 | |||
306 | switch (client->addr << 1) { | ||
307 | case 0x43: | ||
308 | case 0x4b: | ||
309 | { | ||
310 | struct tuner_setup tun_setup; | ||
311 | |||
312 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | ||
313 | tun_setup.type = TUNER_TDA9887; | ||
314 | tun_setup.addr = client->addr; | ||
315 | |||
316 | call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); | ||
317 | |||
318 | break; | ||
319 | } | ||
320 | case 0x42: | ||
321 | PDEBUG(DBG_I2C,"attach_inform: saa7114 detected."); | ||
322 | break; | ||
323 | case 0x4a: | ||
324 | PDEBUG(DBG_I2C,"attach_inform: saa7113 detected."); | ||
325 | break; | ||
326 | case 0xa0: | ||
327 | PDEBUG(DBG_I2C,"attach_inform: eeprom detected."); | ||
328 | break; | ||
329 | |||
330 | default: | ||
331 | { | ||
332 | struct tuner_setup tun_setup; | ||
333 | |||
334 | PDEBUG(DBG_I2C,"attach inform: detected I2C address %x", client->addr << 1); | ||
335 | usbvision->tuner_addr = client->addr; | ||
336 | |||
337 | if ((usbvision->have_tuner) && (usbvision->tuner_type != -1)) { | ||
338 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | ||
339 | tun_setup.type = usbvision->tuner_type; | ||
340 | tun_setup.addr = usbvision->tuner_addr; | ||
341 | call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); | ||
342 | } | ||
343 | } | ||
344 | break; | ||
345 | } | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int detach_inform(struct i2c_client *client) | ||
350 | { | ||
351 | struct usb_usbvision *usbvision; | ||
352 | |||
353 | usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); | ||
354 | |||
355 | PDEBUG(DBG_I2C,"usbvision[%d] detaches %s", usbvision->nr, client->name); | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static int | ||
360 | usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr, | ||
361 | char *buf, short len) | ||
362 | { | ||
363 | int rc, retries; | ||
364 | |||
365 | for (retries = 5;;) { | ||
366 | rc = usbvision_write_reg(usbvision, USBVISION_SER_ADRS, addr); | ||
367 | if (rc < 0) | ||
368 | return rc; | ||
369 | |||
370 | /* Initiate byte read cycle */ | ||
371 | /* USBVISION_SER_CONT <- d0-d2 n. of bytes to r/w */ | ||
372 | /* d3 0=Wr 1=Rd */ | ||
373 | rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, | ||
374 | (len & 0x07) | 0x18); | ||
375 | if (rc < 0) | ||
376 | return rc; | ||
377 | |||
378 | /* Test for Busy and ACK */ | ||
379 | do { | ||
380 | /* USBVISION_SER_CONT -> d4 == 0 busy */ | ||
381 | rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT); | ||
382 | } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */ | ||
383 | if (rc < 0) | ||
384 | return rc; | ||
385 | |||
386 | /* USBVISION_SER_CONT -> d5 == 1 Not ack */ | ||
387 | if ((rc & 0x20) == 0) /* Ack? */ | ||
388 | break; | ||
389 | |||
390 | /* I2C abort */ | ||
391 | rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00); | ||
392 | if (rc < 0) | ||
393 | return rc; | ||
394 | |||
395 | if (--retries < 0) | ||
396 | return -1; | ||
397 | } | ||
398 | |||
399 | switch (len) { | ||
400 | case 4: | ||
401 | buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4); | ||
402 | case 3: | ||
403 | buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3); | ||
404 | case 2: | ||
405 | buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2); | ||
406 | case 1: | ||
407 | buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1); | ||
408 | break; | ||
409 | default: | ||
410 | printk(KERN_ERR | ||
411 | "usbvision_i2c_read_max4: buffer length > 4\n"); | ||
412 | } | ||
413 | |||
414 | if (i2c_debug & DBG_I2C) { | ||
415 | int idx; | ||
416 | for (idx = 0; idx < len; idx++) { | ||
417 | PDEBUG(DBG_I2C,"read %x from address %x", (unsigned char)buf[idx], addr); | ||
418 | } | ||
419 | } | ||
420 | return len; | ||
421 | } | ||
422 | |||
423 | |||
424 | static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision, | ||
425 | unsigned char addr, const char *buf, | ||
426 | short len) | ||
427 | { | ||
428 | int rc, retries; | ||
429 | int i; | ||
430 | unsigned char value[6]; | ||
431 | unsigned char ser_cont; | ||
432 | |||
433 | ser_cont = (len & 0x07) | 0x10; | ||
434 | |||
435 | value[0] = addr; | ||
436 | value[1] = ser_cont; | ||
437 | for (i = 0; i < len; i++) | ||
438 | value[i + 2] = buf[i]; | ||
439 | |||
440 | for (retries = 5;;) { | ||
441 | rc = usb_control_msg(usbvision->dev, | ||
442 | usb_sndctrlpipe(usbvision->dev, 1), | ||
443 | USBVISION_OP_CODE, | ||
444 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
445 | USB_RECIP_ENDPOINT, 0, | ||
446 | (__u16) USBVISION_SER_ADRS, value, | ||
447 | len + 2, HZ); | ||
448 | |||
449 | if (rc < 0) | ||
450 | return rc; | ||
451 | |||
452 | rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, | ||
453 | (len & 0x07) | 0x10); | ||
454 | if (rc < 0) | ||
455 | return rc; | ||
456 | |||
457 | /* Test for Busy and ACK */ | ||
458 | do { | ||
459 | rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT); | ||
460 | } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */ | ||
461 | if (rc < 0) | ||
462 | return rc; | ||
463 | |||
464 | if ((rc & 0x20) == 0) /* Ack? */ | ||
465 | break; | ||
466 | |||
467 | /* I2C abort */ | ||
468 | usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00); | ||
469 | |||
470 | if (--retries < 0) | ||
471 | return -1; | ||
472 | |||
473 | } | ||
474 | |||
475 | if (i2c_debug & DBG_I2C) { | ||
476 | int idx; | ||
477 | for (idx = 0; idx < len; idx++) { | ||
478 | PDEBUG(DBG_I2C,"wrote %x at address %x", (unsigned char)buf[idx], addr); | ||
479 | } | ||
480 | } | ||
481 | return len; | ||
482 | } | ||
483 | |||
484 | static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, | ||
485 | short len) | ||
486 | { | ||
487 | char *bufPtr = buf; | ||
488 | int retval; | ||
489 | int wrcount = 0; | ||
490 | int count; | ||
491 | int maxLen = 4; | ||
492 | struct usb_usbvision *usbvision = (struct usb_usbvision *) data; | ||
493 | |||
494 | while (len > 0) { | ||
495 | count = (len > maxLen) ? maxLen : len; | ||
496 | retval = usbvision_i2c_write_max4(usbvision, addr, bufPtr, count); | ||
497 | if (retval > 0) { | ||
498 | len -= count; | ||
499 | bufPtr += count; | ||
500 | wrcount += count; | ||
501 | } else | ||
502 | return (retval < 0) ? retval : -EFAULT; | ||
503 | } | ||
504 | return wrcount; | ||
505 | } | ||
506 | |||
507 | static int usbvision_i2c_read(void *data, unsigned char addr, char *buf, | ||
508 | short len) | ||
509 | { | ||
510 | char temp[4]; | ||
511 | int retval, i; | ||
512 | int rdcount = 0; | ||
513 | int count; | ||
514 | struct usb_usbvision *usbvision = (struct usb_usbvision *) data; | ||
515 | |||
516 | while (len > 0) { | ||
517 | count = (len > 3) ? 4 : len; | ||
518 | retval = usbvision_i2c_read_max4(usbvision, addr, temp, count); | ||
519 | if (retval > 0) { | ||
520 | for (i = 0; i < len; i++) | ||
521 | buf[rdcount + i] = temp[i]; | ||
522 | len -= count; | ||
523 | rdcount += count; | ||
524 | } else | ||
525 | return (retval < 0) ? retval : -EFAULT; | ||
526 | } | ||
527 | return rdcount; | ||
528 | } | ||
529 | |||
530 | static struct i2c_algo_usb_data i2c_algo_template = { | ||
531 | .data = NULL, | ||
532 | .inb = usbvision_i2c_read, | ||
533 | .outb = usbvision_i2c_write, | ||
534 | .udelay = 10, | ||
535 | .mdelay = 10, | ||
536 | .timeout = 100, | ||
537 | }; | ||
538 | |||
539 | static struct i2c_adapter i2c_adap_template = { | ||
540 | .owner = THIS_MODULE, | ||
541 | .name = "usbvision", | ||
542 | .id = I2C_HW_B_BT848, /* FIXME */ | ||
543 | .algo = NULL, | ||
544 | .algo_data = NULL, | ||
545 | .client_register = attach_inform, | ||
546 | .client_unregister = detach_inform, | ||
547 | #ifdef I2C_ADAP_CLASS_TV_ANALOG | ||
548 | .class = I2C_ADAP_CLASS_TV_ANALOG, | ||
549 | #else | ||
550 | .class = I2C_CLASS_TV_ANALOG, | ||
551 | #endif | ||
552 | }; | ||
553 | |||
554 | static struct i2c_client i2c_client_template = { | ||
555 | .name = "usbvision internal", | ||
556 | }; | ||
557 | |||
558 | EXPORT_SYMBOL(usbvision_i2c_usb_add_bus); | ||
559 | EXPORT_SYMBOL(usbvision_i2c_usb_del_bus); | ||
560 | |||
561 | /* | ||
562 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
563 | * --------------------------------------------------------------------------- | ||
564 | * Local variables: | ||
565 | * c-basic-offset: 8 | ||
566 | * End: | ||
567 | */ | ||
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c new file mode 100644 index 000000000000..864446c012eb --- /dev/null +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -0,0 +1,2051 @@ | |||
1 | /* | ||
2 | * USB USBVISION Video device driver 0.9.9 | ||
3 | * | ||
4 | * | ||
5 | * | ||
6 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
7 | * | ||
8 | * This module is part of usbvision driver project. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | * Let's call the version 0.... until compression decoding is completely | ||
25 | * implemented. | ||
26 | * | ||
27 | * This driver is written by Jose Ignacio Gijon and Joerg Heckenbach. | ||
28 | * It was based on USB CPiA driver written by Peter Pregler, | ||
29 | * Scott J. Bertin and Johannes Erdfelt | ||
30 | * Ideas are taken from bttv driver by Ralph Metzler, Marcus Metzler & | ||
31 | * Gerd Knorr and zoran 36120/36125 driver by Pauline Middelink | ||
32 | * Updates to driver completed by Dwaine P. Garden | ||
33 | * | ||
34 | * | ||
35 | * TODO: | ||
36 | * - use submit_urb for all setup packets | ||
37 | * - Fix memory settings for nt1004. It is 4 times as big as the | ||
38 | * nt1003 memory. | ||
39 | * - Add audio on endpoint 3 for nt1004 chip. Seems impossible, needs a codec interface. Which one? | ||
40 | * - Clean up the driver. | ||
41 | * - optimization for performance. | ||
42 | * - Add Videotext capability (VBI). Working on it..... | ||
43 | * - Check audio for other devices | ||
44 | * | ||
45 | */ | ||
46 | |||
47 | #include <linux/version.h> | ||
48 | #include <linux/kernel.h> | ||
49 | #include <linux/sched.h> | ||
50 | #include <linux/list.h> | ||
51 | #include <linux/timer.h> | ||
52 | #include <linux/slab.h> | ||
53 | #include <linux/mm.h> | ||
54 | #include <linux/utsname.h> | ||
55 | #include <linux/highmem.h> | ||
56 | #include <linux/smp_lock.h> | ||
57 | #include <linux/videodev.h> | ||
58 | #include <linux/vmalloc.h> | ||
59 | #include <linux/module.h> | ||
60 | #include <linux/init.h> | ||
61 | #include <linux/spinlock.h> | ||
62 | #include <asm/io.h> | ||
63 | #include <linux/videodev2.h> | ||
64 | #include <linux/video_decoder.h> | ||
65 | #include <linux/i2c.h> | ||
66 | |||
67 | #include <media/saa7115.h> | ||
68 | #include <media/v4l2-common.h> | ||
69 | #include <media/tuner.h> | ||
70 | #include <media/audiochip.h> | ||
71 | |||
72 | #include <linux/moduleparam.h> | ||
73 | #include <linux/workqueue.h> | ||
74 | |||
75 | #ifdef CONFIG_KMOD | ||
76 | #include <linux/kmod.h> | ||
77 | #endif | ||
78 | |||
79 | #include "usbvision.h" | ||
80 | |||
81 | #define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>, Dwaine Garden <DwaineGarden@rogers.com>" | ||
82 | #define DRIVER_NAME "usbvision" | ||
83 | #define DRIVER_ALIAS "USBVision" | ||
84 | #define DRIVER_DESC "USBVision USB Video Device Driver for Linux" | ||
85 | #define DRIVER_LICENSE "GPL" | ||
86 | #define USBVISION_DRIVER_VERSION_MAJOR 0 | ||
87 | #define USBVISION_DRIVER_VERSION_MINOR 9 | ||
88 | #define USBVISION_DRIVER_VERSION_PATCHLEVEL 9 | ||
89 | #define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,USBVISION_DRIVER_VERSION_MINOR,USBVISION_DRIVER_VERSION_PATCHLEVEL) | ||
90 | #define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) "." __stringify(USBVISION_DRIVER_VERSION_MINOR) "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL) | ||
91 | |||
92 | #define ENABLE_HEXDUMP 0 /* Enable if you need it */ | ||
93 | |||
94 | |||
95 | #ifdef USBVISION_DEBUG | ||
96 | #define PDEBUG(level, fmt, args...) \ | ||
97 | if (video_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) | ||
98 | #else | ||
99 | #define PDEBUG(level, fmt, args...) do {} while(0) | ||
100 | #endif | ||
101 | |||
102 | #define DBG_IOCTL 1<<0 | ||
103 | #define DBG_IO 1<<1 | ||
104 | #define DBG_PROBE 1<<2 | ||
105 | #define DBG_MMAP 1<<3 | ||
106 | |||
107 | //String operations | ||
108 | #define rmspace(str) while(*str==' ') str++; | ||
109 | #define goto2next(str) while(*str!=' ') str++; while(*str==' ') str++; | ||
110 | |||
111 | |||
112 | static int usbvision_nr = 0; // sequential number of usbvision device | ||
113 | |||
114 | static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { | ||
115 | { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" }, | ||
116 | { 1, 2, 16, V4L2_PIX_FMT_RGB565 , "RGB565" }, | ||
117 | { 1, 3, 24, V4L2_PIX_FMT_RGB24 , "RGB24" }, | ||
118 | { 1, 4, 32, V4L2_PIX_FMT_RGB32 , "RGB32" }, | ||
119 | { 1, 2, 16, V4L2_PIX_FMT_RGB555 , "RGB555" }, | ||
120 | { 1, 2, 16, V4L2_PIX_FMT_YUYV , "YUV422" }, | ||
121 | { 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, // 1.5 ! | ||
122 | { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" } | ||
123 | }; | ||
124 | |||
125 | /* supported tv norms */ | ||
126 | static struct usbvision_tvnorm tvnorms[] = { | ||
127 | { | ||
128 | .name = "PAL", | ||
129 | .id = V4L2_STD_PAL, | ||
130 | }, { | ||
131 | .name = "NTSC", | ||
132 | .id = V4L2_STD_NTSC, | ||
133 | }, { | ||
134 | .name = "SECAM", | ||
135 | .id = V4L2_STD_SECAM, | ||
136 | }, { | ||
137 | .name = "PAL-M", | ||
138 | .id = V4L2_STD_PAL_M, | ||
139 | } | ||
140 | }; | ||
141 | |||
142 | #define TVNORMS ARRAY_SIZE(tvnorms) | ||
143 | |||
144 | // Function prototypes | ||
145 | static void usbvision_release(struct usb_usbvision *usbvision); | ||
146 | |||
147 | // Default initalization of device driver parameters | ||
148 | static int isocMode = ISOC_MODE_COMPRESS; // Set the default format for ISOC endpoint | ||
149 | static int video_debug = 0; // Set the default Debug Mode of the device driver | ||
150 | static int PowerOnAtOpen = 1; // Set the default device to power on at startup | ||
151 | static int video_nr = -1; // Sequential Number of Video Device | ||
152 | static int radio_nr = -1; // Sequential Number of Radio Device | ||
153 | static int vbi_nr = -1; // Sequential Number of VBI Device | ||
154 | static char *CustomDevice=NULL; // Set as nothing.... | ||
155 | |||
156 | // Grab parameters for the device driver | ||
157 | |||
158 | #if defined(module_param) // Showing parameters under SYSFS | ||
159 | module_param(isocMode, int, 0444); | ||
160 | module_param(video_debug, int, 0444); | ||
161 | module_param(PowerOnAtOpen, int, 0444); | ||
162 | module_param(video_nr, int, 0444); | ||
163 | module_param(radio_nr, int, 0444); | ||
164 | module_param(vbi_nr, int, 0444); | ||
165 | module_param(CustomDevice, charp, 0444); | ||
166 | #else // Old Style | ||
167 | MODULE_PARAM(isocMode, "i"); | ||
168 | MODULE_PARM(video_debug, "i"); // Grab the Debug Mode of the device driver | ||
169 | MODULE_PARM(adjustCompression, "i"); // Grab the compression to be adaptive | ||
170 | MODULE_PARM(PowerOnAtOpen, "i"); // Grab the device to power on at startup | ||
171 | MODULE_PARM(SwitchSVideoInput, "i"); // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. | ||
172 | MODULE_PARM(video_nr, "i"); // video_nr option allows to specify a certain /dev/videoX device (like /dev/video0 or /dev/video1 ...) | ||
173 | MODULE_PARM(radio_nr, "i"); // radio_nr option allows to specify a certain /dev/radioX device (like /dev/radio0 or /dev/radio1 ...) | ||
174 | MODULE_PARM(vbi_nr, "i"); // vbi_nr option allows to specify a certain /dev/vbiX device (like /dev/vbi0 or /dev/vbi1 ...) | ||
175 | MODULE_PARM(CustomDevice, "s"); // .... CustomDevice | ||
176 | #endif | ||
177 | |||
178 | MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); | ||
179 | MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)"); | ||
180 | MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device is opened. Default: 1 (On)"); | ||
181 | MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 (autodetect)"); | ||
182 | MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); | ||
183 | MODULE_PARM_DESC(vbi_nr, "Set vbi device number (/dev/vbiX). Default: -1 (autodetect)"); | ||
184 | MODULE_PARM_DESC(CustomDevice, " Define the fine tuning parameters for the device. Default: null"); | ||
185 | |||
186 | |||
187 | // Misc stuff | ||
188 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
189 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
190 | MODULE_LICENSE(DRIVER_LICENSE); | ||
191 | MODULE_VERSION(USBVISION_VERSION_STRING); | ||
192 | MODULE_ALIAS(DRIVER_ALIAS); | ||
193 | |||
194 | |||
195 | /****************************************************************************************/ | ||
196 | /* SYSFS Code - Copied from the stv680.c usb module. */ | ||
197 | /* Device information is located at /sys/class/video4linux/video0 */ | ||
198 | /* Device parameters information is located at /sys/module/usbvision */ | ||
199 | /* Device USB Information is located at /sys/bus/usb/drivers/USBVision Video Grabber */ | ||
200 | /****************************************************************************************/ | ||
201 | |||
202 | |||
203 | #define YES_NO(x) ((x) ? "Yes" : "No") | ||
204 | |||
205 | static inline struct usb_usbvision *cd_to_usbvision(struct class_device *cd) | ||
206 | { | ||
207 | struct video_device *vdev = to_video_device(cd); | ||
208 | return video_get_drvdata(vdev); | ||
209 | } | ||
210 | |||
211 | static ssize_t show_version(struct class_device *cd, char *buf) | ||
212 | { | ||
213 | return sprintf(buf, "%s\n", USBVISION_VERSION_STRING); | ||
214 | } | ||
215 | static CLASS_DEVICE_ATTR(version, S_IRUGO, show_version, NULL); | ||
216 | |||
217 | static ssize_t show_model(struct class_device *class_dev, char *buf) | ||
218 | { | ||
219 | struct video_device *vdev = to_video_device(class_dev); | ||
220 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
221 | return sprintf(buf, "%s\n", usbvision_device_data[usbvision->DevModel].ModelString); | ||
222 | } | ||
223 | static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL); | ||
224 | |||
225 | static ssize_t show_hue(struct class_device *class_dev, char *buf) | ||
226 | { | ||
227 | struct video_device *vdev = to_video_device(class_dev); | ||
228 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
229 | struct v4l2_control ctrl; | ||
230 | ctrl.id = V4L2_CID_HUE; | ||
231 | ctrl.value = 0; | ||
232 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | ||
233 | return sprintf(buf, "%d\n", ctrl.value >> 8); | ||
234 | } | ||
235 | static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); | ||
236 | |||
237 | static ssize_t show_contrast(struct class_device *class_dev, char *buf) | ||
238 | { | ||
239 | struct video_device *vdev = to_video_device(class_dev); | ||
240 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
241 | struct v4l2_control ctrl; | ||
242 | ctrl.id = V4L2_CID_CONTRAST; | ||
243 | ctrl.value = 0; | ||
244 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | ||
245 | return sprintf(buf, "%d\n", ctrl.value >> 8); | ||
246 | } | ||
247 | static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); | ||
248 | |||
249 | static ssize_t show_brightness(struct class_device *class_dev, char *buf) | ||
250 | { | ||
251 | struct video_device *vdev = to_video_device(class_dev); | ||
252 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
253 | struct v4l2_control ctrl; | ||
254 | ctrl.id = V4L2_CID_BRIGHTNESS; | ||
255 | ctrl.value = 0; | ||
256 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | ||
257 | return sprintf(buf, "%d\n", ctrl.value >> 8); | ||
258 | } | ||
259 | static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); | ||
260 | |||
261 | static ssize_t show_saturation(struct class_device *class_dev, char *buf) | ||
262 | { | ||
263 | struct video_device *vdev = to_video_device(class_dev); | ||
264 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
265 | struct v4l2_control ctrl; | ||
266 | ctrl.id = V4L2_CID_SATURATION; | ||
267 | ctrl.value = 0; | ||
268 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); | ||
269 | return sprintf(buf, "%d\n", ctrl.value >> 8); | ||
270 | } | ||
271 | static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); | ||
272 | |||
273 | static ssize_t show_streaming(struct class_device *class_dev, char *buf) | ||
274 | { | ||
275 | struct video_device *vdev = to_video_device(class_dev); | ||
276 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
277 | return sprintf(buf, "%s\n", YES_NO(usbvision->streaming==Stream_On?1:0)); | ||
278 | } | ||
279 | static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); | ||
280 | |||
281 | static ssize_t show_compression(struct class_device *class_dev, char *buf) | ||
282 | { | ||
283 | struct video_device *vdev = to_video_device(class_dev); | ||
284 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
285 | return sprintf(buf, "%s\n", YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS)); | ||
286 | } | ||
287 | static CLASS_DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); | ||
288 | |||
289 | static ssize_t show_device_bridge(struct class_device *class_dev, char *buf) | ||
290 | { | ||
291 | struct video_device *vdev = to_video_device(class_dev); | ||
292 | struct usb_usbvision *usbvision = video_get_drvdata(vdev); | ||
293 | return sprintf(buf, "%d\n", usbvision->bridgeType); | ||
294 | } | ||
295 | static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL); | ||
296 | |||
297 | static void usbvision_create_sysfs(struct video_device *vdev) | ||
298 | { | ||
299 | int res; | ||
300 | if (vdev) { | ||
301 | res=video_device_create_file(vdev, &class_device_attr_version); | ||
302 | res=video_device_create_file(vdev, &class_device_attr_model); | ||
303 | res=video_device_create_file(vdev, &class_device_attr_hue); | ||
304 | res=video_device_create_file(vdev, &class_device_attr_contrast); | ||
305 | res=video_device_create_file(vdev, &class_device_attr_brightness); | ||
306 | res=video_device_create_file(vdev, &class_device_attr_saturation); | ||
307 | res=video_device_create_file(vdev, &class_device_attr_streaming); | ||
308 | res=video_device_create_file(vdev, &class_device_attr_compression); | ||
309 | res=video_device_create_file(vdev, &class_device_attr_bridge); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | static void usbvision_remove_sysfs(struct video_device *vdev) | ||
314 | { | ||
315 | if (vdev) { | ||
316 | video_device_remove_file(vdev, &class_device_attr_version); | ||
317 | video_device_remove_file(vdev, &class_device_attr_model); | ||
318 | video_device_remove_file(vdev, &class_device_attr_hue); | ||
319 | video_device_remove_file(vdev, &class_device_attr_contrast); | ||
320 | video_device_remove_file(vdev, &class_device_attr_brightness); | ||
321 | video_device_remove_file(vdev, &class_device_attr_saturation); | ||
322 | video_device_remove_file(vdev, &class_device_attr_streaming); | ||
323 | video_device_remove_file(vdev, &class_device_attr_compression); | ||
324 | video_device_remove_file(vdev, &class_device_attr_bridge); | ||
325 | } | ||
326 | } | ||
327 | |||
328 | |||
329 | /* | ||
330 | * usbvision_open() | ||
331 | * | ||
332 | * This is part of Video 4 Linux API. The driver can be opened by one | ||
333 | * client only (checks internal counter 'usbvision->user'). The procedure | ||
334 | * then allocates buffers needed for video processing. | ||
335 | * | ||
336 | */ | ||
337 | static int usbvision_v4l2_open(struct inode *inode, struct file *file) | ||
338 | { | ||
339 | struct video_device *dev = video_devdata(file); | ||
340 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
341 | int errCode = 0; | ||
342 | |||
343 | PDEBUG(DBG_IO, "open"); | ||
344 | |||
345 | |||
346 | usbvision_reset_powerOffTimer(usbvision); | ||
347 | |||
348 | if (usbvision->user) | ||
349 | errCode = -EBUSY; | ||
350 | else { | ||
351 | /* Allocate memory for the frame buffers */ | ||
352 | errCode = usbvision_frames_alloc(usbvision); | ||
353 | if(!errCode) { | ||
354 | /* Allocate memory for the scratch ring buffer */ | ||
355 | errCode = usbvision_scratch_alloc(usbvision); | ||
356 | if(!errCode) { | ||
357 | /* Allocate memory for the USB S buffers */ | ||
358 | errCode = usbvision_sbuf_alloc(usbvision); | ||
359 | if ((!errCode) && (usbvision->isocMode==ISOC_MODE_COMPRESS)) { | ||
360 | /* Allocate intermediate decompression buffers only if needed */ | ||
361 | errCode = usbvision_decompress_alloc(usbvision); | ||
362 | } | ||
363 | } | ||
364 | } | ||
365 | if (errCode) { | ||
366 | /* Deallocate all buffers if trouble */ | ||
367 | usbvision_frames_free(usbvision); | ||
368 | usbvision_scratch_free(usbvision); | ||
369 | usbvision_sbuf_free(usbvision); | ||
370 | usbvision_decompress_free(usbvision); | ||
371 | } | ||
372 | } | ||
373 | |||
374 | /* If so far no errors then we shall start the camera */ | ||
375 | if (!errCode) { | ||
376 | down(&usbvision->lock); | ||
377 | if (usbvision->power == 0) { | ||
378 | usbvision_power_on(usbvision); | ||
379 | usbvision_init_i2c(usbvision); | ||
380 | } | ||
381 | |||
382 | /* Send init sequence only once, it's large! */ | ||
383 | if (!usbvision->initialized) { | ||
384 | int setup_ok = 0; | ||
385 | setup_ok = usbvision_setup(usbvision,isocMode); | ||
386 | if (setup_ok) | ||
387 | usbvision->initialized = 1; | ||
388 | else | ||
389 | errCode = -EBUSY; | ||
390 | } | ||
391 | |||
392 | if (!errCode) { | ||
393 | usbvision_begin_streaming(usbvision); | ||
394 | errCode = usbvision_init_isoc(usbvision); | ||
395 | /* device needs to be initialized before isoc transfer */ | ||
396 | usbvision_muxsel(usbvision,0); | ||
397 | usbvision->user++; | ||
398 | } | ||
399 | else { | ||
400 | if (PowerOnAtOpen) { | ||
401 | usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); | ||
402 | usbvision_power_off(usbvision); | ||
403 | usbvision->initialized = 0; | ||
404 | } | ||
405 | } | ||
406 | up(&usbvision->lock); | ||
407 | } | ||
408 | |||
409 | if (errCode) { | ||
410 | } | ||
411 | |||
412 | /* prepare queues */ | ||
413 | usbvision_empty_framequeues(usbvision); | ||
414 | |||
415 | PDEBUG(DBG_IO, "success"); | ||
416 | return errCode; | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * usbvision_v4l2_close() | ||
421 | * | ||
422 | * This is part of Video 4 Linux API. The procedure | ||
423 | * stops streaming and deallocates all buffers that were earlier | ||
424 | * allocated in usbvision_v4l2_open(). | ||
425 | * | ||
426 | */ | ||
427 | static int usbvision_v4l2_close(struct inode *inode, struct file *file) | ||
428 | { | ||
429 | struct video_device *dev = video_devdata(file); | ||
430 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
431 | |||
432 | PDEBUG(DBG_IO, "close"); | ||
433 | down(&usbvision->lock); | ||
434 | |||
435 | usbvision_audio_off(usbvision); | ||
436 | usbvision_restart_isoc(usbvision); | ||
437 | usbvision_stop_isoc(usbvision); | ||
438 | |||
439 | usbvision_decompress_free(usbvision); | ||
440 | usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); | ||
441 | usbvision_scratch_free(usbvision); | ||
442 | usbvision_sbuf_free(usbvision); | ||
443 | |||
444 | usbvision->user--; | ||
445 | |||
446 | if (PowerOnAtOpen) { | ||
447 | /* power off in a little while to avoid off/on every close/open short sequences */ | ||
448 | usbvision_set_powerOffTimer(usbvision); | ||
449 | usbvision->initialized = 0; | ||
450 | } | ||
451 | |||
452 | up(&usbvision->lock); | ||
453 | |||
454 | if (usbvision->remove_pending) { | ||
455 | info("%s: Final disconnect", __FUNCTION__); | ||
456 | usbvision_release(usbvision); | ||
457 | } | ||
458 | |||
459 | PDEBUG(DBG_IO, "success"); | ||
460 | |||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | |||
466 | /* | ||
467 | * usbvision_ioctl() | ||
468 | * | ||
469 | * This is part of Video 4 Linux API. The procedure handles ioctl() calls. | ||
470 | * | ||
471 | */ | ||
472 | static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | ||
473 | unsigned int cmd, void *arg) | ||
474 | { | ||
475 | struct video_device *dev = video_devdata(file); | ||
476 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
477 | |||
478 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
479 | return -EFAULT; | ||
480 | |||
481 | switch (cmd) { | ||
482 | |||
483 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
484 | /* ioctls to allow direct acces to the NT100x registers */ | ||
485 | case VIDIOC_INT_G_REGISTER: | ||
486 | { | ||
487 | struct v4l2_register *reg = arg; | ||
488 | int errCode; | ||
489 | |||
490 | if (reg->i2c_id != 0) | ||
491 | return -EINVAL; | ||
492 | /* NT100x has a 8-bit register space */ | ||
493 | errCode = usbvision_read_reg(usbvision, reg->reg&0xff); | ||
494 | if (errCode < 0) { | ||
495 | err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode); | ||
496 | } | ||
497 | else { | ||
498 | reg->val=(unsigned char)errCode; | ||
499 | PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X", | ||
500 | (unsigned int)reg->reg, reg->val); | ||
501 | errCode = 0; // No error | ||
502 | } | ||
503 | return errCode; | ||
504 | } | ||
505 | case VIDIOC_INT_S_REGISTER: | ||
506 | { | ||
507 | struct v4l2_register *reg = arg; | ||
508 | int errCode; | ||
509 | |||
510 | if (reg->i2c_id != 0) | ||
511 | return -EINVAL; | ||
512 | if (!capable(CAP_SYS_ADMIN)) | ||
513 | return -EPERM; | ||
514 | errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); | ||
515 | if (errCode < 0) { | ||
516 | err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode); | ||
517 | } | ||
518 | else { | ||
519 | PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X", | ||
520 | (unsigned int)reg->reg, reg->val); | ||
521 | errCode = 0; | ||
522 | } | ||
523 | return 0; | ||
524 | } | ||
525 | #endif | ||
526 | case VIDIOC_QUERYCAP: | ||
527 | { | ||
528 | struct v4l2_capability *vc=arg; | ||
529 | |||
530 | memset(vc, 0, sizeof(*vc)); | ||
531 | strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); | ||
532 | strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, | ||
533 | sizeof(vc->card)); | ||
534 | strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, | ||
535 | sizeof(vc->bus_info)); | ||
536 | vc->version = USBVISION_DRIVER_VERSION; | ||
537 | vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
538 | V4L2_CAP_AUDIO | | ||
539 | V4L2_CAP_READWRITE | | ||
540 | V4L2_CAP_STREAMING | | ||
541 | (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); | ||
542 | PDEBUG(DBG_IOCTL, "VIDIOC_QUERYCAP"); | ||
543 | return 0; | ||
544 | } | ||
545 | case VIDIOC_ENUMINPUT: | ||
546 | { | ||
547 | struct v4l2_input *vi = arg; | ||
548 | int chan; | ||
549 | |||
550 | if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) | ||
551 | return -EINVAL; | ||
552 | if (usbvision->have_tuner) { | ||
553 | chan = vi->index; | ||
554 | } | ||
555 | else { | ||
556 | chan = vi->index + 1; //skip Television string | ||
557 | } | ||
558 | switch(chan) { | ||
559 | case 0: | ||
560 | if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { | ||
561 | strcpy(vi->name, "White Video Input"); | ||
562 | } | ||
563 | else { | ||
564 | strcpy(vi->name, "Television"); | ||
565 | vi->type = V4L2_INPUT_TYPE_TUNER; | ||
566 | vi->audioset = 1; | ||
567 | vi->tuner = chan; | ||
568 | vi->std = V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM; | ||
569 | } | ||
570 | break; | ||
571 | case 1: | ||
572 | vi->type = V4L2_INPUT_TYPE_CAMERA; | ||
573 | if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { | ||
574 | strcpy(vi->name, "Green Video Input"); | ||
575 | } | ||
576 | else { | ||
577 | strcpy(vi->name, "Composite Video Input"); | ||
578 | } | ||
579 | vi->std = V4L2_STD_PAL; | ||
580 | break; | ||
581 | case 2: | ||
582 | vi->type = V4L2_INPUT_TYPE_CAMERA; | ||
583 | if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { | ||
584 | strcpy(vi->name, "Yellow Video Input"); | ||
585 | } | ||
586 | else { | ||
587 | strcpy(vi->name, "S-Video Input"); | ||
588 | } | ||
589 | vi->std = V4L2_STD_PAL; | ||
590 | break; | ||
591 | case 3: | ||
592 | vi->type = V4L2_INPUT_TYPE_CAMERA; | ||
593 | strcpy(vi->name, "Red Video Input"); | ||
594 | vi->std = V4L2_STD_PAL; | ||
595 | break; | ||
596 | } | ||
597 | PDEBUG(DBG_IOCTL, "VIDIOC_ENUMINPUT name=%s:%d tuners=%d type=%d norm=%x", | ||
598 | vi->name, vi->index, vi->tuner,vi->type,(int)vi->std); | ||
599 | return 0; | ||
600 | } | ||
601 | case VIDIOC_ENUMSTD: | ||
602 | { | ||
603 | struct v4l2_standard *e = arg; | ||
604 | unsigned int i; | ||
605 | int ret; | ||
606 | |||
607 | i = e->index; | ||
608 | if (i >= TVNORMS) | ||
609 | return -EINVAL; | ||
610 | ret = v4l2_video_std_construct(e, tvnorms[e->index].id, | ||
611 | tvnorms[e->index].name); | ||
612 | e->index = i; | ||
613 | if (ret < 0) | ||
614 | return ret; | ||
615 | return 0; | ||
616 | } | ||
617 | case VIDIOC_G_INPUT: | ||
618 | { | ||
619 | int *input = arg; | ||
620 | *input = usbvision->ctl_input; | ||
621 | return 0; | ||
622 | } | ||
623 | case VIDIOC_S_INPUT: | ||
624 | { | ||
625 | int *input = arg; | ||
626 | if ((*input >= usbvision->video_inputs) || (*input < 0) ) | ||
627 | return -EINVAL; | ||
628 | usbvision->ctl_input = *input; | ||
629 | |||
630 | down(&usbvision->lock); | ||
631 | usbvision_muxsel(usbvision, usbvision->ctl_input); | ||
632 | usbvision_set_input(usbvision); | ||
633 | usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); | ||
634 | up(&usbvision->lock); | ||
635 | return 0; | ||
636 | } | ||
637 | case VIDIOC_G_STD: | ||
638 | { | ||
639 | v4l2_std_id *id = arg; | ||
640 | |||
641 | *id = usbvision->tvnorm->id; | ||
642 | |||
643 | PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%s", usbvision->tvnorm->name); | ||
644 | return 0; | ||
645 | } | ||
646 | case VIDIOC_S_STD: | ||
647 | { | ||
648 | v4l2_std_id *id = arg; | ||
649 | unsigned int i; | ||
650 | |||
651 | for (i = 0; i < TVNORMS; i++) | ||
652 | if (*id == tvnorms[i].id) | ||
653 | break; | ||
654 | if (i == TVNORMS) | ||
655 | for (i = 0; i < TVNORMS; i++) | ||
656 | if (*id & tvnorms[i].id) | ||
657 | break; | ||
658 | if (i == TVNORMS) | ||
659 | return -EINVAL; | ||
660 | |||
661 | down(&usbvision->lock); | ||
662 | usbvision->tvnorm = &tvnorms[i]; | ||
663 | |||
664 | call_i2c_clients(usbvision, VIDIOC_S_STD, | ||
665 | &usbvision->tvnorm->id); | ||
666 | |||
667 | up(&usbvision->lock); | ||
668 | |||
669 | PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%s", usbvision->tvnorm->name); | ||
670 | return 0; | ||
671 | } | ||
672 | case VIDIOC_G_TUNER: | ||
673 | { | ||
674 | struct v4l2_tuner *vt = arg; | ||
675 | |||
676 | if (!usbvision->have_tuner || vt->index) // Only tuner 0 | ||
677 | return -EINVAL; | ||
678 | strcpy(vt->name, "Television"); | ||
679 | /* Let clients fill in the remainder of this struct */ | ||
680 | call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt); | ||
681 | |||
682 | PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER signal=%x, afc=%x",vt->signal,vt->afc); | ||
683 | return 0; | ||
684 | } | ||
685 | case VIDIOC_S_TUNER: | ||
686 | { | ||
687 | struct v4l2_tuner *vt = arg; | ||
688 | |||
689 | // Only no or one tuner for now | ||
690 | if (!usbvision->have_tuner || vt->index) | ||
691 | return -EINVAL; | ||
692 | /* let clients handle this */ | ||
693 | call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); | ||
694 | |||
695 | PDEBUG(DBG_IOCTL, "VIDIOC_S_TUNER"); | ||
696 | return 0; | ||
697 | } | ||
698 | case VIDIOC_G_FREQUENCY: | ||
699 | { | ||
700 | struct v4l2_frequency *freq = arg; | ||
701 | |||
702 | freq->tuner = 0; // Only one tuner | ||
703 | freq->type = V4L2_TUNER_ANALOG_TV; | ||
704 | freq->frequency = usbvision->freq; | ||
705 | PDEBUG(DBG_IOCTL, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)freq->frequency); | ||
706 | return 0; | ||
707 | } | ||
708 | case VIDIOC_S_FREQUENCY: | ||
709 | { | ||
710 | struct v4l2_frequency *freq = arg; | ||
711 | |||
712 | // Only no or one tuner for now | ||
713 | if (!usbvision->have_tuner || freq->tuner) | ||
714 | return -EINVAL; | ||
715 | |||
716 | usbvision->freq = freq->frequency; | ||
717 | call_i2c_clients(usbvision, cmd, freq); | ||
718 | PDEBUG(DBG_IOCTL, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)freq->frequency); | ||
719 | return 0; | ||
720 | } | ||
721 | case VIDIOC_G_AUDIO: | ||
722 | { | ||
723 | struct v4l2_audio *v = arg; | ||
724 | memset(v,0, sizeof(v)); | ||
725 | strcpy(v->name, "TV"); | ||
726 | PDEBUG(DBG_IOCTL, "VIDIOC_G_AUDIO"); | ||
727 | return 0; | ||
728 | } | ||
729 | case VIDIOC_S_AUDIO: | ||
730 | { | ||
731 | struct v4l2_audio *v = arg; | ||
732 | if(v->index) { | ||
733 | return -EINVAL; | ||
734 | } | ||
735 | PDEBUG(DBG_IOCTL, "VIDIOC_S_AUDIO"); | ||
736 | return 0; | ||
737 | } | ||
738 | case VIDIOC_QUERYCTRL: | ||
739 | { | ||
740 | struct v4l2_queryctrl *ctrl = arg; | ||
741 | int id=ctrl->id; | ||
742 | |||
743 | memset(ctrl,0,sizeof(*ctrl)); | ||
744 | ctrl->id=id; | ||
745 | |||
746 | call_i2c_clients(usbvision, cmd, arg); | ||
747 | |||
748 | if (ctrl->type) | ||
749 | return 0; | ||
750 | else | ||
751 | return -EINVAL; | ||
752 | |||
753 | PDEBUG(DBG_IOCTL,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type); | ||
754 | } | ||
755 | case VIDIOC_G_CTRL: | ||
756 | { | ||
757 | struct v4l2_control *ctrl = arg; | ||
758 | PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
759 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); | ||
760 | return 0; | ||
761 | } | ||
762 | case VIDIOC_S_CTRL: | ||
763 | { | ||
764 | struct v4l2_control *ctrl = arg; | ||
765 | |||
766 | PDEBUG(DBG_IOCTL, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
767 | call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); | ||
768 | return 0; | ||
769 | } | ||
770 | case VIDIOC_REQBUFS: | ||
771 | { | ||
772 | struct v4l2_requestbuffers *vr = arg; | ||
773 | int ret; | ||
774 | |||
775 | RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); | ||
776 | |||
777 | // Check input validity : the user must do a VIDEO CAPTURE and MMAP method. | ||
778 | if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || | ||
779 | (vr->memory != V4L2_MEMORY_MMAP)) | ||
780 | return -EINVAL; | ||
781 | |||
782 | if(usbvision->streaming == Stream_On) { | ||
783 | if ((ret = usbvision_stream_interrupt(usbvision))) | ||
784 | return ret; | ||
785 | } | ||
786 | |||
787 | usbvision_empty_framequeues(usbvision); | ||
788 | |||
789 | usbvision->curFrame = NULL; | ||
790 | |||
791 | PDEBUG(DBG_IOCTL, "VIDIOC_REQBUFS count=%d",vr->count); | ||
792 | return 0; | ||
793 | } | ||
794 | case VIDIOC_QUERYBUF: | ||
795 | { | ||
796 | struct v4l2_buffer *vb = arg; | ||
797 | struct usbvision_frame *frame; | ||
798 | |||
799 | // FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called) | ||
800 | |||
801 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { | ||
802 | return -EINVAL; | ||
803 | } | ||
804 | if(vb->index>=USBVISION_NUMFRAMES) { | ||
805 | return -EINVAL; | ||
806 | } | ||
807 | // Updating the corresponding frame state | ||
808 | vb->flags = 0; | ||
809 | frame = &usbvision->frame[vb->index]; | ||
810 | if(frame->grabstate >= FrameState_Ready) | ||
811 | vb->flags |= V4L2_BUF_FLAG_QUEUED; | ||
812 | if(frame->grabstate >= FrameState_Done) | ||
813 | vb->flags |= V4L2_BUF_FLAG_DONE; | ||
814 | if(frame->grabstate == FrameState_Unused) | ||
815 | vb->flags |= V4L2_BUF_FLAG_MAPPED; | ||
816 | vb->memory = V4L2_MEMORY_MMAP; | ||
817 | |||
818 | vb->m.offset = vb->index*usbvision->max_frame_size; | ||
819 | |||
820 | vb->memory = V4L2_MEMORY_MMAP; | ||
821 | vb->field = V4L2_FIELD_NONE; | ||
822 | vb->length = usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel; | ||
823 | vb->timestamp = usbvision->frame[vb->index].timestamp; | ||
824 | vb->sequence = usbvision->frame[vb->index].sequence; | ||
825 | return 0; | ||
826 | } | ||
827 | case VIDIOC_QBUF: | ||
828 | { | ||
829 | struct v4l2_buffer *vb = arg; | ||
830 | struct usbvision_frame *frame; | ||
831 | unsigned long lock_flags; | ||
832 | |||
833 | // FIXME : works only on VIDEO_CAPTURE MODE, MMAP. | ||
834 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { | ||
835 | return -EINVAL; | ||
836 | } | ||
837 | if(vb->index>=USBVISION_NUMFRAMES) { | ||
838 | return -EINVAL; | ||
839 | } | ||
840 | |||
841 | frame = &usbvision->frame[vb->index]; | ||
842 | |||
843 | if (frame->grabstate != FrameState_Unused) { | ||
844 | return -EAGAIN; | ||
845 | } | ||
846 | |||
847 | /* Mark it as ready and enqueue frame */ | ||
848 | frame->grabstate = FrameState_Ready; | ||
849 | frame->scanstate = ScanState_Scanning; | ||
850 | frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ | ||
851 | |||
852 | vb->flags &= ~V4L2_BUF_FLAG_DONE; | ||
853 | |||
854 | /* set v4l2_format index */ | ||
855 | frame->v4l2_format = usbvision->palette; | ||
856 | |||
857 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
858 | list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue); | ||
859 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
860 | |||
861 | PDEBUG(DBG_IOCTL, "VIDIOC_QBUF frame #%d",vb->index); | ||
862 | return 0; | ||
863 | } | ||
864 | case VIDIOC_DQBUF: | ||
865 | { | ||
866 | struct v4l2_buffer *vb = arg; | ||
867 | int ret; | ||
868 | struct usbvision_frame *f; | ||
869 | unsigned long lock_flags; | ||
870 | |||
871 | if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
872 | return -EINVAL; | ||
873 | |||
874 | if (list_empty(&(usbvision->outqueue))) { | ||
875 | if (usbvision->streaming == Stream_Idle) | ||
876 | return -EINVAL; | ||
877 | ret = wait_event_interruptible | ||
878 | (usbvision->wait_frame, | ||
879 | !list_empty(&(usbvision->outqueue))); | ||
880 | if (ret) | ||
881 | return ret; | ||
882 | } | ||
883 | |||
884 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
885 | f = list_entry(usbvision->outqueue.next, | ||
886 | struct usbvision_frame, frame); | ||
887 | list_del(usbvision->outqueue.next); | ||
888 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
889 | |||
890 | f->grabstate = FrameState_Unused; | ||
891 | |||
892 | vb->memory = V4L2_MEMORY_MMAP; | ||
893 | vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE; | ||
894 | vb->index = f->index; | ||
895 | vb->sequence = f->sequence; | ||
896 | vb->timestamp = f->timestamp; | ||
897 | vb->field = V4L2_FIELD_NONE; | ||
898 | vb->bytesused = f->scanlength; | ||
899 | |||
900 | return 0; | ||
901 | } | ||
902 | case VIDIOC_STREAMON: | ||
903 | { | ||
904 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
905 | |||
906 | usbvision->streaming = Stream_On; | ||
907 | |||
908 | call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); | ||
909 | |||
910 | PDEBUG(DBG_IOCTL, "VIDIOC_STREAMON"); | ||
911 | |||
912 | return 0; | ||
913 | } | ||
914 | case VIDIOC_STREAMOFF: | ||
915 | { | ||
916 | int *type = arg; | ||
917 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
918 | |||
919 | if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
920 | return -EINVAL; | ||
921 | |||
922 | if(usbvision->streaming == Stream_On) { | ||
923 | usbvision_stream_interrupt(usbvision); | ||
924 | // Stop all video streamings | ||
925 | call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); | ||
926 | } | ||
927 | usbvision_empty_framequeues(usbvision); | ||
928 | |||
929 | PDEBUG(DBG_IOCTL, "VIDIOC_STREAMOFF"); | ||
930 | return 0; | ||
931 | } | ||
932 | case VIDIOC_ENUM_FMT: | ||
933 | { | ||
934 | struct v4l2_fmtdesc *vfd = arg; | ||
935 | |||
936 | if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { | ||
937 | return -EINVAL; | ||
938 | } | ||
939 | vfd->flags = 0; | ||
940 | vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
941 | strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); | ||
942 | vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; | ||
943 | memset(vfd->reserved, 0, sizeof(vfd->reserved)); | ||
944 | return 0; | ||
945 | } | ||
946 | case VIDIOC_G_FMT: | ||
947 | { | ||
948 | struct v4l2_format *vf = arg; | ||
949 | |||
950 | switch (vf->type) { | ||
951 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
952 | { | ||
953 | vf->fmt.pix.width = usbvision->curwidth; | ||
954 | vf->fmt.pix.height = usbvision->curheight; | ||
955 | vf->fmt.pix.pixelformat = usbvision->palette.format; | ||
956 | vf->fmt.pix.bytesperline = usbvision->curwidth*usbvision->palette.bytes_per_pixel; | ||
957 | vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight; | ||
958 | vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
959 | vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */ | ||
960 | PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT w=%d, h=%d, format=%s", | ||
961 | vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); | ||
962 | return 0; | ||
963 | } | ||
964 | default: | ||
965 | PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT invalid type %d",vf->type); | ||
966 | return -EINVAL; | ||
967 | } | ||
968 | return 0; | ||
969 | } | ||
970 | case VIDIOC_TRY_FMT: | ||
971 | case VIDIOC_S_FMT: | ||
972 | { | ||
973 | struct v4l2_format *vf = arg; | ||
974 | int formatIdx,ret; | ||
975 | |||
976 | switch(vf->type) { | ||
977 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
978 | { | ||
979 | /* Find requested format in available ones */ | ||
980 | for(formatIdx=0;formatIdx<USBVISION_SUPPORTED_PALETTES;formatIdx++) { | ||
981 | if(vf->fmt.pix.pixelformat == usbvision_v4l2_format[formatIdx].format) { | ||
982 | usbvision->palette = usbvision_v4l2_format[formatIdx]; | ||
983 | break; | ||
984 | } | ||
985 | } | ||
986 | /* robustness */ | ||
987 | if(formatIdx == USBVISION_SUPPORTED_PALETTES) { | ||
988 | return -EINVAL; | ||
989 | } | ||
990 | RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); | ||
991 | RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT); | ||
992 | |||
993 | vf->fmt.pix.bytesperline = vf->fmt.pix.width*usbvision->palette.bytes_per_pixel; | ||
994 | vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height; | ||
995 | |||
996 | if(cmd == VIDIOC_TRY_FMT) { | ||
997 | PDEBUG(DBG_IOCTL, "VIDIOC_TRY_FMT grabdisplay w=%d, h=%d, format=%s", | ||
998 | vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); | ||
999 | return 0; | ||
1000 | } | ||
1001 | |||
1002 | /* stop io in case it is already in progress */ | ||
1003 | if(usbvision->streaming == Stream_On) { | ||
1004 | if ((ret = usbvision_stream_interrupt(usbvision))) | ||
1005 | return ret; | ||
1006 | } | ||
1007 | usbvision_empty_framequeues(usbvision); | ||
1008 | |||
1009 | usbvision->curFrame = NULL; | ||
1010 | |||
1011 | // by now we are committed to the new data... | ||
1012 | down(&usbvision->lock); | ||
1013 | usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); | ||
1014 | up(&usbvision->lock); | ||
1015 | |||
1016 | PDEBUG(DBG_IOCTL, "VIDIOC_S_FMT grabdisplay w=%d, h=%d, format=%s", | ||
1017 | vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); | ||
1018 | return 0; | ||
1019 | } | ||
1020 | default: | ||
1021 | return -EINVAL; | ||
1022 | } | ||
1023 | } | ||
1024 | default: | ||
1025 | return -ENOIOCTLCMD; | ||
1026 | } | ||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1030 | static int usbvision_v4l2_ioctl(struct inode *inode, struct file *file, | ||
1031 | unsigned int cmd, unsigned long arg) | ||
1032 | { | ||
1033 | return video_usercopy(inode, file, cmd, arg, usbvision_v4l2_do_ioctl); | ||
1034 | } | ||
1035 | |||
1036 | |||
1037 | static ssize_t usbvision_v4l2_read(struct file *file, char *buf, | ||
1038 | size_t count, loff_t *ppos) | ||
1039 | { | ||
1040 | struct video_device *dev = video_devdata(file); | ||
1041 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1042 | int noblock = file->f_flags & O_NONBLOCK; | ||
1043 | unsigned long lock_flags; | ||
1044 | |||
1045 | int frmx = -1; | ||
1046 | int ret,i; | ||
1047 | struct usbvision_frame *frame; | ||
1048 | |||
1049 | PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, (unsigned long)count, noblock); | ||
1050 | |||
1051 | if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) | ||
1052 | return -EFAULT; | ||
1053 | |||
1054 | /* no stream is running, make it running ! */ | ||
1055 | usbvision->streaming = Stream_On; | ||
1056 | call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL); | ||
1057 | |||
1058 | /* First, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */ | ||
1059 | for(i=0;i<USBVISION_NUMFRAMES;i++) { | ||
1060 | frame = &usbvision->frame[i]; | ||
1061 | if(frame->grabstate == FrameState_Unused) { | ||
1062 | /* Mark it as ready and enqueue frame */ | ||
1063 | frame->grabstate = FrameState_Ready; | ||
1064 | frame->scanstate = ScanState_Scanning; | ||
1065 | frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ | ||
1066 | |||
1067 | /* set v4l2_format index */ | ||
1068 | frame->v4l2_format = usbvision->palette; | ||
1069 | |||
1070 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
1071 | list_add_tail(&frame->frame, &usbvision->inqueue); | ||
1072 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1076 | /* Then try to steal a frame (like a VIDIOC_DQBUF would do) */ | ||
1077 | if (list_empty(&(usbvision->outqueue))) { | ||
1078 | if(noblock) | ||
1079 | return -EAGAIN; | ||
1080 | |||
1081 | ret = wait_event_interruptible | ||
1082 | (usbvision->wait_frame, | ||
1083 | !list_empty(&(usbvision->outqueue))); | ||
1084 | if (ret) | ||
1085 | return ret; | ||
1086 | } | ||
1087 | |||
1088 | spin_lock_irqsave(&usbvision->queue_lock, lock_flags); | ||
1089 | frame = list_entry(usbvision->outqueue.next, | ||
1090 | struct usbvision_frame, frame); | ||
1091 | list_del(usbvision->outqueue.next); | ||
1092 | spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); | ||
1093 | |||
1094 | /* An error returns an empty frame */ | ||
1095 | if (frame->grabstate == FrameState_Error) { | ||
1096 | frame->bytes_read = 0; | ||
1097 | return 0; | ||
1098 | } | ||
1099 | |||
1100 | PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", __FUNCTION__, | ||
1101 | frame->index, frame->bytes_read, frame->scanlength); | ||
1102 | |||
1103 | /* copy bytes to user space; we allow for partials reads */ | ||
1104 | if ((count + frame->bytes_read) > (unsigned long)frame->scanlength) | ||
1105 | count = frame->scanlength - frame->bytes_read; | ||
1106 | |||
1107 | if (copy_to_user(buf, frame->data + frame->bytes_read, count)) { | ||
1108 | return -EFAULT; | ||
1109 | } | ||
1110 | |||
1111 | frame->bytes_read += count; | ||
1112 | PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", __FUNCTION__, | ||
1113 | (unsigned long)count, frame->bytes_read); | ||
1114 | |||
1115 | // For now, forget the frame if it has not been read in one shot. | ||
1116 | /* if (frame->bytes_read >= frame->scanlength) {// All data has been read */ | ||
1117 | frame->bytes_read = 0; | ||
1118 | |||
1119 | /* Mark it as available to be used again. */ | ||
1120 | usbvision->frame[frmx].grabstate = FrameState_Unused; | ||
1121 | /* } */ | ||
1122 | |||
1123 | return count; | ||
1124 | } | ||
1125 | |||
1126 | static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | ||
1127 | { | ||
1128 | unsigned long size = vma->vm_end - vma->vm_start, | ||
1129 | start = vma->vm_start; | ||
1130 | void *pos; | ||
1131 | u32 i; | ||
1132 | |||
1133 | struct video_device *dev = video_devdata(file); | ||
1134 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1135 | |||
1136 | down(&usbvision->lock); | ||
1137 | |||
1138 | if (!USBVISION_IS_OPERATIONAL(usbvision)) { | ||
1139 | up(&usbvision->lock); | ||
1140 | return -EFAULT; | ||
1141 | } | ||
1142 | |||
1143 | if (!(vma->vm_flags & VM_WRITE) || | ||
1144 | size != PAGE_ALIGN(usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel)) { | ||
1145 | up(&usbvision->lock); | ||
1146 | return -EINVAL; | ||
1147 | } | ||
1148 | |||
1149 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | ||
1150 | if (((usbvision->max_frame_size*i) >> PAGE_SHIFT) == vma->vm_pgoff) | ||
1151 | break; | ||
1152 | } | ||
1153 | if (i == USBVISION_NUMFRAMES) { | ||
1154 | PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range"); | ||
1155 | up(&usbvision->lock); | ||
1156 | return -EINVAL; | ||
1157 | } | ||
1158 | |||
1159 | /* VM_IO is eventually going to replace PageReserved altogether */ | ||
1160 | vma->vm_flags |= VM_IO; | ||
1161 | vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ | ||
1162 | |||
1163 | pos = usbvision->frame[i].data; | ||
1164 | while (size > 0) { | ||
1165 | |||
1166 | if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { | ||
1167 | PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed"); | ||
1168 | up(&usbvision->lock); | ||
1169 | return -EAGAIN; | ||
1170 | } | ||
1171 | start += PAGE_SIZE; | ||
1172 | pos += PAGE_SIZE; | ||
1173 | size -= PAGE_SIZE; | ||
1174 | } | ||
1175 | |||
1176 | up(&usbvision->lock); | ||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | |||
1181 | /* | ||
1182 | * Here comes the stuff for radio on usbvision based devices | ||
1183 | * | ||
1184 | */ | ||
1185 | static int usbvision_radio_open(struct inode *inode, struct file *file) | ||
1186 | { | ||
1187 | struct video_device *dev = video_devdata(file); | ||
1188 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1189 | struct v4l2_frequency freq; | ||
1190 | int errCode = 0; | ||
1191 | |||
1192 | PDEBUG(DBG_IO, "%s:", __FUNCTION__); | ||
1193 | |||
1194 | down(&usbvision->lock); | ||
1195 | |||
1196 | if (usbvision->user) { | ||
1197 | err("%s: Someone tried to open an already opened USBVision Radio!", __FUNCTION__); | ||
1198 | errCode = -EBUSY; | ||
1199 | } | ||
1200 | else { | ||
1201 | if(PowerOnAtOpen) { | ||
1202 | usbvision_reset_powerOffTimer(usbvision); | ||
1203 | if (usbvision->power == 0) { | ||
1204 | usbvision_power_on(usbvision); | ||
1205 | usbvision_init_i2c(usbvision); | ||
1206 | } | ||
1207 | } | ||
1208 | |||
1209 | // If so far no errors then we shall start the radio | ||
1210 | usbvision->radio = 1; | ||
1211 | call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type); | ||
1212 | freq.frequency = 1517; //SWR3 @ 94.8MHz | ||
1213 | call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, &freq); | ||
1214 | usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO); | ||
1215 | usbvision->user++; | ||
1216 | } | ||
1217 | |||
1218 | if (errCode) { | ||
1219 | if (PowerOnAtOpen) { | ||
1220 | usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); | ||
1221 | usbvision_power_off(usbvision); | ||
1222 | usbvision->initialized = 0; | ||
1223 | } | ||
1224 | } | ||
1225 | up(&usbvision->lock); | ||
1226 | return errCode; | ||
1227 | } | ||
1228 | |||
1229 | |||
1230 | static int usbvision_radio_close(struct inode *inode, struct file *file) | ||
1231 | { | ||
1232 | struct video_device *dev = video_devdata(file); | ||
1233 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1234 | int errCode = 0; | ||
1235 | |||
1236 | PDEBUG(DBG_IO, ""); | ||
1237 | |||
1238 | down(&usbvision->lock); | ||
1239 | |||
1240 | usbvision_audio_off(usbvision); | ||
1241 | usbvision->radio=0; | ||
1242 | usbvision->user--; | ||
1243 | |||
1244 | if (PowerOnAtOpen) { | ||
1245 | usbvision_set_powerOffTimer(usbvision); | ||
1246 | usbvision->initialized = 0; | ||
1247 | } | ||
1248 | |||
1249 | up(&usbvision->lock); | ||
1250 | |||
1251 | if (usbvision->remove_pending) { | ||
1252 | info("%s: Final disconnect", __FUNCTION__); | ||
1253 | usbvision_release(usbvision); | ||
1254 | } | ||
1255 | |||
1256 | |||
1257 | PDEBUG(DBG_IO, "success"); | ||
1258 | |||
1259 | return errCode; | ||
1260 | } | ||
1261 | |||
1262 | static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file, | ||
1263 | unsigned int cmd, void *arg) | ||
1264 | { | ||
1265 | struct video_device *dev = video_devdata(file); | ||
1266 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | ||
1267 | |||
1268 | if (!USBVISION_IS_OPERATIONAL(usbvision)) | ||
1269 | return -EIO; | ||
1270 | |||
1271 | switch (cmd) { | ||
1272 | case VIDIOC_QUERYCAP: | ||
1273 | { | ||
1274 | struct v4l2_capability *vc=arg; | ||
1275 | |||
1276 | memset(vc, 0, sizeof(*vc)); | ||
1277 | strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); | ||
1278 | strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, | ||
1279 | sizeof(vc->card)); | ||
1280 | strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, | ||
1281 | sizeof(vc->bus_info)); | ||
1282 | vc->version = USBVISION_DRIVER_VERSION; | ||
1283 | vc->capabilities = (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); | ||
1284 | PDEBUG(DBG_IO, "VIDIOC_QUERYCAP"); | ||
1285 | return 0; | ||
1286 | } | ||
1287 | case VIDIOC_QUERYCTRL: | ||
1288 | { | ||
1289 | struct v4l2_queryctrl *ctrl = arg; | ||
1290 | int id=ctrl->id; | ||
1291 | |||
1292 | memset(ctrl,0,sizeof(*ctrl)); | ||
1293 | ctrl->id=id; | ||
1294 | |||
1295 | call_i2c_clients(usbvision, cmd, arg); | ||
1296 | PDEBUG(DBG_IO,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type); | ||
1297 | |||
1298 | if (ctrl->type) | ||
1299 | return 0; | ||
1300 | else | ||
1301 | return -EINVAL; | ||
1302 | |||
1303 | } | ||
1304 | case VIDIOC_G_CTRL: | ||
1305 | { | ||
1306 | struct v4l2_control *ctrl = arg; | ||
1307 | |||
1308 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); | ||
1309 | PDEBUG(DBG_IO,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
1310 | return 0; | ||
1311 | } | ||
1312 | case VIDIOC_S_CTRL: | ||
1313 | { | ||
1314 | struct v4l2_control *ctrl = arg; | ||
1315 | |||
1316 | call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); | ||
1317 | PDEBUG(DBG_IO, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value); | ||
1318 | return 0; | ||
1319 | } | ||
1320 | case VIDIOC_G_TUNER: | ||
1321 | { | ||
1322 | struct v4l2_tuner *t = arg; | ||
1323 | |||
1324 | if (t->index > 0) | ||
1325 | return -EINVAL; | ||
1326 | |||
1327 | memset(t,0,sizeof(*t)); | ||
1328 | strcpy(t->name, "Radio"); | ||
1329 | t->type = V4L2_TUNER_RADIO; | ||
1330 | |||
1331 | /* Let clients fill in the remainder of this struct */ | ||
1332 | call_i2c_clients(usbvision,VIDIOC_G_TUNER,t); | ||
1333 | PDEBUG(DBG_IO, "VIDIOC_G_TUNER signal=%x, afc=%x",t->signal,t->afc); | ||
1334 | return 0; | ||
1335 | } | ||
1336 | case VIDIOC_S_TUNER: | ||
1337 | { | ||
1338 | struct v4l2_tuner *vt = arg; | ||
1339 | |||
1340 | // Only no or one tuner for now | ||
1341 | if (!usbvision->have_tuner || vt->index) | ||
1342 | return -EINVAL; | ||
1343 | /* let clients handle this */ | ||
1344 | call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); | ||
1345 | |||
1346 | PDEBUG(DBG_IO, "VIDIOC_S_TUNER"); | ||
1347 | return 0; | ||
1348 | } | ||
1349 | case VIDIOC_G_AUDIO: | ||
1350 | { | ||
1351 | struct v4l2_audio *a = arg; | ||
1352 | |||
1353 | memset(a,0,sizeof(*a)); | ||
1354 | strcpy(a->name,"Radio"); | ||
1355 | PDEBUG(DBG_IO, "VIDIOC_G_AUDIO"); | ||
1356 | return 0; | ||
1357 | } | ||
1358 | case VIDIOC_S_AUDIO: | ||
1359 | case VIDIOC_S_INPUT: | ||
1360 | case VIDIOC_S_STD: | ||
1361 | return 0; | ||
1362 | |||
1363 | case VIDIOC_G_FREQUENCY: | ||
1364 | { | ||
1365 | struct v4l2_frequency *f = arg; | ||
1366 | |||
1367 | memset(f,0,sizeof(*f)); | ||
1368 | |||
1369 | f->type = V4L2_TUNER_RADIO; | ||
1370 | f->frequency = usbvision->freq; | ||
1371 | call_i2c_clients(usbvision, cmd, f); | ||
1372 | PDEBUG(DBG_IO, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)f->frequency); | ||
1373 | |||
1374 | return 0; | ||
1375 | } | ||
1376 | case VIDIOC_S_FREQUENCY: | ||
1377 | { | ||
1378 | struct v4l2_frequency *f = arg; | ||
1379 | |||
1380 | if (f->tuner != 0) | ||
1381 | return -EINVAL; | ||
1382 | usbvision->freq = f->frequency; | ||
1383 | call_i2c_clients(usbvision, cmd, f); | ||
1384 | PDEBUG(DBG_IO, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)f->frequency); | ||
1385 | |||
1386 | return 0; | ||
1387 | } | ||
1388 | default: | ||
1389 | { | ||
1390 | PDEBUG(DBG_IO, "%s: Unknown command %x", __FUNCTION__, cmd); | ||
1391 | return -ENOIOCTLCMD; | ||
1392 | } | ||
1393 | } | ||
1394 | return 0; | ||
1395 | } | ||
1396 | |||
1397 | |||
1398 | static int usbvision_radio_ioctl(struct inode *inode, struct file *file, | ||
1399 | unsigned int cmd, unsigned long arg) | ||
1400 | { | ||
1401 | return video_usercopy(inode, file, cmd, arg, usbvision_do_radio_ioctl); | ||
1402 | } | ||
1403 | |||
1404 | |||
1405 | /* | ||
1406 | * Here comes the stuff for vbi on usbvision based devices | ||
1407 | * | ||
1408 | */ | ||
1409 | static int usbvision_vbi_open(struct inode *inode, struct file *file) | ||
1410 | { | ||
1411 | /* TODO */ | ||
1412 | return -EINVAL; | ||
1413 | |||
1414 | } | ||
1415 | |||
1416 | static int usbvision_vbi_close(struct inode *inode, struct file *file) | ||
1417 | { | ||
1418 | /* TODO */ | ||
1419 | return -EINVAL; | ||
1420 | } | ||
1421 | |||
1422 | static int usbvision_do_vbi_ioctl(struct inode *inode, struct file *file, | ||
1423 | unsigned int cmd, void *arg) | ||
1424 | { | ||
1425 | /* TODO */ | ||
1426 | return -EINVAL; | ||
1427 | } | ||
1428 | |||
1429 | static int usbvision_vbi_ioctl(struct inode *inode, struct file *file, | ||
1430 | unsigned int cmd, unsigned long arg) | ||
1431 | { | ||
1432 | return video_usercopy(inode, file, cmd, arg, usbvision_do_vbi_ioctl); | ||
1433 | } | ||
1434 | |||
1435 | |||
1436 | // | ||
1437 | // Video registration stuff | ||
1438 | // | ||
1439 | |||
1440 | // Video template | ||
1441 | static struct file_operations usbvision_fops = { | ||
1442 | .owner = THIS_MODULE, | ||
1443 | .open = usbvision_v4l2_open, | ||
1444 | .release = usbvision_v4l2_close, | ||
1445 | .read = usbvision_v4l2_read, | ||
1446 | .mmap = usbvision_v4l2_mmap, | ||
1447 | .ioctl = usbvision_v4l2_ioctl, | ||
1448 | .llseek = no_llseek, | ||
1449 | }; | ||
1450 | static struct video_device usbvision_video_template = { | ||
1451 | .owner = THIS_MODULE, | ||
1452 | .type = VID_TYPE_TUNER | VID_TYPE_CAPTURE, | ||
1453 | .hardware = VID_HARDWARE_USBVISION, | ||
1454 | .fops = &usbvision_fops, | ||
1455 | .name = "usbvision-video", | ||
1456 | .release = video_device_release, | ||
1457 | .minor = -1, | ||
1458 | }; | ||
1459 | |||
1460 | |||
1461 | // Radio template | ||
1462 | static struct file_operations usbvision_radio_fops = { | ||
1463 | .owner = THIS_MODULE, | ||
1464 | .open = usbvision_radio_open, | ||
1465 | .release = usbvision_radio_close, | ||
1466 | .ioctl = usbvision_radio_ioctl, | ||
1467 | .llseek = no_llseek, | ||
1468 | }; | ||
1469 | |||
1470 | static struct video_device usbvision_radio_template= | ||
1471 | { | ||
1472 | .owner = THIS_MODULE, | ||
1473 | .type = VID_TYPE_TUNER, | ||
1474 | .hardware = VID_HARDWARE_USBVISION, | ||
1475 | .fops = &usbvision_radio_fops, | ||
1476 | .release = video_device_release, | ||
1477 | .name = "usbvision-radio", | ||
1478 | .minor = -1, | ||
1479 | }; | ||
1480 | |||
1481 | |||
1482 | // vbi template | ||
1483 | static struct file_operations usbvision_vbi_fops = { | ||
1484 | .owner = THIS_MODULE, | ||
1485 | .open = usbvision_vbi_open, | ||
1486 | .release = usbvision_vbi_close, | ||
1487 | .ioctl = usbvision_vbi_ioctl, | ||
1488 | .llseek = no_llseek, | ||
1489 | }; | ||
1490 | |||
1491 | static struct video_device usbvision_vbi_template= | ||
1492 | { | ||
1493 | .owner = THIS_MODULE, | ||
1494 | .type = VID_TYPE_TUNER, | ||
1495 | .hardware = VID_HARDWARE_USBVISION, | ||
1496 | .fops = &usbvision_vbi_fops, | ||
1497 | .release = video_device_release, | ||
1498 | .name = "usbvision-vbi", | ||
1499 | .minor = -1, | ||
1500 | }; | ||
1501 | |||
1502 | |||
1503 | static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, | ||
1504 | struct video_device *vdev_template, | ||
1505 | char *name) | ||
1506 | { | ||
1507 | struct usb_device *usb_dev = usbvision->dev; | ||
1508 | struct video_device *vdev; | ||
1509 | |||
1510 | if (usb_dev == NULL) { | ||
1511 | err("%s: usbvision->dev is not set", __FUNCTION__); | ||
1512 | return NULL; | ||
1513 | } | ||
1514 | |||
1515 | vdev = video_device_alloc(); | ||
1516 | if (NULL == vdev) { | ||
1517 | return NULL; | ||
1518 | } | ||
1519 | *vdev = *vdev_template; | ||
1520 | // vdev->minor = -1; | ||
1521 | vdev->dev = &usb_dev->dev; | ||
1522 | snprintf(vdev->name, sizeof(vdev->name), "%s", name); | ||
1523 | video_set_drvdata(vdev, usbvision); | ||
1524 | return vdev; | ||
1525 | } | ||
1526 | |||
1527 | // unregister video4linux devices | ||
1528 | static void usbvision_unregister_video(struct usb_usbvision *usbvision) | ||
1529 | { | ||
1530 | // vbi Device: | ||
1531 | if (usbvision->vbi) { | ||
1532 | PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", usbvision->vbi->minor & 0x1f); | ||
1533 | if (usbvision->vbi->minor != -1) { | ||
1534 | video_unregister_device(usbvision->vbi); | ||
1535 | } | ||
1536 | else { | ||
1537 | video_device_release(usbvision->vbi); | ||
1538 | } | ||
1539 | usbvision->vbi = NULL; | ||
1540 | } | ||
1541 | |||
1542 | // Radio Device: | ||
1543 | if (usbvision->rdev) { | ||
1544 | PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", usbvision->rdev->minor & 0x1f); | ||
1545 | if (usbvision->rdev->minor != -1) { | ||
1546 | video_unregister_device(usbvision->rdev); | ||
1547 | } | ||
1548 | else { | ||
1549 | video_device_release(usbvision->rdev); | ||
1550 | } | ||
1551 | usbvision->rdev = NULL; | ||
1552 | } | ||
1553 | |||
1554 | // Video Device: | ||
1555 | if (usbvision->vdev) { | ||
1556 | PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", usbvision->vdev->minor & 0x1f); | ||
1557 | if (usbvision->vdev->minor != -1) { | ||
1558 | video_unregister_device(usbvision->vdev); | ||
1559 | } | ||
1560 | else { | ||
1561 | video_device_release(usbvision->vdev); | ||
1562 | } | ||
1563 | usbvision->vdev = NULL; | ||
1564 | } | ||
1565 | } | ||
1566 | |||
1567 | // register video4linux devices | ||
1568 | static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | ||
1569 | { | ||
1570 | // Video Device: | ||
1571 | usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video"); | ||
1572 | if (usbvision->vdev == NULL) { | ||
1573 | goto err_exit; | ||
1574 | } | ||
1575 | if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) { | ||
1576 | goto err_exit; | ||
1577 | } | ||
1578 | info("USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]", usbvision->nr,usbvision->vdev->minor & 0x1f); | ||
1579 | |||
1580 | // Radio Device: | ||
1581 | if (usbvision_device_data[usbvision->DevModel].Radio) { | ||
1582 | // usbvision has radio | ||
1583 | usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio"); | ||
1584 | if (usbvision->rdev == NULL) { | ||
1585 | goto err_exit; | ||
1586 | } | ||
1587 | if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) { | ||
1588 | goto err_exit; | ||
1589 | } | ||
1590 | info("USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]", usbvision->nr, usbvision->rdev->minor & 0x1f); | ||
1591 | } | ||
1592 | // vbi Device: | ||
1593 | if (usbvision_device_data[usbvision->DevModel].vbi) { | ||
1594 | usbvision->vbi = usbvision_vdev_init(usbvision, &usbvision_vbi_template, "USBVision VBI"); | ||
1595 | if (usbvision->vdev == NULL) { | ||
1596 | goto err_exit; | ||
1597 | } | ||
1598 | if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) { | ||
1599 | goto err_exit; | ||
1600 | } | ||
1601 | info("USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)", usbvision->nr,usbvision->vbi->minor & 0x1f); | ||
1602 | } | ||
1603 | // all done | ||
1604 | return 0; | ||
1605 | |||
1606 | err_exit: | ||
1607 | err("USBVision[%d]: video_register_device() failed", usbvision->nr); | ||
1608 | usbvision_unregister_video(usbvision); | ||
1609 | return -1; | ||
1610 | } | ||
1611 | |||
1612 | /* | ||
1613 | * usbvision_alloc() | ||
1614 | * | ||
1615 | * This code allocates the struct usb_usbvision. It is filled with default values. | ||
1616 | * | ||
1617 | * Returns NULL on error, a pointer to usb_usbvision else. | ||
1618 | * | ||
1619 | */ | ||
1620 | static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) | ||
1621 | { | ||
1622 | struct usb_usbvision *usbvision; | ||
1623 | |||
1624 | if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) { | ||
1625 | goto err_exit; | ||
1626 | } | ||
1627 | |||
1628 | usbvision->dev = dev; | ||
1629 | |||
1630 | init_MUTEX(&usbvision->lock); /* to 1 == available */ | ||
1631 | |||
1632 | // prepare control urb for control messages during interrupts | ||
1633 | usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); | ||
1634 | if (usbvision->ctrlUrb == NULL) { | ||
1635 | goto err_exit; | ||
1636 | } | ||
1637 | init_waitqueue_head(&usbvision->ctrlUrb_wq); | ||
1638 | init_MUTEX(&usbvision->ctrlUrbLock); /* to 1 == available */ | ||
1639 | |||
1640 | usbvision_init_powerOffTimer(usbvision); | ||
1641 | |||
1642 | return usbvision; | ||
1643 | |||
1644 | err_exit: | ||
1645 | if (usbvision && usbvision->ctrlUrb) { | ||
1646 | usb_free_urb(usbvision->ctrlUrb); | ||
1647 | } | ||
1648 | if (usbvision) { | ||
1649 | kfree(usbvision); | ||
1650 | } | ||
1651 | return NULL; | ||
1652 | } | ||
1653 | |||
1654 | /* | ||
1655 | * usbvision_release() | ||
1656 | * | ||
1657 | * This code does final release of struct usb_usbvision. This happens | ||
1658 | * after the device is disconnected -and- all clients closed their files. | ||
1659 | * | ||
1660 | */ | ||
1661 | static void usbvision_release(struct usb_usbvision *usbvision) | ||
1662 | { | ||
1663 | PDEBUG(DBG_PROBE, ""); | ||
1664 | |||
1665 | down(&usbvision->lock); | ||
1666 | |||
1667 | usbvision_reset_powerOffTimer(usbvision); | ||
1668 | |||
1669 | usbvision->initialized = 0; | ||
1670 | |||
1671 | up(&usbvision->lock); | ||
1672 | |||
1673 | usbvision_remove_sysfs(usbvision->vdev); | ||
1674 | usbvision_unregister_video(usbvision); | ||
1675 | |||
1676 | if (usbvision->ctrlUrb) { | ||
1677 | usb_free_urb(usbvision->ctrlUrb); | ||
1678 | } | ||
1679 | |||
1680 | kfree(usbvision); | ||
1681 | |||
1682 | PDEBUG(DBG_PROBE, "success"); | ||
1683 | } | ||
1684 | |||
1685 | |||
1686 | /******************************** usb interface *****************************************/ | ||
1687 | |||
1688 | static void usbvision_configure_video(struct usb_usbvision *usbvision) | ||
1689 | { | ||
1690 | int model,i; | ||
1691 | |||
1692 | if (usbvision == NULL) | ||
1693 | return; | ||
1694 | |||
1695 | model = usbvision->DevModel; | ||
1696 | usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24; | ||
1697 | |||
1698 | if (usbvision_device_data[usbvision->DevModel].Vin_Reg2 >= 0) { | ||
1699 | usbvision->Vin_Reg2_Preset = usbvision_device_data[usbvision->DevModel].Vin_Reg2 & 0xff; | ||
1700 | } else { | ||
1701 | usbvision->Vin_Reg2_Preset = 0; | ||
1702 | } | ||
1703 | |||
1704 | for (i = 0; i < TVNORMS; i++) | ||
1705 | if (usbvision_device_data[model].VideoNorm == tvnorms[i].mode) | ||
1706 | break; | ||
1707 | if (i == TVNORMS) | ||
1708 | i = 0; | ||
1709 | usbvision->tvnorm = &tvnorms[i]; /* set default norm */ | ||
1710 | |||
1711 | usbvision->video_inputs = usbvision_device_data[model].VideoChannels; | ||
1712 | usbvision->ctl_input = 0; | ||
1713 | |||
1714 | /* This should be here to make i2c clients to be able to register */ | ||
1715 | usbvision_audio_off(usbvision); //first switch off audio | ||
1716 | if (!PowerOnAtOpen) { | ||
1717 | usbvision_power_on(usbvision); //and then power up the noisy tuner | ||
1718 | usbvision_init_i2c(usbvision); | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | /* | ||
1723 | * usbvision_probe() | ||
1724 | * | ||
1725 | * This procedure queries device descriptor and accepts the interface | ||
1726 | * if it looks like USBVISION video device | ||
1727 | * | ||
1728 | */ | ||
1729 | static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid) | ||
1730 | { | ||
1731 | struct usb_device *dev = interface_to_usbdev(intf); | ||
1732 | __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; | ||
1733 | const struct usb_host_interface *interface; | ||
1734 | struct usb_usbvision *usbvision = NULL; | ||
1735 | const struct usb_endpoint_descriptor *endpoint; | ||
1736 | int model; | ||
1737 | |||
1738 | PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", | ||
1739 | dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); | ||
1740 | /* Is it an USBVISION video dev? */ | ||
1741 | model = 0; | ||
1742 | for(model = 0; usbvision_device_data[model].idVendor; model++) { | ||
1743 | if (le16_to_cpu(dev->descriptor.idVendor) != usbvision_device_data[model].idVendor) { | ||
1744 | continue; | ||
1745 | } | ||
1746 | if (le16_to_cpu(dev->descriptor.idProduct) != usbvision_device_data[model].idProduct) { | ||
1747 | continue; | ||
1748 | } | ||
1749 | |||
1750 | info("%s: %s found", __FUNCTION__, usbvision_device_data[model].ModelString); | ||
1751 | break; | ||
1752 | } | ||
1753 | |||
1754 | if (usbvision_device_data[model].idVendor == 0) { | ||
1755 | return -ENODEV; //no matching device | ||
1756 | } | ||
1757 | if (usbvision_device_data[model].Interface >= 0) { | ||
1758 | interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0]; | ||
1759 | } | ||
1760 | else { | ||
1761 | interface = &dev->actconfig->interface[ifnum]->altsetting[0]; | ||
1762 | } | ||
1763 | endpoint = &interface->endpoint[1].desc; | ||
1764 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { | ||
1765 | err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum); | ||
1766 | err("%s: Endpoint attribures %d", __FUNCTION__, endpoint->bmAttributes); | ||
1767 | return -ENODEV; | ||
1768 | } | ||
1769 | if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { | ||
1770 | err("%s: interface %d. has ISO OUT endpoint!", __FUNCTION__, ifnum); | ||
1771 | return -ENODEV; | ||
1772 | } | ||
1773 | |||
1774 | usb_get_dev(dev); | ||
1775 | |||
1776 | if ((usbvision = usbvision_alloc(dev)) == NULL) { | ||
1777 | err("%s: couldn't allocate USBVision struct", __FUNCTION__); | ||
1778 | return -ENOMEM; | ||
1779 | } | ||
1780 | if (dev->descriptor.bNumConfigurations > 1) { | ||
1781 | usbvision->bridgeType = BRIDGE_NT1004; | ||
1782 | } | ||
1783 | else if (usbvision_device_data[model].ModelString == "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)") { | ||
1784 | usbvision->bridgeType = BRIDGE_NT1005; | ||
1785 | } | ||
1786 | else { | ||
1787 | usbvision->bridgeType = BRIDGE_NT1003; | ||
1788 | } | ||
1789 | PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType); | ||
1790 | |||
1791 | down(&usbvision->lock); | ||
1792 | |||
1793 | usbvision->nr = usbvision_nr++; | ||
1794 | |||
1795 | usbvision->have_tuner = usbvision_device_data[model].Tuner; | ||
1796 | if (usbvision->have_tuner) { | ||
1797 | usbvision->tuner_type = usbvision_device_data[model].TunerType; | ||
1798 | } | ||
1799 | |||
1800 | usbvision->tuner_addr = ADDR_UNSET; | ||
1801 | |||
1802 | usbvision->DevModel = model; | ||
1803 | usbvision->remove_pending = 0; | ||
1804 | usbvision->iface = ifnum; | ||
1805 | usbvision->ifaceAltInactive = 0; | ||
1806 | usbvision->ifaceAltActive = 1; | ||
1807 | usbvision->video_endp = endpoint->bEndpointAddress; | ||
1808 | usbvision->isocPacketSize = 0; | ||
1809 | usbvision->usb_bandwidth = 0; | ||
1810 | usbvision->user = 0; | ||
1811 | usbvision->streaming = Stream_Off; | ||
1812 | usbvision_register_video(usbvision); | ||
1813 | usbvision_configure_video(usbvision); | ||
1814 | up(&usbvision->lock); | ||
1815 | |||
1816 | |||
1817 | usb_set_intfdata (intf, usbvision); | ||
1818 | usbvision_create_sysfs(usbvision->vdev); | ||
1819 | |||
1820 | PDEBUG(DBG_PROBE, "success"); | ||
1821 | return 0; | ||
1822 | } | ||
1823 | |||
1824 | |||
1825 | /* | ||
1826 | * usbvision_disconnect() | ||
1827 | * | ||
1828 | * This procedure stops all driver activity, deallocates interface-private | ||
1829 | * structure (pointed by 'ptr') and after that driver should be removable | ||
1830 | * with no ill consequences. | ||
1831 | * | ||
1832 | */ | ||
1833 | static void __devexit usbvision_disconnect(struct usb_interface *intf) | ||
1834 | { | ||
1835 | struct usb_usbvision *usbvision = usb_get_intfdata(intf); | ||
1836 | |||
1837 | PDEBUG(DBG_PROBE, ""); | ||
1838 | |||
1839 | if (usbvision == NULL) { | ||
1840 | err("%s: usb_get_intfdata() failed", __FUNCTION__); | ||
1841 | return; | ||
1842 | } | ||
1843 | usb_set_intfdata (intf, NULL); | ||
1844 | |||
1845 | down(&usbvision->lock); | ||
1846 | |||
1847 | // At this time we ask to cancel outstanding URBs | ||
1848 | usbvision_stop_isoc(usbvision); | ||
1849 | |||
1850 | if (usbvision->power) { | ||
1851 | usbvision_i2c_usb_del_bus(&usbvision->i2c_adap); | ||
1852 | usbvision_power_off(usbvision); | ||
1853 | } | ||
1854 | usbvision->remove_pending = 1; // Now all ISO data will be ignored | ||
1855 | |||
1856 | usb_put_dev(usbvision->dev); | ||
1857 | usbvision->dev = NULL; // USB device is no more | ||
1858 | |||
1859 | up(&usbvision->lock); | ||
1860 | |||
1861 | if (usbvision->user) { | ||
1862 | info("%s: In use, disconnect pending", __FUNCTION__); | ||
1863 | wake_up_interruptible(&usbvision->wait_frame); | ||
1864 | wake_up_interruptible(&usbvision->wait_stream); | ||
1865 | } | ||
1866 | else { | ||
1867 | usbvision_release(usbvision); | ||
1868 | } | ||
1869 | |||
1870 | PDEBUG(DBG_PROBE, "success"); | ||
1871 | |||
1872 | } | ||
1873 | |||
1874 | static struct usb_driver usbvision_driver = { | ||
1875 | .name = "usbvision", | ||
1876 | .id_table = usbvision_table, | ||
1877 | .probe = usbvision_probe, | ||
1878 | .disconnect = usbvision_disconnect | ||
1879 | }; | ||
1880 | |||
1881 | /* | ||
1882 | * customdevice_process() | ||
1883 | * | ||
1884 | * This procedure preprocesses CustomDevice parameter if any | ||
1885 | * | ||
1886 | */ | ||
1887 | void customdevice_process(void) | ||
1888 | { | ||
1889 | usbvision_device_data[0]=usbvision_device_data[1]; | ||
1890 | usbvision_table[0]=usbvision_table[1]; | ||
1891 | |||
1892 | if(CustomDevice) | ||
1893 | { | ||
1894 | char *parse=CustomDevice; | ||
1895 | |||
1896 | PDEBUG(DBG_PROBE, "CustomDevide=%s", CustomDevice); | ||
1897 | |||
1898 | /*format is CustomDevice="0x0573 0x4D31 0 7113 3 PAL 1 1 1 5 -1 -1 -1 -1 -1" | ||
1899 | usbvision_device_data[0].idVendor; | ||
1900 | usbvision_device_data[0].idProduct; | ||
1901 | usbvision_device_data[0].Interface; | ||
1902 | usbvision_device_data[0].Codec; | ||
1903 | usbvision_device_data[0].VideoChannels; | ||
1904 | usbvision_device_data[0].VideoNorm; | ||
1905 | usbvision_device_data[0].AudioChannels; | ||
1906 | usbvision_device_data[0].Radio; | ||
1907 | usbvision_device_data[0].Tuner; | ||
1908 | usbvision_device_data[0].TunerType; | ||
1909 | usbvision_device_data[0].Vin_Reg1; | ||
1910 | usbvision_device_data[0].Vin_Reg2; | ||
1911 | usbvision_device_data[0].X_Offset; | ||
1912 | usbvision_device_data[0].Y_Offset; | ||
1913 | usbvision_device_data[0].Dvi_yuv; | ||
1914 | usbvision_device_data[0].ModelString; | ||
1915 | */ | ||
1916 | |||
1917 | rmspace(parse); | ||
1918 | usbvision_device_data[0].ModelString="USBVISION Custom Device"; | ||
1919 | |||
1920 | parse+=2; | ||
1921 | sscanf(parse,"%x",&usbvision_device_data[0].idVendor); | ||
1922 | goto2next(parse); | ||
1923 | PDEBUG(DBG_PROBE, "idVendor=0x%.4X", usbvision_device_data[0].idVendor); | ||
1924 | parse+=2; | ||
1925 | sscanf(parse,"%x",&usbvision_device_data[0].idProduct); | ||
1926 | goto2next(parse); | ||
1927 | PDEBUG(DBG_PROBE, "idProduct=0x%.4X", usbvision_device_data[0].idProduct); | ||
1928 | sscanf(parse,"%d",&usbvision_device_data[0].Interface); | ||
1929 | goto2next(parse); | ||
1930 | PDEBUG(DBG_PROBE, "Interface=%d", usbvision_device_data[0].Interface); | ||
1931 | sscanf(parse,"%d",&usbvision_device_data[0].Codec); | ||
1932 | goto2next(parse); | ||
1933 | PDEBUG(DBG_PROBE, "Codec=%d", usbvision_device_data[0].Codec); | ||
1934 | sscanf(parse,"%d",&usbvision_device_data[0].VideoChannels); | ||
1935 | goto2next(parse); | ||
1936 | PDEBUG(DBG_PROBE, "VideoChannels=%d", usbvision_device_data[0].VideoChannels); | ||
1937 | |||
1938 | switch(*parse) | ||
1939 | { | ||
1940 | case 'P': | ||
1941 | PDEBUG(DBG_PROBE, "VideoNorm=PAL"); | ||
1942 | usbvision_device_data[0].VideoNorm=VIDEO_MODE_PAL; | ||
1943 | break; | ||
1944 | |||
1945 | case 'S': | ||
1946 | PDEBUG(DBG_PROBE, "VideoNorm=SECAM"); | ||
1947 | usbvision_device_data[0].VideoNorm=VIDEO_MODE_SECAM; | ||
1948 | break; | ||
1949 | |||
1950 | case 'N': | ||
1951 | PDEBUG(DBG_PROBE, "VideoNorm=NTSC"); | ||
1952 | usbvision_device_data[0].VideoNorm=VIDEO_MODE_NTSC; | ||
1953 | break; | ||
1954 | |||
1955 | default: | ||
1956 | PDEBUG(DBG_PROBE, "VideoNorm=PAL (by default)"); | ||
1957 | usbvision_device_data[0].VideoNorm=VIDEO_MODE_PAL; | ||
1958 | break; | ||
1959 | } | ||
1960 | goto2next(parse); | ||
1961 | |||
1962 | sscanf(parse,"%d",&usbvision_device_data[0].AudioChannels); | ||
1963 | goto2next(parse); | ||
1964 | PDEBUG(DBG_PROBE, "AudioChannels=%d", usbvision_device_data[0].AudioChannels); | ||
1965 | sscanf(parse,"%d",&usbvision_device_data[0].Radio); | ||
1966 | goto2next(parse); | ||
1967 | PDEBUG(DBG_PROBE, "Radio=%d", usbvision_device_data[0].Radio); | ||
1968 | sscanf(parse,"%d",&usbvision_device_data[0].Tuner); | ||
1969 | goto2next(parse); | ||
1970 | PDEBUG(DBG_PROBE, "Tuner=%d", usbvision_device_data[0].Tuner); | ||
1971 | sscanf(parse,"%d",&usbvision_device_data[0].TunerType); | ||
1972 | goto2next(parse); | ||
1973 | PDEBUG(DBG_PROBE, "TunerType=%d", usbvision_device_data[0].TunerType); | ||
1974 | sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg1); | ||
1975 | goto2next(parse); | ||
1976 | PDEBUG(DBG_PROBE, "Vin_Reg1=%d", usbvision_device_data[0].Vin_Reg1); | ||
1977 | sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg2); | ||
1978 | goto2next(parse); | ||
1979 | PDEBUG(DBG_PROBE, "Vin_Reg2=%d", usbvision_device_data[0].Vin_Reg2); | ||
1980 | sscanf(parse,"%d",&usbvision_device_data[0].X_Offset); | ||
1981 | goto2next(parse); | ||
1982 | PDEBUG(DBG_PROBE, "X_Offset=%d", usbvision_device_data[0].X_Offset); | ||
1983 | sscanf(parse,"%d",&usbvision_device_data[0].Y_Offset); | ||
1984 | goto2next(parse); | ||
1985 | PDEBUG(DBG_PROBE, "Y_Offset=%d", usbvision_device_data[0].Y_Offset); | ||
1986 | sscanf(parse,"%d",&usbvision_device_data[0].Dvi_yuv); | ||
1987 | PDEBUG(DBG_PROBE, "Dvi_yuv=%d", usbvision_device_data[0].Dvi_yuv); | ||
1988 | |||
1989 | //add to usbvision_table also | ||
1990 | usbvision_table[0].match_flags=USB_DEVICE_ID_MATCH_DEVICE; | ||
1991 | usbvision_table[0].idVendor=usbvision_device_data[0].idVendor; | ||
1992 | usbvision_table[0].idProduct=usbvision_device_data[0].idProduct; | ||
1993 | |||
1994 | } | ||
1995 | } | ||
1996 | |||
1997 | |||
1998 | |||
1999 | /* | ||
2000 | * usbvision_init() | ||
2001 | * | ||
2002 | * This code is run to initialize the driver. | ||
2003 | * | ||
2004 | */ | ||
2005 | static int __init usbvision_init(void) | ||
2006 | { | ||
2007 | int errCode; | ||
2008 | |||
2009 | PDEBUG(DBG_PROBE, ""); | ||
2010 | |||
2011 | PDEBUG(DBG_IOCTL, "IOCTL debugging is enabled [video]"); | ||
2012 | PDEBUG(DBG_IO, "IO debugging is enabled [video]"); | ||
2013 | PDEBUG(DBG_PROBE, "PROBE debugging is enabled [video]"); | ||
2014 | PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]"); | ||
2015 | |||
2016 | /* disable planar mode support unless compression enabled */ | ||
2017 | if (isocMode != ISOC_MODE_COMPRESS ) { | ||
2018 | // FIXME : not the right way to set supported flag | ||
2019 | usbvision_v4l2_format[6].supported = 0; // V4L2_PIX_FMT_YVU420 | ||
2020 | usbvision_v4l2_format[7].supported = 0; // V4L2_PIX_FMT_YUV422P | ||
2021 | } | ||
2022 | |||
2023 | customdevice_process(); | ||
2024 | |||
2025 | errCode = usb_register(&usbvision_driver); | ||
2026 | |||
2027 | if (errCode == 0) { | ||
2028 | info(DRIVER_DESC " : " USBVISION_VERSION_STRING); | ||
2029 | PDEBUG(DBG_PROBE, "success"); | ||
2030 | } | ||
2031 | return errCode; | ||
2032 | } | ||
2033 | |||
2034 | static void __exit usbvision_exit(void) | ||
2035 | { | ||
2036 | PDEBUG(DBG_PROBE, ""); | ||
2037 | |||
2038 | usb_deregister(&usbvision_driver); | ||
2039 | PDEBUG(DBG_PROBE, "success"); | ||
2040 | } | ||
2041 | |||
2042 | module_init(usbvision_init); | ||
2043 | module_exit(usbvision_exit); | ||
2044 | |||
2045 | /* | ||
2046 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
2047 | * --------------------------------------------------------------------------- | ||
2048 | * Local variables: | ||
2049 | * c-basic-offset: 8 | ||
2050 | * End: | ||
2051 | */ | ||
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h new file mode 100644 index 000000000000..0e7e3d653cac --- /dev/null +++ b/drivers/media/video/usbvision/usbvision.h | |||
@@ -0,0 +1,558 @@ | |||
1 | /* | ||
2 | * USBVISION.H | ||
3 | * usbvision header file | ||
4 | * | ||
5 | * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> | ||
6 | * Dwaine Garden <dwainegarden@rogers.com> | ||
7 | * | ||
8 | * | ||
9 | * Report problems to v4l MailingList : http://www.redhat.com/mailman/listinfo/video4linux-list | ||
10 | * | ||
11 | * This module is part of usbvision driver project. | ||
12 | * Updates to driver completed by Dwaine P. Garden | ||
13 | * v4l2 conversion by Thierry Merle <thierry.merle@free.fr> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | */ | ||
29 | |||
30 | |||
31 | #ifndef __LINUX_USBVISION_H | ||
32 | #define __LINUX_USBVISION_H | ||
33 | |||
34 | #include <linux/list.h> | ||
35 | #include <linux/usb.h> | ||
36 | #include <media/v4l2-common.h> | ||
37 | #include <media/tuner.h> | ||
38 | #include <linux/videodev2.h> | ||
39 | |||
40 | #define USBVISION_DEBUG /* Turn on debug messages */ | ||
41 | |||
42 | #ifndef VID_HARDWARE_USBVISION | ||
43 | #define VID_HARDWARE_USBVISION 34 /* USBVision Video Grabber */ | ||
44 | #endif | ||
45 | |||
46 | #define USBVISION_PWR_REG 0x00 | ||
47 | #define USBVISION_SSPND_EN (1 << 1) | ||
48 | #define USBVISION_RES2 (1 << 2) | ||
49 | #define USBVISION_PWR_VID (1 << 5) | ||
50 | #define USBVISION_E2_EN (1 << 7) | ||
51 | #define USBVISION_CONFIG_REG 0x01 | ||
52 | #define USBVISION_ADRS_REG 0x02 | ||
53 | #define USBVISION_ALTER_REG 0x03 | ||
54 | #define USBVISION_FORCE_ALTER_REG 0x04 | ||
55 | #define USBVISION_STATUS_REG 0x05 | ||
56 | #define USBVISION_IOPIN_REG 0x06 | ||
57 | #define USBVISION_IO_1 (1 << 0) | ||
58 | #define USBVISION_IO_2 (1 << 1) | ||
59 | #define USBVISION_AUDIO_IN 0 | ||
60 | #define USBVISION_AUDIO_TV 1 | ||
61 | #define USBVISION_AUDIO_RADIO 2 | ||
62 | #define USBVISION_AUDIO_MUTE 3 | ||
63 | #define USBVISION_SER_MODE 0x07 | ||
64 | #define USBVISION_SER_ADRS 0x08 | ||
65 | #define USBVISION_SER_CONT 0x09 | ||
66 | #define USBVISION_SER_DAT1 0x0A | ||
67 | #define USBVISION_SER_DAT2 0x0B | ||
68 | #define USBVISION_SER_DAT3 0x0C | ||
69 | #define USBVISION_SER_DAT4 0x0D | ||
70 | #define USBVISION_EE_DATA 0x0E | ||
71 | #define USBVISION_EE_LSBAD 0x0F | ||
72 | #define USBVISION_EE_CONT 0x10 | ||
73 | #define USBVISION_DRM_CONT 0x12 | ||
74 | #define USBVISION_REF (1 << 0) | ||
75 | #define USBVISION_RES_UR (1 << 2) | ||
76 | #define USBVISION_RES_FDL (1 << 3) | ||
77 | #define USBVISION_RES_VDW (1 << 4) | ||
78 | #define USBVISION_DRM_PRM1 0x13 | ||
79 | #define USBVISION_DRM_PRM2 0x14 | ||
80 | #define USBVISION_DRM_PRM3 0x15 | ||
81 | #define USBVISION_DRM_PRM4 0x16 | ||
82 | #define USBVISION_DRM_PRM5 0x17 | ||
83 | #define USBVISION_DRM_PRM6 0x18 | ||
84 | #define USBVISION_DRM_PRM7 0x19 | ||
85 | #define USBVISION_DRM_PRM8 0x1A | ||
86 | #define USBVISION_VIN_REG1 0x1B | ||
87 | #define USBVISION_8_422_SYNC 0x01 | ||
88 | #define USBVISION_16_422_SYNC 0x02 | ||
89 | #define USBVISION_VSNC_POL (1 << 3) | ||
90 | #define USBVISION_HSNC_POL (1 << 4) | ||
91 | #define USBVISION_FID_POL (1 << 5) | ||
92 | #define USBVISION_HVALID_PO (1 << 6) | ||
93 | #define USBVISION_VCLK_POL (1 << 7) | ||
94 | #define USBVISION_VIN_REG2 0x1C | ||
95 | #define USBVISION_AUTO_FID (1 << 0) | ||
96 | #define USBVISION_NONE_INTER (1 << 1) | ||
97 | #define USBVISION_NOHVALID (1 << 2) | ||
98 | #define USBVISION_UV_ID (1 << 3) | ||
99 | #define USBVISION_FIX_2C (1 << 4) | ||
100 | #define USBVISION_SEND_FID (1 << 5) | ||
101 | #define USBVISION_KEEP_BLANK (1 << 7) | ||
102 | #define USBVISION_LXSIZE_I 0x1D | ||
103 | #define USBVISION_MXSIZE_I 0x1E | ||
104 | #define USBVISION_LYSIZE_I 0x1F | ||
105 | #define USBVISION_MYSIZE_I 0x20 | ||
106 | #define USBVISION_LX_OFFST 0x21 | ||
107 | #define USBVISION_MX_OFFST 0x22 | ||
108 | #define USBVISION_LY_OFFST 0x23 | ||
109 | #define USBVISION_MY_OFFST 0x24 | ||
110 | #define USBVISION_FRM_RATE 0x25 | ||
111 | #define USBVISION_LXSIZE_O 0x26 | ||
112 | #define USBVISION_MXSIZE_O 0x27 | ||
113 | #define USBVISION_LYSIZE_O 0x28 | ||
114 | #define USBVISION_MYSIZE_O 0x29 | ||
115 | #define USBVISION_FILT_CONT 0x2A | ||
116 | #define USBVISION_VO_MODE 0x2B | ||
117 | #define USBVISION_INTRA_CYC 0x2C | ||
118 | #define USBVISION_STRIP_SZ 0x2D | ||
119 | #define USBVISION_FORCE_INTRA 0x2E | ||
120 | #define USBVISION_FORCE_UP 0x2F | ||
121 | #define USBVISION_BUF_THR 0x30 | ||
122 | #define USBVISION_DVI_YUV 0x31 | ||
123 | #define USBVISION_AUDIO_CONT 0x32 | ||
124 | #define USBVISION_AUD_PK_LEN 0x33 | ||
125 | #define USBVISION_BLK_PK_LEN 0x34 | ||
126 | #define USBVISION_PCM_THR1 0x38 | ||
127 | #define USBVISION_PCM_THR2 0x39 | ||
128 | #define USBVISION_DIST_THR_L 0x3A | ||
129 | #define USBVISION_DIST_THR_H 0x3B | ||
130 | #define USBVISION_MAX_DIST_L 0x3C | ||
131 | #define USBVISION_MAX_DIST_H 0x3D | ||
132 | #define USBVISION_OP_CODE 0x33 | ||
133 | |||
134 | #define MAX_BYTES_PER_PIXEL 4 | ||
135 | |||
136 | #define MIN_FRAME_WIDTH 64 | ||
137 | #define MAX_USB_WIDTH 320 //384 | ||
138 | #define MAX_FRAME_WIDTH 320 //384 /*streching sometimes causes crashes*/ | ||
139 | |||
140 | #define MIN_FRAME_HEIGHT 48 | ||
141 | #define MAX_USB_HEIGHT 240 //288 | ||
142 | #define MAX_FRAME_HEIGHT 240 //288 /*Streching sometimes causes crashes*/ | ||
143 | |||
144 | #define MAX_FRAME_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL) | ||
145 | #define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask | ||
146 | |||
147 | #define USBVISION_URB_FRAMES 32 | ||
148 | #define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023 | ||
149 | |||
150 | #define USBVISION_NUM_HEADERMARKER 20 | ||
151 | #define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */ | ||
152 | #define USBVISION_NUMSBUF 2 /* Dimensioning the USB S buffering */ | ||
153 | |||
154 | #define USBVISION_POWEROFF_TIME 3 * (HZ) // 3 seconds | ||
155 | |||
156 | |||
157 | #define FRAMERATE_MIN 0 | ||
158 | #define FRAMERATE_MAX 31 | ||
159 | |||
160 | enum { | ||
161 | ISOC_MODE_YUV422 = 0x03, | ||
162 | ISOC_MODE_YUV420 = 0x14, | ||
163 | ISOC_MODE_COMPRESS = 0x60, | ||
164 | }; | ||
165 | |||
166 | /* This macro restricts an int variable to an inclusive range */ | ||
167 | #define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } | ||
168 | |||
169 | /* | ||
170 | * We use macros to do YUV -> RGB conversion because this is | ||
171 | * very important for speed and totally unimportant for size. | ||
172 | * | ||
173 | * YUV -> RGB Conversion | ||
174 | * --------------------- | ||
175 | * | ||
176 | * B = 1.164*(Y-16) + 2.018*(V-128) | ||
177 | * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128) | ||
178 | * R = 1.164*(Y-16) + 1.596*(U-128) | ||
179 | * | ||
180 | * If you fancy integer arithmetics (as you should), hear this: | ||
181 | * | ||
182 | * 65536*B = 76284*(Y-16) + 132252*(V-128) | ||
183 | * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128) | ||
184 | * 65536*R = 76284*(Y-16) + 104595*(U-128) | ||
185 | * | ||
186 | * Make sure the output values are within [0..255] range. | ||
187 | */ | ||
188 | #define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) | ||
189 | #define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ | ||
190 | int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ | ||
191 | mm_y = (my) - 16; \ | ||
192 | mm_u = (mu) - 128; \ | ||
193 | mm_v = (mv) - 128; \ | ||
194 | mm_yc= mm_y * 76284; \ | ||
195 | mm_b = (mm_yc + 132252*mm_v ) >> 16; \ | ||
196 | mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ | ||
197 | mm_r = (mm_yc + 104595*mm_u ) >> 16; \ | ||
198 | mb = LIMIT_RGB(mm_b); \ | ||
199 | mg = LIMIT_RGB(mm_g); \ | ||
200 | mr = LIMIT_RGB(mm_r); \ | ||
201 | } | ||
202 | |||
203 | /* Debugging aid */ | ||
204 | #define USBVISION_SAY_AND_WAIT(what) { \ | ||
205 | wait_queue_head_t wq; \ | ||
206 | init_waitqueue_head(&wq); \ | ||
207 | printk(KERN_INFO "Say: %s\n", what); \ | ||
208 | interruptible_sleep_on_timeout (&wq, HZ*3); \ | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * This macro checks if usbvision is still operational. The 'usbvision' | ||
213 | * pointer must be valid, usbvision->dev must be valid, we are not | ||
214 | * removing the device and the device has not erred on us. | ||
215 | */ | ||
216 | #define USBVISION_IS_OPERATIONAL(udevice) (\ | ||
217 | (udevice != NULL) && \ | ||
218 | ((udevice)->dev != NULL) && \ | ||
219 | ((udevice)->last_error == 0) && \ | ||
220 | (!(udevice)->remove_pending)) | ||
221 | |||
222 | /* I2C structures */ | ||
223 | struct i2c_algo_usb_data { | ||
224 | void *data; /* private data for lowlevel routines */ | ||
225 | int (*inb) (void *data, unsigned char addr, char *buf, short len); | ||
226 | int (*outb) (void *data, unsigned char addr, char *buf, short len); | ||
227 | |||
228 | /* local settings */ | ||
229 | int udelay; | ||
230 | int mdelay; | ||
231 | int timeout; | ||
232 | }; | ||
233 | |||
234 | #define I2C_USB_ADAP_MAX 16 | ||
235 | |||
236 | /* ----------------------------------------------------------------- */ | ||
237 | /* usbvision video structures */ | ||
238 | /* ----------------------------------------------------------------- */ | ||
239 | enum ScanState { | ||
240 | ScanState_Scanning, /* Scanning for header */ | ||
241 | ScanState_Lines /* Parsing lines */ | ||
242 | }; | ||
243 | |||
244 | /* Completion states of the data parser */ | ||
245 | enum ParseState { | ||
246 | ParseState_Continue, /* Just parse next item */ | ||
247 | ParseState_NextFrame, /* Frame done, send it to V4L */ | ||
248 | ParseState_Out, /* Not enough data for frame */ | ||
249 | ParseState_EndParse /* End parsing */ | ||
250 | }; | ||
251 | |||
252 | enum FrameState { | ||
253 | FrameState_Unused, /* Unused (no MCAPTURE) */ | ||
254 | FrameState_Ready, /* Ready to start grabbing */ | ||
255 | FrameState_Grabbing, /* In the process of being grabbed into */ | ||
256 | FrameState_Done, /* Finished grabbing, but not been synced yet */ | ||
257 | FrameState_DoneHold, /* Are syncing or reading */ | ||
258 | FrameState_Error, /* Something bad happened while processing */ | ||
259 | }; | ||
260 | |||
261 | /* stream states */ | ||
262 | enum StreamState { | ||
263 | Stream_Off, /* Driver streaming is completely OFF */ | ||
264 | Stream_Idle, /* Driver streaming is ready to be put ON by the application */ | ||
265 | Stream_Interrupt, /* Driver streaming must be interrupted */ | ||
266 | Stream_On, /* Driver streaming is put ON by the application */ | ||
267 | }; | ||
268 | |||
269 | enum IsocState { | ||
270 | IsocState_InFrame, /* Isoc packet is member of frame */ | ||
271 | IsocState_NoFrame, /* Isoc packet is not member of any frame */ | ||
272 | }; | ||
273 | |||
274 | struct usb_device; | ||
275 | |||
276 | struct usbvision_sbuf { | ||
277 | char *data; | ||
278 | struct urb *urb; | ||
279 | }; | ||
280 | |||
281 | #define USBVISION_MAGIC_1 0x55 | ||
282 | #define USBVISION_MAGIC_2 0xAA | ||
283 | #define USBVISION_HEADER_LENGTH 0x0c | ||
284 | #define USBVISION_SAA7111_ADDR 0x48 | ||
285 | #define USBVISION_SAA7113_ADDR 0x4a | ||
286 | #define USBVISION_IIC_LRACK 0x20 | ||
287 | #define USBVISION_IIC_LRNACK 0x30 | ||
288 | #define USBVISION_FRAME_FORMAT_PARAM_INTRA (1<<7) | ||
289 | |||
290 | struct usbvision_v4l2_format_st { | ||
291 | int supported; | ||
292 | int bytes_per_pixel; | ||
293 | int depth; | ||
294 | int format; | ||
295 | char *desc; | ||
296 | }; | ||
297 | #define USBVISION_SUPPORTED_PALETTES ARRAY_SIZE(usbvision_v4l2_format) | ||
298 | |||
299 | struct usbvision_frame_header { | ||
300 | unsigned char magic_1; /* 0 magic */ | ||
301 | unsigned char magic_2; /* 1 magic */ | ||
302 | unsigned char headerLength; /* 2 */ | ||
303 | unsigned char frameNum; /* 3 */ | ||
304 | unsigned char framePhase; /* 4 */ | ||
305 | unsigned char frameLatency; /* 5 */ | ||
306 | unsigned char dataFormat; /* 6 */ | ||
307 | unsigned char formatParam; /* 7 */ | ||
308 | unsigned char frameWidthLo; /* 8 */ | ||
309 | unsigned char frameWidthHi; /* 9 */ | ||
310 | unsigned char frameHeightLo; /* 10 */ | ||
311 | unsigned char frameHeightHi; /* 11 */ | ||
312 | __u16 frameWidth; /* 8 - 9 after endian correction*/ | ||
313 | __u16 frameHeight; /* 10 - 11 after endian correction*/ | ||
314 | }; | ||
315 | |||
316 | /* tvnorms */ | ||
317 | struct usbvision_tvnorm { | ||
318 | char *name; | ||
319 | v4l2_std_id id; | ||
320 | /* mode for saa7113h */ | ||
321 | int mode; | ||
322 | }; | ||
323 | |||
324 | struct usbvision_frame { | ||
325 | char *data; /* Frame buffer */ | ||
326 | struct usbvision_frame_header isocHeader; /* Header from stream */ | ||
327 | |||
328 | int width; /* Width application is expecting */ | ||
329 | int height; /* Height */ | ||
330 | int index; /* Frame index */ | ||
331 | int frmwidth; /* Width the frame actually is */ | ||
332 | int frmheight; /* Height */ | ||
333 | |||
334 | volatile int grabstate; /* State of grabbing */ | ||
335 | int scanstate; /* State of scanning */ | ||
336 | |||
337 | struct list_head frame; | ||
338 | |||
339 | int curline; /* Line of frame we're working on */ | ||
340 | |||
341 | long scanlength; /* uncompressed, raw data length of frame */ | ||
342 | long bytes_read; /* amount of scanlength that has been read from data */ | ||
343 | struct usbvision_v4l2_format_st v4l2_format; /* format the user needs*/ | ||
344 | int v4l2_linesize; /* bytes for one videoline*/ | ||
345 | struct timeval timestamp; | ||
346 | int sequence; // How many video frames we send to user | ||
347 | }; | ||
348 | |||
349 | #define CODEC_SAA7113 7113 | ||
350 | #define CODEC_SAA7111 7111 | ||
351 | #define BRIDGE_NT1003 1003 | ||
352 | #define BRIDGE_NT1004 1004 | ||
353 | #define BRIDGE_NT1005 1005 | ||
354 | |||
355 | struct usbvision_device_data_st { | ||
356 | int idVendor; | ||
357 | int idProduct; | ||
358 | int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */ | ||
359 | int Codec; | ||
360 | int VideoChannels; | ||
361 | __u64 VideoNorm; | ||
362 | int AudioChannels; | ||
363 | int Radio; | ||
364 | int vbi; | ||
365 | int Tuner; | ||
366 | int TunerType; | ||
367 | int Vin_Reg1; | ||
368 | int Vin_Reg2; | ||
369 | int X_Offset; | ||
370 | int Y_Offset; | ||
371 | int Dvi_yuv; | ||
372 | char *ModelString; | ||
373 | }; | ||
374 | |||
375 | /* Declared on usbvision-cards.c */ | ||
376 | extern struct usbvision_device_data_st usbvision_device_data[]; | ||
377 | extern struct usb_device_id usbvision_table[]; | ||
378 | |||
379 | struct usb_usbvision { | ||
380 | struct video_device *vdev; /* Video Device */ | ||
381 | struct video_device *rdev; /* Radio Device */ | ||
382 | struct video_device *vbi; /* VBI Device */ | ||
383 | |||
384 | /* i2c Declaration Section*/ | ||
385 | struct i2c_adapter i2c_adap; | ||
386 | struct i2c_algo_usb_data i2c_algo; | ||
387 | struct i2c_client i2c_client; | ||
388 | |||
389 | struct urb *ctrlUrb; | ||
390 | unsigned char ctrlUrbBuffer[8]; | ||
391 | int ctrlUrbBusy; | ||
392 | struct usb_ctrlrequest ctrlUrbSetup; | ||
393 | wait_queue_head_t ctrlUrb_wq; // Processes waiting | ||
394 | struct semaphore ctrlUrbLock; | ||
395 | |||
396 | /* configuration part */ | ||
397 | int have_tuner; | ||
398 | int tuner_type; | ||
399 | int tuner_addr; | ||
400 | int bridgeType; // NT1003, NT1004, NT1005 | ||
401 | int channel; | ||
402 | int radio; | ||
403 | int video_inputs; // # of inputs | ||
404 | unsigned long freq; | ||
405 | int AudioMute; | ||
406 | int AudioChannel; | ||
407 | int isocMode; // format of video data for the usb isoc-transfer | ||
408 | unsigned int nr; // Number of the device | ||
409 | |||
410 | /* Device structure */ | ||
411 | struct usb_device *dev; | ||
412 | unsigned char iface; /* Video interface number */ | ||
413 | unsigned char ifaceAltActive, ifaceAltInactive; /* Alt settings */ | ||
414 | unsigned char Vin_Reg2_Preset; | ||
415 | struct semaphore lock; | ||
416 | struct timer_list powerOffTimer; | ||
417 | struct work_struct powerOffWork; | ||
418 | int power; /* is the device powered on? */ | ||
419 | int user; /* user count for exclusive use */ | ||
420 | int initialized; /* Had we already sent init sequence? */ | ||
421 | int DevModel; /* What type of USBVISION device we got? */ | ||
422 | enum StreamState streaming; /* Are we streaming Isochronous? */ | ||
423 | int last_error; /* What calamity struck us? */ | ||
424 | int curwidth; /* width of the frame the device is currently set to*/ | ||
425 | int curheight; /* height of the frame the device is currently set to*/ | ||
426 | int stretch_width; /* stretch-factor for frame width (from usb to screen)*/ | ||
427 | int stretch_height; /* stretch-factor for frame height (from usb to screen)*/ | ||
428 | char *fbuf; /* Videodev buffer area for mmap*/ | ||
429 | int max_frame_size; /* Bytes in one video frame */ | ||
430 | int fbuf_size; /* Videodev buffer size */ | ||
431 | spinlock_t queue_lock; /* spinlock for protecting mods on inqueue and outqueue */ | ||
432 | struct list_head inqueue, outqueue; /* queued frame list and ready to dequeue frame list */ | ||
433 | wait_queue_head_t wait_frame; /* Processes waiting */ | ||
434 | wait_queue_head_t wait_stream; /* Processes waiting */ | ||
435 | struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header | ||
436 | struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer | ||
437 | struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering | ||
438 | volatile int remove_pending; /* If set then about to exit */ | ||
439 | |||
440 | /* Scratch space from the Isochronous Pipe.*/ | ||
441 | unsigned char *scratch; | ||
442 | int scratch_read_ptr; | ||
443 | int scratch_write_ptr; | ||
444 | int scratch_headermarker[USBVISION_NUM_HEADERMARKER]; | ||
445 | int scratch_headermarker_read_ptr; | ||
446 | int scratch_headermarker_write_ptr; | ||
447 | enum IsocState isocstate; | ||
448 | struct usbvision_v4l2_format_st palette; | ||
449 | |||
450 | struct v4l2_capability vcap; /* Video capabilities */ | ||
451 | unsigned int ctl_input; /* selected input */ | ||
452 | struct usbvision_tvnorm *tvnorm; /* selected tv norm */ | ||
453 | unsigned char video_endp; /* 0x82 for USBVISION devices based */ | ||
454 | |||
455 | // Decompression stuff: | ||
456 | unsigned char *IntraFrameBuffer; /* Buffer for reference frame */ | ||
457 | int BlockPos; //for test only | ||
458 | int requestIntra; // 0 = normal; 1 = intra frame is requested; | ||
459 | int lastIsocFrameNum; // check for lost isoc frames | ||
460 | int isocPacketSize; // need to calculate usedBandwidth | ||
461 | int usedBandwidth; // used bandwidth 0-100%, need to set comprLevel | ||
462 | int comprLevel; // How strong (100) or weak (0) is compression | ||
463 | int lastComprLevel; // How strong (100) or weak (0) was compression | ||
464 | int usb_bandwidth; /* Mbit/s */ | ||
465 | |||
466 | /* Statistics that can be overlayed on the screen */ | ||
467 | unsigned long isocUrbCount; // How many URBs we received so far | ||
468 | unsigned long urb_length; /* Length of last URB */ | ||
469 | unsigned long isocDataCount; /* How many bytes we received */ | ||
470 | unsigned long header_count; /* How many frame headers we found */ | ||
471 | unsigned long scratch_ovf_count; /* How many times we overflowed scratch */ | ||
472 | unsigned long isocSkipCount; /* How many empty ISO packets received */ | ||
473 | unsigned long isocErrCount; /* How many bad ISO packets received */ | ||
474 | unsigned long isocPacketCount; // How many packets we totally got | ||
475 | unsigned long timeInIrq; // How long do we need for interrupt | ||
476 | int isocMeasureBandwidthCount; | ||
477 | int frame_num; // How many video frames we send to user | ||
478 | int maxStripLen; // How big is the biggest strip | ||
479 | int comprBlockPos; | ||
480 | int stripLenErrors; // How many times was BlockPos greater than StripLen | ||
481 | int stripMagicErrors; | ||
482 | int stripLineNumberErrors; | ||
483 | int ComprBlockTypes[4]; | ||
484 | }; | ||
485 | |||
486 | |||
487 | /* --------------------------------------------------------------- */ | ||
488 | /* defined in usbvision-i2c.c */ | ||
489 | /* i2c-algo-usb declaration */ | ||
490 | /* --------------------------------------------------------------- */ | ||
491 | |||
492 | int usbvision_i2c_usb_add_bus(struct i2c_adapter *); | ||
493 | int usbvision_i2c_usb_del_bus(struct i2c_adapter *); | ||
494 | |||
495 | static inline void *i2c_get_algo_usb_data (struct i2c_algo_usb_data *dev) | ||
496 | { | ||
497 | return dev->data; | ||
498 | } | ||
499 | |||
500 | static inline void i2c_set_algo_usb_data (struct i2c_algo_usb_data *dev, void *data) | ||
501 | { | ||
502 | dev->data = data; | ||
503 | } | ||
504 | |||
505 | |||
506 | /* ----------------------------------------------------------------------- */ | ||
507 | /* usbvision specific I2C functions */ | ||
508 | /* ----------------------------------------------------------------------- */ | ||
509 | int usbvision_init_i2c(struct usb_usbvision *usbvision); | ||
510 | void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg); | ||
511 | |||
512 | /* defined in usbvision-core.c */ | ||
513 | void *usbvision_rvmalloc(unsigned long size); | ||
514 | void usbvision_rvfree(void *mem, unsigned long size); | ||
515 | int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg); | ||
516 | int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, | ||
517 | unsigned char value); | ||
518 | |||
519 | int usbvision_frames_alloc(struct usb_usbvision *usbvision); | ||
520 | void usbvision_frames_free(struct usb_usbvision *usbvision); | ||
521 | int usbvision_scratch_alloc(struct usb_usbvision *usbvision); | ||
522 | void usbvision_scratch_free(struct usb_usbvision *usbvision); | ||
523 | int usbvision_sbuf_alloc(struct usb_usbvision *usbvision); | ||
524 | void usbvision_sbuf_free(struct usb_usbvision *usbvision); | ||
525 | int usbvision_decompress_alloc(struct usb_usbvision *usbvision); | ||
526 | void usbvision_decompress_free(struct usb_usbvision *usbvision); | ||
527 | |||
528 | int usbvision_setup(struct usb_usbvision *usbvision,int format); | ||
529 | int usbvision_init_isoc(struct usb_usbvision *usbvision); | ||
530 | int usbvision_restart_isoc(struct usb_usbvision *usbvision); | ||
531 | void usbvision_stop_isoc(struct usb_usbvision *usbvision); | ||
532 | |||
533 | int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel); | ||
534 | int usbvision_audio_off(struct usb_usbvision *usbvision); | ||
535 | |||
536 | int usbvision_begin_streaming(struct usb_usbvision *usbvision); | ||
537 | void usbvision_empty_framequeues(struct usb_usbvision *dev); | ||
538 | int usbvision_stream_interrupt(struct usb_usbvision *dev); | ||
539 | |||
540 | int usbvision_muxsel(struct usb_usbvision *usbvision, int channel); | ||
541 | int usbvision_set_input(struct usb_usbvision *usbvision); | ||
542 | int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height); | ||
543 | |||
544 | void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision); | ||
545 | void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision); | ||
546 | void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision); | ||
547 | int usbvision_power_off(struct usb_usbvision *usbvision); | ||
548 | int usbvision_power_on(struct usb_usbvision *usbvision); | ||
549 | |||
550 | #endif /* __LINUX_USBVISION_H */ | ||
551 | |||
552 | /* | ||
553 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
554 | * --------------------------------------------------------------------------- | ||
555 | * Local variables: | ||
556 | * c-basic-offset: 8 | ||
557 | * End: | ||
558 | */ | ||
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 1d899e2db394..8a13e595304e 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c | |||
@@ -350,6 +350,7 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
350 | struct video_buffer *buffer = arg; | 350 | struct video_buffer *buffer = arg; |
351 | 351 | ||
352 | memset(buffer, 0, sizeof(*buffer)); | 352 | memset(buffer, 0, sizeof(*buffer)); |
353 | memset(&fbuf2, 0, sizeof(fbuf2)); | ||
353 | 354 | ||
354 | err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); | 355 | err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); |
355 | if (err < 0) { | 356 | if (err < 0) { |
@@ -616,6 +617,7 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
616 | case VIDIOCSPICT: /* set tone controls & partial capture format */ | 617 | case VIDIOCSPICT: /* set tone controls & partial capture format */ |
617 | { | 618 | { |
618 | struct video_picture *pict = arg; | 619 | struct video_picture *pict = arg; |
620 | memset(&fbuf2, 0, sizeof(fbuf2)); | ||
619 | 621 | ||
620 | set_v4l_control(inode, file, | 622 | set_v4l_control(inode, file, |
621 | V4L2_CID_BRIGHTNESS, pict->brightness, drv); | 623 | V4L2_CID_BRIGHTNESS, pict->brightness, drv); |
@@ -708,12 +710,22 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
708 | } | 710 | } |
709 | case VIDIOCSTUNER: /* select a tuner input */ | 711 | case VIDIOCSTUNER: /* select a tuner input */ |
710 | { | 712 | { |
711 | err = 0; | 713 | struct video_tuner *tun = arg; |
714 | struct v4l2_tuner t; | ||
715 | memset(&t,0,sizeof(t)); | ||
716 | |||
717 | t.index=tun->tuner; | ||
718 | |||
719 | err = drv(inode, file, VIDIOC_S_INPUT, &t); | ||
720 | if (err < 0) | ||
721 | dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err); | ||
722 | |||
712 | break; | 723 | break; |
713 | } | 724 | } |
714 | case VIDIOCGFREQ: /* get frequency */ | 725 | case VIDIOCGFREQ: /* get frequency */ |
715 | { | 726 | { |
716 | unsigned long *freq = arg; | 727 | unsigned long *freq = arg; |
728 | memset(&freq2,0,sizeof(freq2)); | ||
717 | 729 | ||
718 | freq2.tuner = 0; | 730 | freq2.tuner = 0; |
719 | err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); | 731 | err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); |
@@ -726,8 +738,8 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
726 | case VIDIOCSFREQ: /* set frequency */ | 738 | case VIDIOCSFREQ: /* set frequency */ |
727 | { | 739 | { |
728 | unsigned long *freq = arg; | 740 | unsigned long *freq = arg; |
741 | memset(&freq2,0,sizeof(freq2)); | ||
729 | 742 | ||
730 | freq2.tuner = 0; | ||
731 | drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); | 743 | drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); |
732 | freq2.frequency = *freq; | 744 | freq2.frequency = *freq; |
733 | err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); | 745 | err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); |
@@ -738,6 +750,7 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
738 | case VIDIOCGAUDIO: /* get audio properties/controls */ | 750 | case VIDIOCGAUDIO: /* get audio properties/controls */ |
739 | { | 751 | { |
740 | struct video_audio *aud = arg; | 752 | struct video_audio *aud = arg; |
753 | memset(&aud2,0,sizeof(aud2)); | ||
741 | 754 | ||
742 | err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); | 755 | err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); |
743 | if (err < 0) { | 756 | if (err < 0) { |
@@ -898,6 +911,7 @@ v4l_compat_translate_ioctl(struct inode *inode, | |||
898 | { | 911 | { |
899 | int *i = arg; | 912 | int *i = arg; |
900 | 913 | ||
914 | memset(&buf2,0,sizeof(buf2)); | ||
901 | buf2.index = *i; | 915 | buf2.index = *i; |
902 | buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 916 | buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
903 | err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); | 917 | err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 78d28b03ec93..752c82c37f55 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -87,6 +87,78 @@ MODULE_LICENSE("GPL"); | |||
87 | */ | 87 | */ |
88 | 88 | ||
89 | 89 | ||
90 | char *v4l2_norm_to_name(v4l2_std_id id) | ||
91 | { | ||
92 | char *name; | ||
93 | |||
94 | switch (id) { | ||
95 | case V4L2_STD_PAL: | ||
96 | name="PAL"; break; | ||
97 | case V4L2_STD_PAL_BG: | ||
98 | name="PAL-BG"; break; | ||
99 | case V4L2_STD_PAL_DK: | ||
100 | name="PAL-DK"; break; | ||
101 | case V4L2_STD_PAL_B: | ||
102 | name="PAL-B"; break; | ||
103 | case V4L2_STD_PAL_B1: | ||
104 | name="PAL-B1"; break; | ||
105 | case V4L2_STD_PAL_G: | ||
106 | name="PAL-G"; break; | ||
107 | case V4L2_STD_PAL_H: | ||
108 | name="PAL-H"; break; | ||
109 | case V4L2_STD_PAL_I: | ||
110 | name="PAL-I"; break; | ||
111 | case V4L2_STD_PAL_D: | ||
112 | name="PAL-D"; break; | ||
113 | case V4L2_STD_PAL_D1: | ||
114 | name="PAL-D1"; break; | ||
115 | case V4L2_STD_PAL_K: | ||
116 | name="PAL-K"; break; | ||
117 | case V4L2_STD_PAL_M: | ||
118 | name="PAL-M"; break; | ||
119 | case V4L2_STD_PAL_N: | ||
120 | name="PAL-N"; break; | ||
121 | case V4L2_STD_PAL_Nc: | ||
122 | name="PAL-Nc"; break; | ||
123 | case V4L2_STD_PAL_60: | ||
124 | name="PAL-60"; break; | ||
125 | case V4L2_STD_NTSC: | ||
126 | name="NTSC"; break; | ||
127 | case V4L2_STD_NTSC_M: | ||
128 | name="NTSC-M"; break; | ||
129 | case V4L2_STD_NTSC_M_JP: | ||
130 | name="NTSC-M-JP"; break; | ||
131 | case V4L2_STD_NTSC_443: | ||
132 | name="NTSC-443"; break; | ||
133 | case V4L2_STD_NTSC_M_KR: | ||
134 | name="NTSC-M-KR"; break; | ||
135 | case V4L2_STD_SECAM: | ||
136 | name="SECAM"; break; | ||
137 | case V4L2_STD_SECAM_DK: | ||
138 | name="SECAM-DK"; break; | ||
139 | case V4L2_STD_SECAM_B: | ||
140 | name="SECAM-B"; break; | ||
141 | case V4L2_STD_SECAM_D: | ||
142 | name="SECAM-D"; break; | ||
143 | case V4L2_STD_SECAM_G: | ||
144 | name="SECAM-G"; break; | ||
145 | case V4L2_STD_SECAM_H: | ||
146 | name="SECAM-H"; break; | ||
147 | case V4L2_STD_SECAM_K: | ||
148 | name="SECAM-K"; break; | ||
149 | case V4L2_STD_SECAM_K1: | ||
150 | name="SECAM-K1"; break; | ||
151 | case V4L2_STD_SECAM_L: | ||
152 | name="SECAM-L"; break; | ||
153 | case V4L2_STD_SECAM_LC: | ||
154 | name="SECAM-LC"; break; | ||
155 | default: | ||
156 | name="Unknown"; break; | ||
157 | } | ||
158 | |||
159 | return name; | ||
160 | } | ||
161 | |||
90 | /* Fill in the fields of a v4l2_standard structure according to the | 162 | /* Fill in the fields of a v4l2_standard structure according to the |
91 | 'id' and 'transmission' parameters. Returns negative on error. */ | 163 | 'id' and 'transmission' parameters. Returns negative on error. */ |
92 | int v4l2_video_std_construct(struct v4l2_standard *vs, | 164 | int v4l2_video_std_construct(struct v4l2_standard *vs, |
@@ -184,11 +256,13 @@ char *v4l2_field_names[] = { | |||
184 | }; | 256 | }; |
185 | 257 | ||
186 | char *v4l2_type_names[] = { | 258 | char *v4l2_type_names[] = { |
187 | [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", | 259 | [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", |
188 | [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", | 260 | [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", |
189 | [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", | 261 | [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", |
190 | [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", | 262 | [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", |
191 | [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", | 263 | [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", |
264 | [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap", | ||
265 | [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "slicec-vbi-out", | ||
192 | }; | 266 | }; |
193 | 267 | ||
194 | static char *v4l2_memory_names[] = { | 268 | static char *v4l2_memory_names[] = { |
@@ -1451,6 +1525,7 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) | |||
1451 | 1525 | ||
1452 | /* ----------------------------------------------------------------- */ | 1526 | /* ----------------------------------------------------------------- */ |
1453 | 1527 | ||
1528 | EXPORT_SYMBOL(v4l2_norm_to_name); | ||
1454 | EXPORT_SYMBOL(v4l2_video_std_construct); | 1529 | EXPORT_SYMBOL(v4l2_video_std_construct); |
1455 | 1530 | ||
1456 | EXPORT_SYMBOL(v4l2_prio_init); | 1531 | EXPORT_SYMBOL(v4l2_prio_init); |
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 41ec0c4b35a2..6a0e8ca72948 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c | |||
@@ -342,7 +342,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd, | |||
342 | 342 | ||
343 | dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " | 343 | dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " |
344 | "bytesused=%d, flags=0x%08d, " | 344 | "bytesused=%d, flags=0x%08d, " |
345 | "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n", | 345 | "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n", |
346 | (p->timestamp.tv_sec/3600), | 346 | (p->timestamp.tv_sec/3600), |
347 | (int)(p->timestamp.tv_sec/60)%60, | 347 | (int)(p->timestamp.tv_sec/60)%60, |
348 | (int)(p->timestamp.tv_sec%60), | 348 | (int)(p->timestamp.tv_sec%60), |
@@ -352,7 +352,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd, | |||
352 | p->bytesused,p->flags, | 352 | p->bytesused,p->flags, |
353 | p->field,p->sequence, | 353 | p->field,p->sequence, |
354 | prt_names(p->memory,v4l2_memory_names), | 354 | prt_names(p->memory,v4l2_memory_names), |
355 | p->m.userptr); | 355 | p->m.userptr, p->length); |
356 | dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " | 356 | dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " |
357 | "flags=0x%08d, frames=%d, userbits=0x%08x\n", | 357 | "flags=0x%08d, frames=%d, userbits=0x%08x\n", |
358 | tc->hours,tc->minutes,tc->seconds, | 358 | tc->hours,tc->minutes,tc->seconds, |
@@ -369,9 +369,13 @@ static inline void dbgrect(struct video_device *vfd, char *s, | |||
369 | static inline void v4l_print_pix_fmt (struct video_device *vfd, | 369 | static inline void v4l_print_pix_fmt (struct video_device *vfd, |
370 | struct v4l2_pix_format *fmt) | 370 | struct v4l2_pix_format *fmt) |
371 | { | 371 | { |
372 | dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, " | 372 | dbgarg2 ("width=%d, height=%d, format=%c%c%c%c, field=%s, " |
373 | "bytesperline=%d sizeimage=%d, colorspace=%d\n", | 373 | "bytesperline=%d sizeimage=%d, colorspace=%d\n", |
374 | fmt->width,fmt->height,fmt->pixelformat, | 374 | fmt->width,fmt->height, |
375 | (fmt->pixelformat & 0xff), | ||
376 | (fmt->pixelformat >> 8) & 0xff, | ||
377 | (fmt->pixelformat >> 16) & 0xff, | ||
378 | (fmt->pixelformat >> 24) & 0xff, | ||
375 | prt_names(fmt->field,v4l2_field_names_FIXME), | 379 | prt_names(fmt->field,v4l2_field_names_FIXME), |
376 | fmt->bytesperline,fmt->sizeimage,fmt->colorspace); | 380 | fmt->bytesperline,fmt->sizeimage,fmt->colorspace); |
377 | }; | 381 | }; |
@@ -428,6 +432,10 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
428 | v4l_print_ioctl(vfd->name, cmd); | 432 | v4l_print_ioctl(vfd->name, cmd); |
429 | } | 433 | } |
430 | 434 | ||
435 | if (_IOC_TYPE(cmd)=='v') | ||
436 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | ||
437 | __video_do_ioctl); | ||
438 | |||
431 | switch(cmd) { | 439 | switch(cmd) { |
432 | /* --- capabilities ------------------------------------------ */ | 440 | /* --- capabilities ------------------------------------------ */ |
433 | case VIDIOC_QUERYCAP: | 441 | case VIDIOC_QUERYCAP: |
@@ -526,12 +534,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
526 | } | 534 | } |
527 | if (!ret) | 535 | if (!ret) |
528 | dbgarg (cmd, "index=%d, type=%d, flags=%d, " | 536 | dbgarg (cmd, "index=%d, type=%d, flags=%d, " |
529 | "description=%s," | 537 | "pixelformat=%c%c%c%c, description='%s'\n", |
530 | " pixelformat=0x%8x\n", | ||
531 | f->index, f->type, f->flags, | 538 | f->index, f->type, f->flags, |
532 | f->description, | 539 | (f->pixelformat & 0xff), |
533 | f->pixelformat); | 540 | (f->pixelformat >> 8) & 0xff, |
534 | 541 | (f->pixelformat >> 16) & 0xff, | |
542 | (f->pixelformat >> 24) & 0xff, | ||
543 | f->description); | ||
535 | break; | 544 | break; |
536 | } | 545 | } |
537 | case VIDIOC_G_FMT: | 546 | case VIDIOC_G_FMT: |
@@ -829,20 +838,85 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
829 | case VIDIOC_ENUMSTD: | 838 | case VIDIOC_ENUMSTD: |
830 | { | 839 | { |
831 | struct v4l2_standard *p = arg; | 840 | struct v4l2_standard *p = arg; |
832 | unsigned int index = p->index; | 841 | v4l2_std_id id = vfd->tvnorms,curr_id=0; |
842 | unsigned int index = p->index,i; | ||
833 | 843 | ||
834 | if (!vfd->tvnormsize) { | 844 | if (index<0) { |
835 | printk (KERN_WARNING "%s: no TV norms defined!\n", | 845 | ret=-EINVAL; |
836 | vfd->name); | ||
837 | break; | 846 | break; |
838 | } | 847 | } |
839 | 848 | ||
840 | if (index<0 || index >= vfd->tvnormsize) { | 849 | /* Return norm array on a canonical way */ |
841 | ret=-EINVAL; | 850 | for (i=0;i<= index && id; i++) { |
842 | break; | 851 | if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) { |
852 | curr_id = V4L2_STD_PAL; | ||
853 | } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) { | ||
854 | curr_id = V4L2_STD_PAL_BG; | ||
855 | } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) { | ||
856 | curr_id = V4L2_STD_PAL_DK; | ||
857 | } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) { | ||
858 | curr_id = V4L2_STD_PAL_B; | ||
859 | } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) { | ||
860 | curr_id = V4L2_STD_PAL_B1; | ||
861 | } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) { | ||
862 | curr_id = V4L2_STD_PAL_G; | ||
863 | } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) { | ||
864 | curr_id = V4L2_STD_PAL_H; | ||
865 | } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) { | ||
866 | curr_id = V4L2_STD_PAL_I; | ||
867 | } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) { | ||
868 | curr_id = V4L2_STD_PAL_D; | ||
869 | } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) { | ||
870 | curr_id = V4L2_STD_PAL_D1; | ||
871 | } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) { | ||
872 | curr_id = V4L2_STD_PAL_K; | ||
873 | } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) { | ||
874 | curr_id = V4L2_STD_PAL_M; | ||
875 | } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) { | ||
876 | curr_id = V4L2_STD_PAL_N; | ||
877 | } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) { | ||
878 | curr_id = V4L2_STD_PAL_Nc; | ||
879 | } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) { | ||
880 | curr_id = V4L2_STD_PAL_60; | ||
881 | } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) { | ||
882 | curr_id = V4L2_STD_NTSC; | ||
883 | } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) { | ||
884 | curr_id = V4L2_STD_NTSC_M; | ||
885 | } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) { | ||
886 | curr_id = V4L2_STD_NTSC_M_JP; | ||
887 | } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) { | ||
888 | curr_id = V4L2_STD_NTSC_443; | ||
889 | } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) { | ||
890 | curr_id = V4L2_STD_NTSC_M_KR; | ||
891 | } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) { | ||
892 | curr_id = V4L2_STD_SECAM; | ||
893 | } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) { | ||
894 | curr_id = V4L2_STD_SECAM_DK; | ||
895 | } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) { | ||
896 | curr_id = V4L2_STD_SECAM_B; | ||
897 | } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) { | ||
898 | curr_id = V4L2_STD_SECAM_D; | ||
899 | } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) { | ||
900 | curr_id = V4L2_STD_SECAM_G; | ||
901 | } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) { | ||
902 | curr_id = V4L2_STD_SECAM_H; | ||
903 | } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) { | ||
904 | curr_id = V4L2_STD_SECAM_K; | ||
905 | } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) { | ||
906 | curr_id = V4L2_STD_SECAM_K1; | ||
907 | } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) { | ||
908 | curr_id = V4L2_STD_SECAM_L; | ||
909 | } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) { | ||
910 | curr_id = V4L2_STD_SECAM_LC; | ||
911 | } else { | ||
912 | break; | ||
913 | } | ||
914 | id &= ~curr_id; | ||
843 | } | 915 | } |
844 | v4l2_video_std_construct(p, vfd->tvnorms[p->index].id, | 916 | if (i<=index) |
845 | vfd->tvnorms[p->index].name); | 917 | return -EINVAL; |
918 | |||
919 | v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id)); | ||
846 | p->index = index; | 920 | p->index = index; |
847 | 921 | ||
848 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " | 922 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " |
@@ -868,39 +942,23 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
868 | } | 942 | } |
869 | case VIDIOC_S_STD: | 943 | case VIDIOC_S_STD: |
870 | { | 944 | { |
871 | v4l2_std_id *id = arg; | 945 | v4l2_std_id *id = arg,norm; |
872 | unsigned int i; | ||
873 | |||
874 | if (!vfd->tvnormsize) { | ||
875 | printk (KERN_WARNING "%s: no TV norms defined!\n", | ||
876 | vfd->name); | ||
877 | break; | ||
878 | } | ||
879 | 946 | ||
880 | dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); | 947 | dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); |
881 | 948 | ||
882 | /* First search for exact match */ | 949 | norm = (*id) & vfd->tvnorms; |
883 | for (i = 0; i < vfd->tvnormsize; i++) | 950 | if ( vfd->tvnorms && !norm) /* Check if std is supported */ |
884 | if (*id == vfd->tvnorms[i].id) | ||
885 | break; | ||
886 | /* Then for a generic video std that contains desired std */ | ||
887 | if (i == vfd->tvnormsize) | ||
888 | for (i = 0; i < vfd->tvnormsize; i++) | ||
889 | if (*id & vfd->tvnorms[i].id) | ||
890 | break; | ||
891 | if (i == vfd->tvnormsize) { | ||
892 | break; | 951 | break; |
893 | } | ||
894 | 952 | ||
895 | /* Calls the specific handler */ | 953 | /* Calls the specific handler */ |
896 | if (vfd->vidioc_s_std) | 954 | if (vfd->vidioc_s_std) |
897 | ret=vfd->vidioc_s_std(file, fh, i); | 955 | ret=vfd->vidioc_s_std(file, fh, &norm); |
898 | else | 956 | else |
899 | ret=-EINVAL; | 957 | ret=-EINVAL; |
900 | 958 | ||
901 | /* Updates standard information */ | 959 | /* Updates standard information */ |
902 | if (!ret) | 960 | if (ret>=0) |
903 | vfd->current_norm=*id; | 961 | vfd->current_norm=norm; |
904 | 962 | ||
905 | break; | 963 | break; |
906 | } | 964 | } |
@@ -1088,9 +1146,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1088 | case VIDIOC_G_AUDIO: | 1146 | case VIDIOC_G_AUDIO: |
1089 | { | 1147 | { |
1090 | struct v4l2_audio *p=arg; | 1148 | struct v4l2_audio *p=arg; |
1149 | __u32 index=p->index; | ||
1091 | 1150 | ||
1092 | if (!vfd->vidioc_g_audio) | 1151 | if (!vfd->vidioc_g_audio) |
1093 | break; | 1152 | break; |
1153 | |||
1154 | memset(p,0,sizeof(*p)); | ||
1155 | p->index=index; | ||
1094 | dbgarg(cmd, "Get for index=%d\n", p->index); | 1156 | dbgarg(cmd, "Get for index=%d\n", p->index); |
1095 | ret=vfd->vidioc_g_audio(file, fh, p); | 1157 | ret=vfd->vidioc_g_audio(file, fh, p); |
1096 | if (!ret) | 1158 | if (!ret) |
@@ -1288,25 +1350,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1288 | ret=vfd->vidioc_g_parm(file, fh, p); | 1350 | ret=vfd->vidioc_g_parm(file, fh, p); |
1289 | } else { | 1351 | } else { |
1290 | struct v4l2_standard s; | 1352 | struct v4l2_standard s; |
1291 | int i; | ||
1292 | |||
1293 | if (!vfd->tvnormsize) { | ||
1294 | printk (KERN_WARNING "%s: no TV norms defined!\n", | ||
1295 | vfd->name); | ||
1296 | break; | ||
1297 | } | ||
1298 | 1353 | ||
1299 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1354 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1300 | return -EINVAL; | 1355 | return -EINVAL; |
1301 | 1356 | ||
1302 | for (i = 0; i < vfd->tvnormsize; i++) | ||
1303 | if (vfd->tvnorms[i].id == vfd->current_norm) | ||
1304 | break; | ||
1305 | if (i >= vfd->tvnormsize) | ||
1306 | return -EINVAL; | ||
1307 | |||
1308 | v4l2_video_std_construct(&s, vfd->current_norm, | 1357 | v4l2_video_std_construct(&s, vfd->current_norm, |
1309 | vfd->tvnorms[i].name); | 1358 | v4l2_norm_to_name(vfd->current_norm)); |
1310 | 1359 | ||
1311 | memset(p,0,sizeof(*p)); | 1360 | memset(p,0,sizeof(*p)); |
1312 | 1361 | ||
@@ -1329,8 +1378,14 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1329 | case VIDIOC_G_TUNER: | 1378 | case VIDIOC_G_TUNER: |
1330 | { | 1379 | { |
1331 | struct v4l2_tuner *p=arg; | 1380 | struct v4l2_tuner *p=arg; |
1381 | __u32 index=p->index; | ||
1382 | |||
1332 | if (!vfd->vidioc_g_tuner) | 1383 | if (!vfd->vidioc_g_tuner) |
1333 | break; | 1384 | break; |
1385 | |||
1386 | memset(p,0,sizeof(*p)); | ||
1387 | p->index=index; | ||
1388 | |||
1334 | ret=vfd->vidioc_g_tuner(file, fh, p); | 1389 | ret=vfd->vidioc_g_tuner(file, fh, p); |
1335 | if (!ret) | 1390 | if (!ret) |
1336 | dbgarg (cmd, "index=%d, name=%s, type=%d, " | 1391 | dbgarg (cmd, "index=%d, name=%s, type=%d, " |
@@ -1363,6 +1418,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1363 | struct v4l2_frequency *p=arg; | 1418 | struct v4l2_frequency *p=arg; |
1364 | if (!vfd->vidioc_g_frequency) | 1419 | if (!vfd->vidioc_g_frequency) |
1365 | break; | 1420 | break; |
1421 | |||
1422 | memset(p,0,sizeof(*p)); | ||
1423 | |||
1366 | ret=vfd->vidioc_g_frequency(file, fh, p); | 1424 | ret=vfd->vidioc_g_frequency(file, fh, p); |
1367 | if (!ret) | 1425 | if (!ret) |
1368 | dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", | 1426 | dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", |
@@ -1396,12 +1454,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1396 | ret=vfd->vidioc_log_status(file, fh); | 1454 | ret=vfd->vidioc_log_status(file, fh); |
1397 | break; | 1455 | break; |
1398 | } | 1456 | } |
1399 | 1457 | } /* switch */ | |
1400 | /* --- Others --------------------------------------------- */ | ||
1401 | |||
1402 | default: | ||
1403 | ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl); | ||
1404 | } | ||
1405 | 1458 | ||
1406 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { | 1459 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { |
1407 | if (ret<0) { | 1460 | if (ret<0) { |
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 9986de5cb3d6..474ddb779643 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -1044,16 +1044,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
1044 | return (0); | 1044 | return (0); |
1045 | } | 1045 | } |
1046 | 1046 | ||
1047 | static struct v4l2_tvnorm tvnorms[] = { | 1047 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *i) |
1048 | { | ||
1049 | .name = "NTSC-M", | ||
1050 | .id = V4L2_STD_NTSC_M, | ||
1051 | } | ||
1052 | }; | ||
1053 | |||
1054 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a) | ||
1055 | { | 1048 | { |
1056 | |||
1057 | return 0; | 1049 | return 0; |
1058 | } | 1050 | } |
1059 | 1051 | ||
@@ -1333,8 +1325,8 @@ static struct video_device vivi = { | |||
1333 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 1325 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1334 | .vidiocgmbuf = vidiocgmbuf, | 1326 | .vidiocgmbuf = vidiocgmbuf, |
1335 | #endif | 1327 | #endif |
1336 | .tvnorms = tvnorms, | 1328 | .tvnorms = V4L2_STD_NTSC_M, |
1337 | .tvnormsize = ARRAY_SIZE(tvnorms), | 1329 | .current_norm = V4L2_STD_NTSC_M, |
1338 | }; | 1330 | }; |
1339 | /* ----------------------------------------------------------------- | 1331 | /* ----------------------------------------------------------------- |
1340 | Initialization and module stuff | 1332 | Initialization and module stuff |
@@ -1361,8 +1353,6 @@ static int __init vivi_init(void) | |||
1361 | dev->vidq.timeout.data = (unsigned long)dev; | 1353 | dev->vidq.timeout.data = (unsigned long)dev; |
1362 | init_timer(&dev->vidq.timeout); | 1354 | init_timer(&dev->vidq.timeout); |
1363 | 1355 | ||
1364 | vivi.current_norm = tvnorms[0].id; | ||
1365 | |||
1366 | ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr); | 1356 | ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr); |
1367 | printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret); | 1357 | printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret); |
1368 | return ret; | 1358 | return ret; |
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c deleted file mode 100644 index 0cbf564388a6..000000000000 --- a/drivers/media/video/zr36120.c +++ /dev/null | |||
@@ -1,2079 +0,0 @@ | |||
1 | /* | ||
2 | zr36120.c - Zoran 36120/36125 based framegrabbers | ||
3 | |||
4 | Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/major.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/vmalloc.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/signal.h> | ||
33 | #include <linux/wait.h> | ||
34 | #include <asm/io.h> | ||
35 | #include <asm/pgtable.h> | ||
36 | #include <asm/page.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/video_decoder.h> | ||
39 | |||
40 | #include <asm/uaccess.h> | ||
41 | |||
42 | #include "tuner.h" | ||
43 | #include "zr36120.h" | ||
44 | #include "zr36120_mem.h" | ||
45 | |||
46 | /* mark an required function argument unused - lintism */ | ||
47 | #define UNUSED(x) (void)(x) | ||
48 | |||
49 | /* sensible default */ | ||
50 | #ifndef CARDTYPE | ||
51 | #define CARDTYPE 0 | ||
52 | #endif | ||
53 | |||
54 | /* Anybody who uses more than four? */ | ||
55 | #define ZORAN_MAX 4 | ||
56 | |||
57 | static unsigned int triton1=0; /* triton1 chipset? */ | ||
58 | static unsigned int cardtype[ZORAN_MAX]={ [ 0 ... ZORAN_MAX-1 ] = CARDTYPE }; | ||
59 | static int video_nr = -1; | ||
60 | static int vbi_nr = -1; | ||
61 | |||
62 | static struct pci_device_id zr36120_pci_tbl[] = { | ||
63 | { PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, | ||
64 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
65 | { 0 } | ||
66 | }; | ||
67 | MODULE_DEVICE_TABLE(pci, zr36120_pci_tbl); | ||
68 | |||
69 | MODULE_AUTHOR("Pauline Middelink <middelin@polyware.nl>"); | ||
70 | MODULE_DESCRIPTION("Zoran ZR36120 based framegrabber"); | ||
71 | MODULE_LICENSE("GPL"); | ||
72 | |||
73 | module_param(triton1, uint, 0); | ||
74 | module_param_array(cardtype, uint, NULL, 0); | ||
75 | module_param(video_nr, int, 0); | ||
76 | module_param(vbi_nr, int, 0); | ||
77 | |||
78 | static int zoran_cards; | ||
79 | static struct zoran zorans[ZORAN_MAX]; | ||
80 | |||
81 | /* | ||
82 | * the meaning of each element can be found in zr36120.h | ||
83 | * Determining the value of gpdir/gpval can be tricky. The | ||
84 | * best way is to run the card under the original software | ||
85 | * and read the values from the general purpose registers | ||
86 | * 0x28 and 0x2C. How you do that is left as an exercise | ||
87 | * to the impatient reader :) | ||
88 | */ | ||
89 | #define T 1 /* to separate the bools from the ints */ | ||
90 | #define F 0 | ||
91 | static struct tvcard tvcards[] = { | ||
92 | /* reported working by <middelin@polyware.nl> */ | ||
93 | /*0*/ { "Trust Victor II", | ||
94 | 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, | ||
95 | /* reported working by <Michael.Paxton@aihw.gov.au> */ | ||
96 | /*1*/ { "Aitech WaveWatcher TV-PCI", | ||
97 | 3, 0, T, F, T, T, 0x7F, 0x80, { 1, TUNER(3), SVHS(6) }, { 0 } }, | ||
98 | /* reported working by ? */ | ||
99 | /*2*/ { "Genius Video Wonder PCI Video Capture Card", | ||
100 | 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, | ||
101 | /* reported working by <Pascal.Gabriel@wanadoo.fr> */ | ||
102 | /*3*/ { "Guillemot Maxi-TV PCI", | ||
103 | 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, | ||
104 | /* reported working by "Craig Whitmore <lennon@igrin.co.nz> */ | ||
105 | /*4*/ { "Quadrant Buster", | ||
106 | 3, 3, T, F, T, T, 0x7F, 0x80, { SVHS(1), TUNER(2), 3 }, { 1, 2, 3 } }, | ||
107 | /* a debug entry which has all inputs mapped */ | ||
108 | /*5*/ { "ZR36120 based framegrabber (all inputs enabled)", | ||
109 | 6, 0, T, T, T, T, 0x7F, 0x80, { 1, 2, 3, 4, 5, 6 }, { 0 } } | ||
110 | }; | ||
111 | #undef T | ||
112 | #undef F | ||
113 | #define NRTVCARDS (sizeof(tvcards)/sizeof(tvcards[0])) | ||
114 | |||
115 | #ifdef __sparc__ | ||
116 | #define ENDIANESS 0 | ||
117 | #else | ||
118 | #define ENDIANESS ZORAN_VFEC_LE | ||
119 | #endif | ||
120 | |||
121 | static struct { const char name[8]; uint mode; uint bpp; } palette2fmt[] = { | ||
122 | /* n/a */ { "n/a", 0, 0 }, | ||
123 | /* GREY */ { "GRAY", 0, 0 }, | ||
124 | /* HI240 */ { "HI240", 0, 0 }, | ||
125 | /* RGB565 */ { "RGB565", ZORAN_VFEC_RGB_RGB565|ENDIANESS, 2 }, | ||
126 | /* RGB24 */ { "RGB24", ZORAN_VFEC_RGB_RGB888|ENDIANESS|ZORAN_VFEC_PACK24, 3 }, | ||
127 | /* RGB32 */ { "RGB32", ZORAN_VFEC_RGB_RGB888|ENDIANESS, 4 }, | ||
128 | /* RGB555 */ { "RGB555", ZORAN_VFEC_RGB_RGB555|ENDIANESS, 2 }, | ||
129 | /* YUV422 */ { "YUV422", ZORAN_VFEC_RGB_YUV422|ENDIANESS, 2 }, | ||
130 | /* YUYV */ { "YUYV", 0, 0 }, | ||
131 | /* UYVY */ { "UYVY", 0, 0 }, | ||
132 | /* YUV420 */ { "YUV420", 0, 0 }, | ||
133 | /* YUV411 */ { "YUV411", 0, 0 }, | ||
134 | /* RAW */ { "RAW", 0, 0 }, | ||
135 | /* YUV422P */ { "YUV422P", 0, 0 }, | ||
136 | /* YUV411P */ { "YUV411P", 0, 0 }}; | ||
137 | #define NRPALETTES (sizeof(palette2fmt)/sizeof(palette2fmt[0])) | ||
138 | #undef ENDIANESS | ||
139 | |||
140 | /* ----------------------------------------------------------------------- */ | ||
141 | /* ZORAN chipset detector */ | ||
142 | /* shamelessly stolen from bttv.c */ | ||
143 | /* Reason for beeing here: we need to detect if we are running on a */ | ||
144 | /* Triton based chipset, and if so, enable a certain bit */ | ||
145 | /* ----------------------------------------------------------------------- */ | ||
146 | static | ||
147 | void __init handle_chipset(void) | ||
148 | { | ||
149 | /* Just in case some nut set this to something dangerous */ | ||
150 | if (triton1) | ||
151 | triton1 = ZORAN_VDC_TRICOM; | ||
152 | |||
153 | if (pci_pci_problems & PCIPCI_TRITON) { | ||
154 | printk(KERN_INFO "zoran: Host bridge 82437FX Triton PIIX\n"); | ||
155 | triton1 = ZORAN_VDC_TRICOM; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | /* ----------------------------------------------------------------------- */ | ||
160 | /* ZORAN functions */ | ||
161 | /* ----------------------------------------------------------------------- */ | ||
162 | |||
163 | static void zoran_set_geo(struct zoran* ztv, struct vidinfo* i); | ||
164 | |||
165 | #if 0 /* unused */ | ||
166 | static | ||
167 | void zoran_dump(struct zoran *ztv) | ||
168 | { | ||
169 | char str[256]; | ||
170 | char *p=str; /* shut up, gcc! */ | ||
171 | int i; | ||
172 | |||
173 | for (i=0; i<0x60; i+=4) { | ||
174 | if ((i % 16) == 0) { | ||
175 | if (i) printk("%s\n",str); | ||
176 | p = str; | ||
177 | p+= sprintf(str, KERN_DEBUG " %04x: ",i); | ||
178 | } | ||
179 | p += sprintf(p, "%08x ",zrread(i)); | ||
180 | } | ||
181 | } | ||
182 | #endif /* unused */ | ||
183 | |||
184 | static | ||
185 | void reap_states(struct zoran* ztv) | ||
186 | { | ||
187 | /* count frames */ | ||
188 | ztv->fieldnr++; | ||
189 | |||
190 | /* | ||
191 | * Are we busy at all? | ||
192 | * This depends on if there is a workqueue AND the | ||
193 | * videotransfer is enabled on the chip... | ||
194 | */ | ||
195 | if (ztv->workqueue && (zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN)) | ||
196 | { | ||
197 | struct vidinfo* newitem; | ||
198 | |||
199 | /* did we get a complete frame? */ | ||
200 | if (zrread(ZORAN_VSTR) & ZORAN_VSTR_GRAB) | ||
201 | return; | ||
202 | |||
203 | DEBUG(printk(CARD_DEBUG "completed %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue)); | ||
204 | |||
205 | /* we are done with this buffer, tell everyone */ | ||
206 | ztv->workqueue->status = FBUFFER_DONE; | ||
207 | ztv->workqueue->fieldnr = ztv->fieldnr; | ||
208 | /* not good, here for BTTV_FIELDNR reasons */ | ||
209 | ztv->lastfieldnr = ztv->fieldnr; | ||
210 | |||
211 | switch (ztv->workqueue->kindof) { | ||
212 | case FBUFFER_GRAB: | ||
213 | wake_up_interruptible(&ztv->grabq); | ||
214 | break; | ||
215 | case FBUFFER_VBI: | ||
216 | wake_up_interruptible(&ztv->vbiq); | ||
217 | break; | ||
218 | default: | ||
219 | printk(CARD_INFO "somebody killed the workqueue (kindof=%d)!\n",CARD,ztv->workqueue->kindof); | ||
220 | } | ||
221 | |||
222 | /* item completed, skip to next item in queue */ | ||
223 | write_lock(&ztv->lock); | ||
224 | newitem = ztv->workqueue->next; | ||
225 | ztv->workqueue->next = 0; /* mark completed */ | ||
226 | ztv->workqueue = newitem; | ||
227 | write_unlock(&ztv->lock); | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * ok, so it seems we have nothing in progress right now. | ||
232 | * Lets see if we can find some work. | ||
233 | */ | ||
234 | if (ztv->workqueue) | ||
235 | { | ||
236 | struct vidinfo* newitem; | ||
237 | again: | ||
238 | |||
239 | DEBUG(printk(CARD_DEBUG "starting %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue)); | ||
240 | |||
241 | /* loadup the frame settings */ | ||
242 | read_lock(&ztv->lock); | ||
243 | zoran_set_geo(ztv,ztv->workqueue); | ||
244 | read_unlock(&ztv->lock); | ||
245 | |||
246 | switch (ztv->workqueue->kindof) { | ||
247 | case FBUFFER_GRAB: | ||
248 | case FBUFFER_VBI: | ||
249 | zrand(~ZORAN_OCR_OVLEN, ZORAN_OCR); | ||
250 | zror(ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR); | ||
251 | zror(ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
252 | |||
253 | /* start single-shot grab */ | ||
254 | zror(ZORAN_VSTR_GRAB, ZORAN_VSTR); | ||
255 | break; | ||
256 | default: | ||
257 | printk(CARD_INFO "what is this doing on the queue? (kindof=%d)\n",CARD,ztv->workqueue->kindof); | ||
258 | write_lock(&ztv->lock); | ||
259 | newitem = ztv->workqueue->next; | ||
260 | ztv->workqueue->next = 0; | ||
261 | ztv->workqueue = newitem; | ||
262 | write_unlock(&ztv->lock); | ||
263 | if (newitem) | ||
264 | goto again; /* yeah, sure.. */ | ||
265 | } | ||
266 | /* bye for now */ | ||
267 | return; | ||
268 | } | ||
269 | DEBUG(printk(CARD_DEBUG "nothing in queue\n",CARD)); | ||
270 | |||
271 | /* | ||
272 | * What? Even the workqueue is empty? Am i really here | ||
273 | * for nothing? Did i come all that way to... do nothing? | ||
274 | */ | ||
275 | |||
276 | /* do we need to overlay? */ | ||
277 | if (test_bit(STATE_OVERLAY, &ztv->state)) | ||
278 | { | ||
279 | /* are we already overlaying? */ | ||
280 | if (!(zrread(ZORAN_OCR) & ZORAN_OCR_OVLEN) || | ||
281 | !(zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN)) | ||
282 | { | ||
283 | DEBUG(printk(CARD_DEBUG "starting overlay\n",CARD)); | ||
284 | |||
285 | read_lock(&ztv->lock); | ||
286 | zoran_set_geo(ztv,&ztv->overinfo); | ||
287 | read_unlock(&ztv->lock); | ||
288 | |||
289 | zror(ZORAN_OCR_OVLEN, ZORAN_OCR); | ||
290 | zrand(~ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR); | ||
291 | zror(ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * leave overlaying on, but turn interrupts off. | ||
296 | */ | ||
297 | zrand(~ZORAN_ICR_EN,ZORAN_ICR); | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | /* do we have any VBI idle time processing? */ | ||
302 | if (test_bit(STATE_VBI, &ztv->state)) | ||
303 | { | ||
304 | struct vidinfo* item; | ||
305 | struct vidinfo* lastitem; | ||
306 | |||
307 | /* protect the workqueue */ | ||
308 | write_lock(&ztv->lock); | ||
309 | lastitem = ztv->workqueue; | ||
310 | if (lastitem) | ||
311 | while (lastitem->next) lastitem = lastitem->next; | ||
312 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) | ||
313 | if (item->next == 0 && item->status == FBUFFER_FREE) | ||
314 | { | ||
315 | DEBUG(printk(CARD_DEBUG "%p added to queue\n",CARD,item)); | ||
316 | item->status = FBUFFER_BUSY; | ||
317 | if (!lastitem) | ||
318 | ztv->workqueue = item; | ||
319 | else | ||
320 | lastitem->next = item; | ||
321 | lastitem = item; | ||
322 | } | ||
323 | write_unlock(&ztv->lock); | ||
324 | if (ztv->workqueue) | ||
325 | goto again; /* hey, _i_ graduated :) */ | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | * Then we must be realy IDLE | ||
330 | */ | ||
331 | DEBUG(printk(CARD_DEBUG "turning off\n",CARD)); | ||
332 | /* nothing further to do, disable DMA and further IRQs */ | ||
333 | zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
334 | zrand(~ZORAN_ICR_EN,ZORAN_ICR); | ||
335 | } | ||
336 | |||
337 | static | ||
338 | void zoran_irq(int irq, void *dev_id) | ||
339 | { | ||
340 | u32 stat,estat; | ||
341 | int count = 0; | ||
342 | struct zoran *ztv = dev_id; | ||
343 | |||
344 | UNUSED(irq); | ||
345 | for (;;) { | ||
346 | /* get/clear interrupt status bits */ | ||
347 | stat=zrread(ZORAN_ISR); | ||
348 | estat=stat & zrread(ZORAN_ICR); | ||
349 | if (!estat) | ||
350 | return; | ||
351 | zrwrite(estat,ZORAN_ISR); | ||
352 | IDEBUG(printk(CARD_DEBUG "estat %08x\n",CARD,estat)); | ||
353 | IDEBUG(printk(CARD_DEBUG " stat %08x\n",CARD,stat)); | ||
354 | |||
355 | if (estat & ZORAN_ISR_CODE) | ||
356 | { | ||
357 | IDEBUG(printk(CARD_DEBUG "CodReplIRQ\n",CARD)); | ||
358 | } | ||
359 | if (estat & ZORAN_ISR_GIRQ0) | ||
360 | { | ||
361 | IDEBUG(printk(CARD_DEBUG "GIRQ0\n",CARD)); | ||
362 | if (!ztv->card->usegirq1) | ||
363 | reap_states(ztv); | ||
364 | } | ||
365 | if (estat & ZORAN_ISR_GIRQ1) | ||
366 | { | ||
367 | IDEBUG(printk(CARD_DEBUG "GIRQ1\n",CARD)); | ||
368 | if (ztv->card->usegirq1) | ||
369 | reap_states(ztv); | ||
370 | } | ||
371 | |||
372 | count++; | ||
373 | if (count > 10) | ||
374 | printk(CARD_ERR "irq loop %d (%x)\n",CARD,count,estat); | ||
375 | if (count > 20) | ||
376 | { | ||
377 | zrwrite(0, ZORAN_ICR); | ||
378 | printk(CARD_ERR "IRQ lockup, cleared int mask\n",CARD); | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | |||
383 | static | ||
384 | int zoran_muxsel(struct zoran* ztv, int channel, int norm) | ||
385 | { | ||
386 | int rv; | ||
387 | |||
388 | /* set the new video norm */ | ||
389 | rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &norm); | ||
390 | if (rv) | ||
391 | return rv; | ||
392 | ztv->norm = norm; | ||
393 | |||
394 | /* map the given channel to the cards decoder's channel */ | ||
395 | channel = ztv->card->video_mux[channel] & CHANNEL_MASK; | ||
396 | |||
397 | /* set the new channel */ | ||
398 | rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &channel); | ||
399 | return rv; | ||
400 | } | ||
401 | |||
402 | /* Tell the interrupt handler what to to. */ | ||
403 | static | ||
404 | void zoran_cap(struct zoran* ztv, int on) | ||
405 | { | ||
406 | DEBUG(printk(CARD_DEBUG "zoran_cap(%d) state=%x\n",CARD,on,ztv->state)); | ||
407 | |||
408 | if (on) { | ||
409 | ztv->running = 1; | ||
410 | |||
411 | /* | ||
412 | * turn interrupts (back) on. The DMA will be enabled | ||
413 | * inside the irq handler when it detects a restart. | ||
414 | */ | ||
415 | zror(ZORAN_ICR_EN,ZORAN_ICR); | ||
416 | } | ||
417 | else { | ||
418 | /* | ||
419 | * turn both interrupts and DMA off | ||
420 | */ | ||
421 | zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
422 | zrand(~ZORAN_ICR_EN,ZORAN_ICR); | ||
423 | |||
424 | ztv->running = 0; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | static ulong dmask[] = { | ||
429 | 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8, | ||
430 | 0xFFFFFFF0, 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80, | ||
431 | 0xFFFFFF00, 0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800, | ||
432 | 0xFFFFF000, 0xFFFFE000, 0xFFFFC000, 0xFFFF8000, | ||
433 | 0xFFFF0000, 0xFFFE0000, 0xFFFC0000, 0xFFF80000, | ||
434 | 0xFFF00000, 0xFFE00000, 0xFFC00000, 0xFF800000, | ||
435 | 0xFF000000, 0xFE000000, 0xFC000000, 0xF8000000, | ||
436 | 0xF0000000, 0xE0000000, 0xC0000000, 0x80000000 | ||
437 | }; | ||
438 | |||
439 | static | ||
440 | void zoran_built_overlay(struct zoran* ztv, int count, struct video_clip *vcp) | ||
441 | { | ||
442 | ulong* mtop; | ||
443 | int ystep = (ztv->vidXshift + ztv->vidWidth+31)/32; /* next DWORD */ | ||
444 | int i; | ||
445 | |||
446 | DEBUG(printk(KERN_DEBUG " overlay at %p, ystep=%d, clips=%d\n",ztv->overinfo.overlay,ystep,count)); | ||
447 | |||
448 | for (i=0; i<count; i++) { | ||
449 | struct video_clip *vp = vcp+i; | ||
450 | UNUSED(vp); | ||
451 | DEBUG(printk(KERN_DEBUG " %d: clip(%d,%d,%d,%d)\n", i,vp->x,vp->y,vp->width,vp->height)); | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | * activate the visible portion of the screen | ||
456 | * Note we take some shortcuts here, because we | ||
457 | * know the width can never be < 32. (I.e. a DWORD) | ||
458 | * We also assume the overlay starts somewhere in | ||
459 | * the FIRST dword. | ||
460 | */ | ||
461 | { | ||
462 | int start = ztv->vidXshift; | ||
463 | ulong firstd = dmask[start]; | ||
464 | ulong lastd = ~dmask[(start + ztv->overinfo.w) & 31]; | ||
465 | mtop = ztv->overinfo.overlay; | ||
466 | for (i=0; i<ztv->overinfo.h; i++) { | ||
467 | int w = ztv->vidWidth; | ||
468 | ulong* line = mtop; | ||
469 | if (start & 31) { | ||
470 | *line++ = firstd; | ||
471 | w -= 32-(start&31); | ||
472 | } | ||
473 | memset(line, ~0, w/8); | ||
474 | if (w & 31) | ||
475 | line[w/32] = lastd; | ||
476 | mtop += ystep; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /* process clipping regions */ | ||
481 | for (i=0; i<count; i++) { | ||
482 | int h; | ||
483 | if (vcp->x < 0 || (uint)vcp->x > ztv->overinfo.w || | ||
484 | vcp->y < 0 || vcp->y > ztv->overinfo.h || | ||
485 | vcp->width < 0 || (uint)(vcp->x+vcp->width) > ztv->overinfo.w || | ||
486 | vcp->height < 0 || (vcp->y+vcp->height) > ztv->overinfo.h) | ||
487 | { | ||
488 | DEBUG(printk(CARD_DEBUG "invalid clipzone (%d,%d,%d,%d) not in (0,0,%d,%d), adapting\n",CARD,vcp->x,vcp->y,vcp->width,vcp->height,ztv->overinfo.w,ztv->overinfo.h)); | ||
489 | if (vcp->x < 0) vcp->x = 0; | ||
490 | if ((uint)vcp->x > ztv->overinfo.w) vcp->x = ztv->overinfo.w; | ||
491 | if (vcp->y < 0) vcp->y = 0; | ||
492 | if (vcp->y > ztv->overinfo.h) vcp->y = ztv->overinfo.h; | ||
493 | if (vcp->width < 0) vcp->width = 0; | ||
494 | if ((uint)(vcp->x+vcp->width) > ztv->overinfo.w) vcp->width = ztv->overinfo.w - vcp->x; | ||
495 | if (vcp->height < 0) vcp->height = 0; | ||
496 | if (vcp->y+vcp->height > ztv->overinfo.h) vcp->height = ztv->overinfo.h - vcp->y; | ||
497 | // continue; | ||
498 | } | ||
499 | |||
500 | mtop = &ztv->overinfo.overlay[vcp->y*ystep]; | ||
501 | for (h=0; h<=vcp->height; h++) { | ||
502 | int w; | ||
503 | int x = ztv->vidXshift + vcp->x; | ||
504 | for (w=0; w<=vcp->width; w++) { | ||
505 | clear_bit(x&31, &mtop[x/32]); | ||
506 | x++; | ||
507 | } | ||
508 | mtop += ystep; | ||
509 | } | ||
510 | ++vcp; | ||
511 | } | ||
512 | |||
513 | mtop = ztv->overinfo.overlay; | ||
514 | zrwrite(virt_to_bus(mtop), ZORAN_MTOP); | ||
515 | zrwrite(virt_to_bus(mtop+ystep), ZORAN_MBOT); | ||
516 | zraor((ztv->vidInterlace*ystep)<<0,~ZORAN_OCR_MASKSTRIDE,ZORAN_OCR); | ||
517 | } | ||
518 | |||
519 | struct tvnorm | ||
520 | { | ||
521 | u16 Wt, Wa, Ht, Ha, HStart, VStart; | ||
522 | }; | ||
523 | |||
524 | static struct tvnorm tvnorms[] = { | ||
525 | /* PAL-BDGHI */ | ||
526 | /* { 864, 720, 625, 576, 131, 21 },*/ | ||
527 | /*00*/ { 864, 768, 625, 576, 81, 17 }, | ||
528 | /* NTSC */ | ||
529 | /*01*/ { 858, 720, 525, 480, 121, 10 }, | ||
530 | /* SECAM */ | ||
531 | /*02*/ { 864, 720, 625, 576, 131, 21 }, | ||
532 | /* BW50 */ | ||
533 | /*03*/ { 864, 720, 625, 576, 131, 21 }, | ||
534 | /* BW60 */ | ||
535 | /*04*/ { 858, 720, 525, 480, 121, 10 } | ||
536 | }; | ||
537 | #define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm)) | ||
538 | |||
539 | /* | ||
540 | * Program the chip for a setup as described in the vidinfo struct. | ||
541 | * | ||
542 | * Side-effects: calculates vidXshift, vidInterlace, | ||
543 | * vidHeight, vidWidth which are used in a later stage | ||
544 | * to calculate the overlay mask | ||
545 | * | ||
546 | * This is an internal function, as such it does not check the | ||
547 | * validity of the struct members... Spectaculair crashes will | ||
548 | * follow /very/ quick when you're wrong and the chip right :) | ||
549 | */ | ||
550 | static | ||
551 | void zoran_set_geo(struct zoran* ztv, struct vidinfo* i) | ||
552 | { | ||
553 | ulong top, bot; | ||
554 | int stride; | ||
555 | int winWidth, winHeight; | ||
556 | int maxWidth, maxHeight, maxXOffset, maxYOffset; | ||
557 | long vfec; | ||
558 | |||
559 | DEBUG(printk(CARD_DEBUG "set_geo(rect=(%d,%d,%d,%d), norm=%d, format=%d, bpp=%d, bpl=%d, busadr=%lx, overlay=%p)\n",CARD,i->x,i->y,i->w,i->h,ztv->norm,i->format,i->bpp,i->bpl,i->busadr,i->overlay)); | ||
560 | |||
561 | /* | ||
562 | * make sure the DMA transfers are inhibited during our | ||
563 | * reprogramming of the chip | ||
564 | */ | ||
565 | zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); | ||
566 | |||
567 | maxWidth = tvnorms[ztv->norm].Wa; | ||
568 | maxHeight = tvnorms[ztv->norm].Ha/2; | ||
569 | maxXOffset = tvnorms[ztv->norm].HStart; | ||
570 | maxYOffset = tvnorms[ztv->norm].VStart; | ||
571 | |||
572 | /* setup vfec register (keep ExtFl,TopField and VCLKPol settings) */ | ||
573 | vfec = (zrread(ZORAN_VFEC) & (ZORAN_VFEC_EXTFL|ZORAN_VFEC_TOPFIELD|ZORAN_VFEC_VCLKPOL)) | | ||
574 | (palette2fmt[i->format].mode & (ZORAN_VFEC_RGB|ZORAN_VFEC_ERRDIF|ZORAN_VFEC_LE|ZORAN_VFEC_PACK24)); | ||
575 | |||
576 | /* | ||
577 | * Set top, bottom ptrs. Since these must be DWORD aligned, | ||
578 | * possible adjust the x and the width of the window. | ||
579 | * so the endposition stay the same. The vidXshift will make | ||
580 | * sure we are not writing pixels before the requested x. | ||
581 | */ | ||
582 | ztv->vidXshift = 0; | ||
583 | winWidth = i->w; | ||
584 | if (winWidth < 0) | ||
585 | winWidth = -winWidth; | ||
586 | top = i->busadr + i->x*i->bpp + i->y*i->bpl; | ||
587 | if (top & 3) { | ||
588 | ztv->vidXshift = (top & 3) / i->bpp; | ||
589 | winWidth += ztv->vidXshift; | ||
590 | DEBUG(printk(KERN_DEBUG " window-x shifted %d pixels left\n",ztv->vidXshift)); | ||
591 | top &= ~3; | ||
592 | } | ||
593 | |||
594 | /* | ||
595 | * bottom points to next frame but in interleaved mode we want | ||
596 | * to 'mix' the 2 frames to one capture, so 'bot' points to one | ||
597 | * (physical) line below the top line. | ||
598 | */ | ||
599 | bot = top + i->bpl; | ||
600 | zrwrite(top,ZORAN_VTOP); | ||
601 | zrwrite(bot,ZORAN_VBOT); | ||
602 | |||
603 | /* | ||
604 | * Make sure the winWidth is DWORD aligned too, | ||
605 | * thereby automaticly making sure the stride to the | ||
606 | * next line is DWORD aligned too (as required by spec). | ||
607 | */ | ||
608 | if ((winWidth*i->bpp) & 3) { | ||
609 | DEBUG(printk(KERN_DEBUG " window-width enlarged by %d pixels\n",(winWidth*i->bpp) & 3)); | ||
610 | winWidth += (winWidth*i->bpp) & 3; | ||
611 | } | ||
612 | |||
613 | /* determine the DispMode and stride */ | ||
614 | if (i->h >= 0 && i->h <= maxHeight) { | ||
615 | /* single frame grab suffices for this height. */ | ||
616 | vfec |= ZORAN_VFEC_DISPMOD; | ||
617 | ztv->vidInterlace = 0; | ||
618 | stride = i->bpl - (winWidth*i->bpp); | ||
619 | winHeight = i->h; | ||
620 | } | ||
621 | else { | ||
622 | /* interleaving needed for this height */ | ||
623 | ztv->vidInterlace = 1; | ||
624 | stride = i->bpl*2 - (winWidth*i->bpp); | ||
625 | winHeight = i->h/2; | ||
626 | } | ||
627 | if (winHeight < 0) /* can happen for VBI! */ | ||
628 | winHeight = -winHeight; | ||
629 | |||
630 | /* safety net, sometimes bpl is too short??? */ | ||
631 | if (stride<0) { | ||
632 | DEBUG(printk(CARD_DEBUG "WARNING stride = %d\n",CARD,stride)); | ||
633 | stride = 0; | ||
634 | } | ||
635 | |||
636 | zraor((winHeight<<12)|(winWidth<<0),~(ZORAN_VDC_VIDWINHT|ZORAN_VDC_VIDWINWID), ZORAN_VDC); | ||
637 | zraor(stride<<16,~ZORAN_VSTR_DISPSTRIDE,ZORAN_VSTR); | ||
638 | |||
639 | /* remember vidWidth, vidHeight for overlay calculations */ | ||
640 | ztv->vidWidth = winWidth; | ||
641 | ztv->vidHeight = winHeight; | ||
642 | DEBUG(printk(KERN_DEBUG " top=%08lx, bottom=%08lx\n",top,bot)); | ||
643 | DEBUG(printk(KERN_DEBUG " winWidth=%d, winHeight=%d\n",winWidth,winHeight)); | ||
644 | DEBUG(printk(KERN_DEBUG " maxWidth=%d, maxHeight=%d\n",maxWidth,maxHeight)); | ||
645 | DEBUG(printk(KERN_DEBUG " stride=%d\n",stride)); | ||
646 | |||
647 | /* | ||
648 | * determine horizontal scales and crops | ||
649 | */ | ||
650 | if (i->w < 0) { | ||
651 | int Hstart = 1; | ||
652 | int Hend = Hstart + winWidth; | ||
653 | DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Hstart, Hend)); | ||
654 | zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH); | ||
655 | } | ||
656 | else { | ||
657 | int Wa = maxWidth; | ||
658 | int X = (winWidth*64+Wa-1)/Wa; | ||
659 | int We = winWidth*64/X; | ||
660 | int HorDcm = 64-X; | ||
661 | int hcrop1 = 2*(Wa-We)/4; | ||
662 | /* | ||
663 | * BUGFIX: Juha Nurmela <junki@qn-lpr2-165.quicknet.inet.fi> | ||
664 | * found the solution to the color phase shift. | ||
665 | * See ChangeLog for the full explanation) | ||
666 | */ | ||
667 | int Hstart = (maxXOffset + hcrop1) | 1; | ||
668 | int Hend = Hstart + We - 1; | ||
669 | |||
670 | DEBUG(printk(KERN_DEBUG " X: scale=%d, start=%d, end=%d\n", HorDcm, Hstart, Hend)); | ||
671 | |||
672 | zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH); | ||
673 | vfec |= HorDcm<<14; | ||
674 | |||
675 | if (HorDcm<16) | ||
676 | vfec |= ZORAN_VFEC_HFILTER_1; /* no filter */ | ||
677 | else if (HorDcm<32) | ||
678 | vfec |= ZORAN_VFEC_HFILTER_3; /* 3 tap filter */ | ||
679 | else if (HorDcm<48) | ||
680 | vfec |= ZORAN_VFEC_HFILTER_4; /* 4 tap filter */ | ||
681 | else vfec |= ZORAN_VFEC_HFILTER_5; /* 5 tap filter */ | ||
682 | } | ||
683 | |||
684 | /* | ||
685 | * Determine vertical scales and crops | ||
686 | * | ||
687 | * when height is negative, we want to read starting at line 0 | ||
688 | * One day someone might need access to these lines... | ||
689 | */ | ||
690 | if (i->h < 0) { | ||
691 | int Vstart = 0; | ||
692 | int Vend = Vstart + winHeight; | ||
693 | DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Vstart, Vend)); | ||
694 | zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV); | ||
695 | } | ||
696 | else { | ||
697 | int Ha = maxHeight; | ||
698 | int Y = (winHeight*64+Ha-1)/Ha; | ||
699 | int He = winHeight*64/Y; | ||
700 | int VerDcm = 64-Y; | ||
701 | int vcrop1 = 2*(Ha-He)/4; | ||
702 | int Vstart = maxYOffset + vcrop1; | ||
703 | int Vend = Vstart + He - 1; | ||
704 | |||
705 | DEBUG(printk(KERN_DEBUG " Y: scale=%d, start=%d, end=%d\n", VerDcm, Vstart, Vend)); | ||
706 | zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV); | ||
707 | vfec |= VerDcm<<8; | ||
708 | } | ||
709 | |||
710 | DEBUG(printk(KERN_DEBUG " F: format=%d(=%s)\n",i->format,palette2fmt[i->format].name)); | ||
711 | |||
712 | /* setup the requested format */ | ||
713 | zrwrite(vfec, ZORAN_VFEC); | ||
714 | } | ||
715 | |||
716 | static | ||
717 | void zoran_common_open(struct zoran* ztv, int flags) | ||
718 | { | ||
719 | UNUSED(flags); | ||
720 | |||
721 | /* already opened? */ | ||
722 | if (ztv->users++ != 0) | ||
723 | return; | ||
724 | |||
725 | /* unmute audio */ | ||
726 | /* /what/ audio? */ | ||
727 | |||
728 | ztv->state = 0; | ||
729 | |||
730 | /* setup the encoder to the initial values */ | ||
731 | ztv->picture.colour=254<<7; | ||
732 | ztv->picture.brightness=128<<8; | ||
733 | ztv->picture.hue=128<<8; | ||
734 | ztv->picture.contrast=216<<7; | ||
735 | i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &ztv->picture); | ||
736 | |||
737 | /* default to the composite input since my camera is there */ | ||
738 | zoran_muxsel(ztv, 0, VIDEO_MODE_PAL); | ||
739 | } | ||
740 | |||
741 | static | ||
742 | void zoran_common_close(struct zoran* ztv) | ||
743 | { | ||
744 | if (--ztv->users != 0) | ||
745 | return; | ||
746 | |||
747 | /* mute audio */ | ||
748 | /* /what/ audio? */ | ||
749 | |||
750 | /* stop the chip */ | ||
751 | zoran_cap(ztv, 0); | ||
752 | } | ||
753 | |||
754 | /* | ||
755 | * Open a zoran card. Right now the flags are just a hack | ||
756 | */ | ||
757 | static int zoran_open(struct video_device *dev, int flags) | ||
758 | { | ||
759 | struct zoran *ztv = (struct zoran*)dev; | ||
760 | struct vidinfo* item; | ||
761 | char* pos; | ||
762 | |||
763 | DEBUG(printk(CARD_DEBUG "open(dev,%d)\n",CARD,flags)); | ||
764 | |||
765 | /********************************************* | ||
766 | * We really should be doing lazy allocing... | ||
767 | *********************************************/ | ||
768 | /* allocate a frame buffer */ | ||
769 | if (!ztv->fbuffer) | ||
770 | ztv->fbuffer = bmalloc(ZORAN_MAX_FBUFSIZE); | ||
771 | if (!ztv->fbuffer) { | ||
772 | /* could not get a buffer, bail out */ | ||
773 | return -ENOBUFS; | ||
774 | } | ||
775 | /* at this time we _always_ have a framebuffer */ | ||
776 | memset(ztv->fbuffer,0,ZORAN_MAX_FBUFSIZE); | ||
777 | |||
778 | if (!ztv->overinfo.overlay) | ||
779 | ztv->overinfo.overlay = kmalloc(1024*1024/8, GFP_KERNEL); | ||
780 | if (!ztv->overinfo.overlay) { | ||
781 | /* could not get an overlay buffer, bail out */ | ||
782 | bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE); | ||
783 | return -ENOBUFS; | ||
784 | } | ||
785 | /* at this time we _always_ have a overlay */ | ||
786 | |||
787 | /* clear buffer status, and give them a DMAable address */ | ||
788 | pos = ztv->fbuffer; | ||
789 | for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) | ||
790 | { | ||
791 | item->status = FBUFFER_FREE; | ||
792 | item->memadr = pos; | ||
793 | item->busadr = virt_to_bus(pos); | ||
794 | pos += ZORAN_MAX_FBUFFER; | ||
795 | } | ||
796 | |||
797 | /* do the common part of all open's */ | ||
798 | zoran_common_open(ztv, flags); | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | static | ||
804 | void zoran_close(struct video_device* dev) | ||
805 | { | ||
806 | struct zoran *ztv = (struct zoran*)dev; | ||
807 | |||
808 | DEBUG(printk(CARD_DEBUG "close(dev)\n",CARD)); | ||
809 | |||
810 | /* driver specific closure */ | ||
811 | clear_bit(STATE_OVERLAY, &ztv->state); | ||
812 | |||
813 | zoran_common_close(ztv); | ||
814 | |||
815 | /* | ||
816 | * This is sucky but right now I can't find a good way to | ||
817 | * be sure its safe to free the buffer. We wait 5-6 fields | ||
818 | * which is more than sufficient to be sure. | ||
819 | */ | ||
820 | msleep(100); /* Wait 1/10th of a second */ | ||
821 | |||
822 | /* free the allocated framebuffer */ | ||
823 | bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE); | ||
824 | ztv->fbuffer = 0; | ||
825 | kfree(ztv->overinfo.overlay); | ||
826 | ztv->overinfo.overlay = 0; | ||
827 | |||
828 | } | ||
829 | |||
830 | /* | ||
831 | * This read function could be used reentrant in a SMP situation. | ||
832 | * | ||
833 | * This is made possible by the spinlock which is kept till we | ||
834 | * found and marked a buffer for our own use. The lock must | ||
835 | * be released as soon as possible to prevent lock contention. | ||
836 | */ | ||
837 | static | ||
838 | long zoran_read(struct video_device* dev, char* buf, unsigned long count, int nonblock) | ||
839 | { | ||
840 | struct zoran *ztv = (struct zoran*)dev; | ||
841 | unsigned long max; | ||
842 | struct vidinfo* unused = 0; | ||
843 | struct vidinfo* done = 0; | ||
844 | |||
845 | DEBUG(printk(CARD_DEBUG "zoran_read(%p,%ld,%d)\n",CARD,buf,count,nonblock)); | ||
846 | |||
847 | /* find ourself a free or completed buffer */ | ||
848 | for (;;) { | ||
849 | struct vidinfo* item; | ||
850 | |||
851 | write_lock_irq(&ztv->lock); | ||
852 | for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) | ||
853 | { | ||
854 | if (!unused && item->status == FBUFFER_FREE) | ||
855 | unused = item; | ||
856 | if (!done && item->status == FBUFFER_DONE) | ||
857 | done = item; | ||
858 | } | ||
859 | if (done || unused) | ||
860 | break; | ||
861 | |||
862 | /* no more free buffers, wait for them. */ | ||
863 | write_unlock_irq(&ztv->lock); | ||
864 | if (nonblock) | ||
865 | return -EWOULDBLOCK; | ||
866 | interruptible_sleep_on(&ztv->grabq); | ||
867 | if (signal_pending(current)) | ||
868 | return -EINTR; | ||
869 | } | ||
870 | |||
871 | /* Do we have 'ready' data? */ | ||
872 | if (!done) { | ||
873 | /* no? than this will take a while... */ | ||
874 | if (nonblock) { | ||
875 | write_unlock_irq(&ztv->lock); | ||
876 | return -EWOULDBLOCK; | ||
877 | } | ||
878 | |||
879 | /* mark the unused buffer as wanted */ | ||
880 | unused->status = FBUFFER_BUSY; | ||
881 | unused->w = 320; | ||
882 | unused->h = 240; | ||
883 | unused->format = VIDEO_PALETTE_RGB24; | ||
884 | unused->bpp = palette2fmt[unused->format].bpp; | ||
885 | unused->bpl = unused->w * unused->bpp; | ||
886 | unused->next = 0; | ||
887 | { /* add to tail of queue */ | ||
888 | struct vidinfo* oldframe = ztv->workqueue; | ||
889 | if (!oldframe) ztv->workqueue = unused; | ||
890 | else { | ||
891 | while (oldframe->next) oldframe = oldframe->next; | ||
892 | oldframe->next = unused; | ||
893 | } | ||
894 | } | ||
895 | write_unlock_irq(&ztv->lock); | ||
896 | |||
897 | /* tell the state machine we want it filled /NOW/ */ | ||
898 | zoran_cap(ztv, 1); | ||
899 | |||
900 | /* wait till this buffer gets grabbed */ | ||
901 | wait_event_interruptible(ztv->grabq, | ||
902 | (unused->status != FBUFFER_BUSY)); | ||
903 | /* see if a signal did it */ | ||
904 | if (signal_pending(current)) | ||
905 | return -EINTR; | ||
906 | done = unused; | ||
907 | } | ||
908 | else | ||
909 | write_unlock_irq(&ztv->lock); | ||
910 | |||
911 | /* Yes! we got data! */ | ||
912 | max = done->bpl * done->h; | ||
913 | if (count > max) | ||
914 | count = max; | ||
915 | if (copy_to_user((void*)buf, done->memadr, count)) | ||
916 | count = -EFAULT; | ||
917 | |||
918 | /* keep the engine running */ | ||
919 | done->status = FBUFFER_FREE; | ||
920 | // zoran_cap(ztv,1); | ||
921 | |||
922 | /* tell listeners this buffer became free */ | ||
923 | wake_up_interruptible(&ztv->grabq); | ||
924 | |||
925 | /* goodbye */ | ||
926 | DEBUG(printk(CARD_DEBUG "zoran_read() returns %lu\n",CARD,count)); | ||
927 | return count; | ||
928 | } | ||
929 | |||
930 | static | ||
931 | long zoran_write(struct video_device* dev, const char* buf, unsigned long count, int nonblock) | ||
932 | { | ||
933 | struct zoran *ztv = (struct zoran *)dev; | ||
934 | UNUSED(ztv); UNUSED(dev); UNUSED(buf); UNUSED(count); UNUSED(nonblock); | ||
935 | DEBUG(printk(CARD_DEBUG "zoran_write\n",CARD)); | ||
936 | return -EINVAL; | ||
937 | } | ||
938 | |||
939 | static | ||
940 | unsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait) | ||
941 | { | ||
942 | struct zoran *ztv = (struct zoran *)dev; | ||
943 | struct vidinfo* item; | ||
944 | unsigned int mask = 0; | ||
945 | |||
946 | poll_wait(file, &ztv->grabq, wait); | ||
947 | |||
948 | for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) | ||
949 | if (item->status == FBUFFER_DONE) | ||
950 | { | ||
951 | mask |= (POLLIN | POLLRDNORM); | ||
952 | break; | ||
953 | } | ||
954 | |||
955 | DEBUG(printk(CARD_DEBUG "zoran_poll()=%x\n",CARD,mask)); | ||
956 | |||
957 | return mask; | ||
958 | } | ||
959 | |||
960 | /* append a new clipregion to the vector of video_clips */ | ||
961 | static | ||
962 | void new_clip(struct video_window* vw, struct video_clip* vcp, int x, int y, int w, int h) | ||
963 | { | ||
964 | vcp[vw->clipcount].x = x; | ||
965 | vcp[vw->clipcount].y = y; | ||
966 | vcp[vw->clipcount].width = w; | ||
967 | vcp[vw->clipcount].height = h; | ||
968 | vw->clipcount++; | ||
969 | } | ||
970 | |||
971 | static | ||
972 | int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg) | ||
973 | { | ||
974 | struct zoran* ztv = (struct zoran*)dev; | ||
975 | |||
976 | switch (cmd) { | ||
977 | case VIDIOCGCAP: | ||
978 | { | ||
979 | struct video_capability c; | ||
980 | DEBUG(printk(CARD_DEBUG "VIDIOCGCAP\n",CARD)); | ||
981 | |||
982 | strcpy(c.name,ztv->video_dev.name); | ||
983 | c.type = VID_TYPE_CAPTURE| | ||
984 | VID_TYPE_OVERLAY| | ||
985 | VID_TYPE_CLIPPING| | ||
986 | VID_TYPE_FRAMERAM| | ||
987 | VID_TYPE_SCALES; | ||
988 | if (ztv->have_tuner) | ||
989 | c.type |= VID_TYPE_TUNER; | ||
990 | if (pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) | ||
991 | c.type &= ~VID_TYPE_OVERLAY; | ||
992 | if (ztv->have_decoder) { | ||
993 | c.channels = ztv->card->video_inputs; | ||
994 | c.audios = ztv->card->audio_inputs; | ||
995 | } else | ||
996 | /* no decoder -> no channels */ | ||
997 | c.channels = c.audios = 0; | ||
998 | c.maxwidth = 768; | ||
999 | c.maxheight = 576; | ||
1000 | c.minwidth = 32; | ||
1001 | c.minheight = 32; | ||
1002 | if (copy_to_user(arg,&c,sizeof(c))) | ||
1003 | return -EFAULT; | ||
1004 | break; | ||
1005 | } | ||
1006 | |||
1007 | case VIDIOCGCHAN: | ||
1008 | { | ||
1009 | struct video_channel v; | ||
1010 | int mux; | ||
1011 | if (copy_from_user(&v, arg,sizeof(v))) | ||
1012 | return -EFAULT; | ||
1013 | DEBUG(printk(CARD_DEBUG "VIDIOCGCHAN(%d)\n",CARD,v.channel)); | ||
1014 | v.flags=VIDEO_VC_AUDIO | ||
1015 | #ifdef VIDEO_VC_NORM | ||
1016 | |VIDEO_VC_NORM | ||
1017 | #endif | ||
1018 | ; | ||
1019 | v.tuners=0; | ||
1020 | v.type=VIDEO_TYPE_CAMERA; | ||
1021 | #ifdef I_EXPECT_POSSIBLE_NORMS_IN_THE_API | ||
1022 | v.norm=VIDEO_MODE_PAL| | ||
1023 | VIDEO_MODE_NTSC| | ||
1024 | VIDEO_MODE_SECAM; | ||
1025 | #else | ||
1026 | v.norm=VIDEO_MODE_PAL; | ||
1027 | #endif | ||
1028 | /* too many inputs? no decoder -> no channels */ | ||
1029 | if (!ztv->have_decoder || v.channel < 0 || v.channel >= ztv->card->video_inputs) | ||
1030 | return -EINVAL; | ||
1031 | |||
1032 | /* now determine the name of the channel */ | ||
1033 | mux = ztv->card->video_mux[v.channel]; | ||
1034 | if (mux & IS_TUNER) { | ||
1035 | /* lets assume only one tuner, yes? */ | ||
1036 | strcpy(v.name,"Television"); | ||
1037 | v.type = VIDEO_TYPE_TV; | ||
1038 | if (ztv->have_tuner) { | ||
1039 | v.flags |= VIDEO_VC_TUNER; | ||
1040 | v.tuners = 1; | ||
1041 | } | ||
1042 | } | ||
1043 | else if (mux & IS_SVHS) | ||
1044 | sprintf(v.name,"S-Video-%d",v.channel); | ||
1045 | else | ||
1046 | sprintf(v.name,"CVBS-%d",v.channel); | ||
1047 | |||
1048 | if (copy_to_user(arg,&v,sizeof(v))) | ||
1049 | return -EFAULT; | ||
1050 | break; | ||
1051 | } | ||
1052 | case VIDIOCSCHAN: | ||
1053 | { /* set video channel */ | ||
1054 | struct video_channel v; | ||
1055 | if (copy_from_user(&v, arg,sizeof(v))) | ||
1056 | return -EFAULT; | ||
1057 | DEBUG(printk(CARD_DEBUG "VIDIOCSCHAN(%d,%d)\n",CARD,v.channel,v.norm)); | ||
1058 | |||
1059 | /* too many inputs? no decoder -> no channels */ | ||
1060 | if (!ztv->have_decoder || v.channel >= ztv->card->video_inputs || v.channel < 0) | ||
1061 | return -EINVAL; | ||
1062 | |||
1063 | if (v.norm != VIDEO_MODE_PAL && | ||
1064 | v.norm != VIDEO_MODE_NTSC && | ||
1065 | v.norm != VIDEO_MODE_SECAM && | ||
1066 | v.norm != VIDEO_MODE_AUTO) | ||
1067 | return -EOPNOTSUPP; | ||
1068 | |||
1069 | /* make it happen, nr1! */ | ||
1070 | return zoran_muxsel(ztv,v.channel,v.norm); | ||
1071 | } | ||
1072 | |||
1073 | case VIDIOCGTUNER: | ||
1074 | { | ||
1075 | struct video_tuner v; | ||
1076 | if (copy_from_user(&v, arg,sizeof(v))) | ||
1077 | return -EFAULT; | ||
1078 | DEBUG(printk(CARD_DEBUG "VIDIOCGTUNER(%d)\n",CARD,v.tuner)); | ||
1079 | |||
1080 | /* Only no or one tuner for now */ | ||
1081 | if (!ztv->have_tuner || v.tuner) | ||
1082 | return -EINVAL; | ||
1083 | |||
1084 | strcpy(v.name,"Television"); | ||
1085 | v.rangelow = 0; | ||
1086 | v.rangehigh = ~0; | ||
1087 | v.flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; | ||
1088 | v.mode = ztv->norm; | ||
1089 | v.signal = 0xFFFF; /* unknown */ | ||
1090 | |||
1091 | if (copy_to_user(arg,&v,sizeof(v))) | ||
1092 | return -EFAULT; | ||
1093 | break; | ||
1094 | } | ||
1095 | case VIDIOCSTUNER: | ||
1096 | { | ||
1097 | struct video_tuner v; | ||
1098 | if (copy_from_user(&v, arg, sizeof(v))) | ||
1099 | return -EFAULT; | ||
1100 | DEBUG(printk(CARD_DEBUG "VIDIOCSTUNER(%d,%d)\n",CARD,v.tuner,v.mode)); | ||
1101 | |||
1102 | /* Only no or one tuner for now */ | ||
1103 | if (!ztv->have_tuner || v.tuner) | ||
1104 | return -EINVAL; | ||
1105 | |||
1106 | /* and it only has certain valid modes */ | ||
1107 | if( v.mode != VIDEO_MODE_PAL && | ||
1108 | v.mode != VIDEO_MODE_NTSC && | ||
1109 | v.mode != VIDEO_MODE_SECAM) | ||
1110 | return -EOPNOTSUPP; | ||
1111 | |||
1112 | /* engage! */ | ||
1113 | return zoran_muxsel(ztv,v.tuner,v.mode); | ||
1114 | } | ||
1115 | |||
1116 | case VIDIOCGPICT: | ||
1117 | { | ||
1118 | struct video_picture p = ztv->picture; | ||
1119 | DEBUG(printk(CARD_DEBUG "VIDIOCGPICT\n",CARD)); | ||
1120 | p.depth = ztv->depth; | ||
1121 | switch (p.depth) { | ||
1122 | case 8: p.palette=VIDEO_PALETTE_YUV422; | ||
1123 | break; | ||
1124 | case 15: p.palette=VIDEO_PALETTE_RGB555; | ||
1125 | break; | ||
1126 | case 16: p.palette=VIDEO_PALETTE_RGB565; | ||
1127 | break; | ||
1128 | case 24: p.palette=VIDEO_PALETTE_RGB24; | ||
1129 | break; | ||
1130 | case 32: p.palette=VIDEO_PALETTE_RGB32; | ||
1131 | break; | ||
1132 | } | ||
1133 | if (copy_to_user(arg, &p, sizeof(p))) | ||
1134 | return -EFAULT; | ||
1135 | break; | ||
1136 | } | ||
1137 | case VIDIOCSPICT: | ||
1138 | { | ||
1139 | struct video_picture p; | ||
1140 | if (copy_from_user(&p, arg,sizeof(p))) | ||
1141 | return -EFAULT; | ||
1142 | DEBUG(printk(CARD_DEBUG "VIDIOCSPICT(%d,%d,%d,%d,%d,%d,%d)\n",CARD,p.brightness,p.hue,p.colour,p.contrast,p.whiteness,p.depth,p.palette)); | ||
1143 | |||
1144 | /* depth must match with framebuffer */ | ||
1145 | if (p.depth != ztv->depth) | ||
1146 | return -EINVAL; | ||
1147 | |||
1148 | /* check if palette matches this bpp */ | ||
1149 | if (p.palette>NRPALETTES || | ||
1150 | palette2fmt[p.palette].bpp != ztv->overinfo.bpp) | ||
1151 | return -EINVAL; | ||
1152 | |||
1153 | write_lock_irq(&ztv->lock); | ||
1154 | ztv->overinfo.format = p.palette; | ||
1155 | ztv->picture = p; | ||
1156 | write_unlock_irq(&ztv->lock); | ||
1157 | |||
1158 | /* tell the decoder */ | ||
1159 | i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &p); | ||
1160 | break; | ||
1161 | } | ||
1162 | |||
1163 | case VIDIOCGWIN: | ||
1164 | { | ||
1165 | struct video_window vw; | ||
1166 | DEBUG(printk(CARD_DEBUG "VIDIOCGWIN\n",CARD)); | ||
1167 | read_lock(&ztv->lock); | ||
1168 | vw.x = ztv->overinfo.x; | ||
1169 | vw.y = ztv->overinfo.y; | ||
1170 | vw.width = ztv->overinfo.w; | ||
1171 | vw.height = ztv->overinfo.h; | ||
1172 | vw.chromakey= 0; | ||
1173 | vw.flags = 0; | ||
1174 | if (ztv->vidInterlace) | ||
1175 | vw.flags|=VIDEO_WINDOW_INTERLACE; | ||
1176 | read_unlock(&ztv->lock); | ||
1177 | if (copy_to_user(arg,&vw,sizeof(vw))) | ||
1178 | return -EFAULT; | ||
1179 | break; | ||
1180 | } | ||
1181 | case VIDIOCSWIN: | ||
1182 | { | ||
1183 | struct video_window vw; | ||
1184 | struct video_clip *vcp; | ||
1185 | int on; | ||
1186 | if (copy_from_user(&vw,arg,sizeof(vw))) | ||
1187 | return -EFAULT; | ||
1188 | DEBUG(printk(CARD_DEBUG "VIDIOCSWIN(%d,%d,%d,%d,%x,%d)\n",CARD,vw.x,vw.y,vw.width,vw.height,vw.flags,vw.clipcount)); | ||
1189 | |||
1190 | if (vw.flags) | ||
1191 | return -EINVAL; | ||
1192 | |||
1193 | if (vw.clipcount <0 || vw.clipcount>256) | ||
1194 | return -EDOM; /* Too many! */ | ||
1195 | |||
1196 | /* | ||
1197 | * Do any clips. | ||
1198 | */ | ||
1199 | vcp = vmalloc(sizeof(struct video_clip)*(vw.clipcount+4)); | ||
1200 | if (vcp==NULL) | ||
1201 | return -ENOMEM; | ||
1202 | if (vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount)) { | ||
1203 | vfree(vcp); | ||
1204 | return -EFAULT; | ||
1205 | } | ||
1206 | |||
1207 | on = ztv->running; | ||
1208 | if (on) | ||
1209 | zoran_cap(ztv, 0); | ||
1210 | |||
1211 | /* | ||
1212 | * strange, it seems xawtv sometimes calls us with 0 | ||
1213 | * width and/or height. Ignore these values | ||
1214 | */ | ||
1215 | if (vw.x == 0) | ||
1216 | vw.x = ztv->overinfo.x; | ||
1217 | if (vw.y == 0) | ||
1218 | vw.y = ztv->overinfo.y; | ||
1219 | |||
1220 | /* by now we are committed to the new data... */ | ||
1221 | write_lock_irq(&ztv->lock); | ||
1222 | ztv->overinfo.x = vw.x; | ||
1223 | ztv->overinfo.y = vw.y; | ||
1224 | ztv->overinfo.w = vw.width; | ||
1225 | ztv->overinfo.h = vw.height; | ||
1226 | write_unlock_irq(&ztv->lock); | ||
1227 | |||
1228 | /* | ||
1229 | * Impose display clips | ||
1230 | */ | ||
1231 | if (vw.x+vw.width > ztv->swidth) | ||
1232 | new_clip(&vw, vcp, ztv->swidth-vw.x, 0, vw.width-1, vw.height-1); | ||
1233 | if (vw.y+vw.height > ztv->sheight) | ||
1234 | new_clip(&vw, vcp, 0, ztv->sheight-vw.y, vw.width-1, vw.height-1); | ||
1235 | |||
1236 | /* built the requested clipping zones */ | ||
1237 | zoran_set_geo(ztv, &ztv->overinfo); | ||
1238 | zoran_built_overlay(ztv, vw.clipcount, vcp); | ||
1239 | vfree(vcp); | ||
1240 | |||
1241 | /* if we were on, restart the video engine */ | ||
1242 | if (on) | ||
1243 | zoran_cap(ztv, 1); | ||
1244 | break; | ||
1245 | } | ||
1246 | |||
1247 | case VIDIOCCAPTURE: | ||
1248 | { | ||
1249 | int v; | ||
1250 | if (get_user(v, (int *)arg)) | ||
1251 | return -EFAULT; | ||
1252 | DEBUG(printk(CARD_DEBUG "VIDIOCCAPTURE(%d)\n",CARD,v)); | ||
1253 | |||
1254 | if (v==0) { | ||
1255 | clear_bit(STATE_OVERLAY, &ztv->state); | ||
1256 | zoran_cap(ztv, 1); | ||
1257 | } | ||
1258 | else { | ||
1259 | /* is VIDIOCSFBUF, VIDIOCSWIN done? */ | ||
1260 | if (ztv->overinfo.busadr==0 || ztv->overinfo.w==0 || ztv->overinfo.h==0) | ||
1261 | return -EINVAL; | ||
1262 | |||
1263 | set_bit(STATE_OVERLAY, &ztv->state); | ||
1264 | zoran_cap(ztv, 1); | ||
1265 | } | ||
1266 | break; | ||
1267 | } | ||
1268 | |||
1269 | case VIDIOCGFBUF: | ||
1270 | { | ||
1271 | struct video_buffer v; | ||
1272 | DEBUG(printk(CARD_DEBUG "VIDIOCGFBUF\n",CARD)); | ||
1273 | read_lock(&ztv->lock); | ||
1274 | v.base = (void *)ztv->overinfo.busadr; | ||
1275 | v.height = ztv->sheight; | ||
1276 | v.width = ztv->swidth; | ||
1277 | v.depth = ztv->depth; | ||
1278 | v.bytesperline = ztv->overinfo.bpl; | ||
1279 | read_unlock(&ztv->lock); | ||
1280 | if(copy_to_user(arg, &v,sizeof(v))) | ||
1281 | return -EFAULT; | ||
1282 | break; | ||
1283 | } | ||
1284 | case VIDIOCSFBUF: | ||
1285 | { | ||
1286 | struct video_buffer v; | ||
1287 | if(!capable(CAP_SYS_ADMIN)) | ||
1288 | return -EPERM; | ||
1289 | if (pcipci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) | ||
1290 | return -ENXIO; | ||
1291 | if (copy_from_user(&v, arg,sizeof(v))) | ||
1292 | return -EFAULT; | ||
1293 | DEBUG(printk(CARD_DEBUG "VIDIOCSFBUF(%p,%d,%d,%d,%d)\n",CARD,v.base, v.width,v.height,v.depth,v.bytesperline)); | ||
1294 | |||
1295 | if (v.depth!=15 && v.depth!=16 && v.depth!=24 && v.depth!=32) | ||
1296 | return -EINVAL; | ||
1297 | if (v.bytesperline<1) | ||
1298 | return -EINVAL; | ||
1299 | if (ztv->running) | ||
1300 | return -EBUSY; | ||
1301 | write_lock_irq(&ztv->lock); | ||
1302 | ztv->overinfo.busadr = (ulong)v.base; | ||
1303 | ztv->sheight = v.height; | ||
1304 | ztv->swidth = v.width; | ||
1305 | ztv->depth = v.depth; /* bits per pixel */ | ||
1306 | ztv->overinfo.bpp = ((v.depth+1)&0x38)/8;/* bytes per pixel */ | ||
1307 | ztv->overinfo.bpl = v.bytesperline; /* bytes per line */ | ||
1308 | write_unlock_irq(&ztv->lock); | ||
1309 | break; | ||
1310 | } | ||
1311 | |||
1312 | case VIDIOCKEY: | ||
1313 | { | ||
1314 | /* Will be handled higher up .. */ | ||
1315 | break; | ||
1316 | } | ||
1317 | |||
1318 | case VIDIOCSYNC: | ||
1319 | { | ||
1320 | int i; | ||
1321 | if (get_user(i, (int *) arg)) | ||
1322 | return -EFAULT; | ||
1323 | DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d)\n",CARD,i)); | ||
1324 | if (i<0 || i>ZORAN_MAX_FBUFFERS) | ||
1325 | return -EINVAL; | ||
1326 | switch (ztv->grabinfo[i].status) { | ||
1327 | case FBUFFER_FREE: | ||
1328 | return -EINVAL; | ||
1329 | case FBUFFER_BUSY: | ||
1330 | /* wait till this buffer gets grabbed */ | ||
1331 | wait_event_interruptible(ztv->grabq, | ||
1332 | (ztv->grabinfo[i].status != FBUFFER_BUSY)); | ||
1333 | /* see if a signal did it */ | ||
1334 | if (signal_pending(current)) | ||
1335 | return -EINTR; | ||
1336 | /* don't fall through; a DONE buffer is not UNUSED */ | ||
1337 | break; | ||
1338 | case FBUFFER_DONE: | ||
1339 | ztv->grabinfo[i].status = FBUFFER_FREE; | ||
1340 | /* tell ppl we have a spare buffer */ | ||
1341 | wake_up_interruptible(&ztv->grabq); | ||
1342 | break; | ||
1343 | } | ||
1344 | DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d) returns\n",CARD,i)); | ||
1345 | break; | ||
1346 | } | ||
1347 | |||
1348 | case VIDIOCMCAPTURE: | ||
1349 | { | ||
1350 | struct video_mmap vm; | ||
1351 | struct vidinfo* frame; | ||
1352 | if (copy_from_user(&vm,arg,sizeof(vm))) | ||
1353 | return -EFAULT; | ||
1354 | DEBUG(printk(CARD_DEBUG "VIDIOCMCAPTURE(%d,(%d,%d),%d)\n",CARD,vm.frame,vm.width,vm.height,vm.format)); | ||
1355 | if (vm.frame<0 || vm.frame>ZORAN_MAX_FBUFFERS || | ||
1356 | vm.width<32 || vm.width>768 || | ||
1357 | vm.height<32 || vm.height>576 || | ||
1358 | vm.format>NRPALETTES || | ||
1359 | palette2fmt[vm.format].mode == 0) | ||
1360 | return -EINVAL; | ||
1361 | |||
1362 | /* we are allowed to take over UNUSED and DONE buffers */ | ||
1363 | frame = &ztv->grabinfo[vm.frame]; | ||
1364 | if (frame->status == FBUFFER_BUSY) | ||
1365 | return -EBUSY; | ||
1366 | |||
1367 | /* setup the other parameters if they are given */ | ||
1368 | write_lock_irq(&ztv->lock); | ||
1369 | frame->w = vm.width; | ||
1370 | frame->h = vm.height; | ||
1371 | frame->format = vm.format; | ||
1372 | frame->bpp = palette2fmt[frame->format].bpp; | ||
1373 | frame->bpl = frame->w*frame->bpp; | ||
1374 | frame->status = FBUFFER_BUSY; | ||
1375 | frame->next = 0; | ||
1376 | { /* add to tail of queue */ | ||
1377 | struct vidinfo* oldframe = ztv->workqueue; | ||
1378 | if (!oldframe) ztv->workqueue = frame; | ||
1379 | else { | ||
1380 | while (oldframe->next) oldframe = oldframe->next; | ||
1381 | oldframe->next = frame; | ||
1382 | } | ||
1383 | } | ||
1384 | write_unlock_irq(&ztv->lock); | ||
1385 | zoran_cap(ztv, 1); | ||
1386 | break; | ||
1387 | } | ||
1388 | |||
1389 | case VIDIOCGMBUF: | ||
1390 | { | ||
1391 | struct video_mbuf mb; | ||
1392 | int i; | ||
1393 | DEBUG(printk(CARD_DEBUG "VIDIOCGMBUF\n",CARD)); | ||
1394 | mb.size = ZORAN_MAX_FBUFSIZE; | ||
1395 | mb.frames = ZORAN_MAX_FBUFFERS; | ||
1396 | for (i=0; i<ZORAN_MAX_FBUFFERS; i++) | ||
1397 | mb.offsets[i] = i*ZORAN_MAX_FBUFFER; | ||
1398 | if(copy_to_user(arg, &mb,sizeof(mb))) | ||
1399 | return -EFAULT; | ||
1400 | break; | ||
1401 | } | ||
1402 | |||
1403 | case VIDIOCGUNIT: | ||
1404 | { | ||
1405 | struct video_unit vu; | ||
1406 | DEBUG(printk(CARD_DEBUG "VIDIOCGUNIT\n",CARD)); | ||
1407 | vu.video = ztv->video_dev.minor; | ||
1408 | vu.vbi = ztv->vbi_dev.minor; | ||
1409 | vu.radio = VIDEO_NO_UNIT; | ||
1410 | vu.audio = VIDEO_NO_UNIT; | ||
1411 | vu.teletext = VIDEO_NO_UNIT; | ||
1412 | if(copy_to_user(arg, &vu,sizeof(vu))) | ||
1413 | return -EFAULT; | ||
1414 | break; | ||
1415 | } | ||
1416 | |||
1417 | case VIDIOCGFREQ: | ||
1418 | { | ||
1419 | unsigned long v = ztv->tuner_freq; | ||
1420 | if (copy_to_user(arg,&v,sizeof(v))) | ||
1421 | return -EFAULT; | ||
1422 | DEBUG(printk(CARD_DEBUG "VIDIOCGFREQ\n",CARD)); | ||
1423 | break; | ||
1424 | } | ||
1425 | case VIDIOCSFREQ: | ||
1426 | { | ||
1427 | unsigned long v; | ||
1428 | if (copy_from_user(&v, arg, sizeof(v))) | ||
1429 | return -EFAULT; | ||
1430 | DEBUG(printk(CARD_DEBUG "VIDIOCSFREQ\n",CARD)); | ||
1431 | |||
1432 | if (ztv->have_tuner) { | ||
1433 | int fixme = v; | ||
1434 | if (i2c_control_device(&(ztv->i2c), I2C_DRIVERID_TUNER, TUNER_SET_TVFREQ, &fixme) < 0) | ||
1435 | return -EAGAIN; | ||
1436 | } | ||
1437 | ztv->tuner_freq = v; | ||
1438 | break; | ||
1439 | } | ||
1440 | |||
1441 | /* Why isn't this in the API? | ||
1442 | * And why doesn't it take a buffer number? | ||
1443 | case BTTV_FIELDNR: | ||
1444 | { | ||
1445 | unsigned long v = ztv->lastfieldnr; | ||
1446 | if (copy_to_user(arg,&v,sizeof(v))) | ||
1447 | return -EFAULT; | ||
1448 | DEBUG(printk(CARD_DEBUG "BTTV_FIELDNR\n",CARD)); | ||
1449 | break; | ||
1450 | } | ||
1451 | */ | ||
1452 | |||
1453 | default: | ||
1454 | return -ENOIOCTLCMD; | ||
1455 | } | ||
1456 | return 0; | ||
1457 | } | ||
1458 | |||
1459 | static | ||
1460 | int zoran_mmap(struct vm_area_struct *vma, struct video_device* dev, const char* adr, unsigned long size) | ||
1461 | { | ||
1462 | struct zoran* ztv = (struct zoran*)dev; | ||
1463 | unsigned long start = (unsigned long)adr; | ||
1464 | unsigned long pos; | ||
1465 | |||
1466 | DEBUG(printk(CARD_DEBUG "zoran_mmap(0x%p,%ld)\n",CARD,adr,size)); | ||
1467 | |||
1468 | /* sanity checks */ | ||
1469 | if (size > ZORAN_MAX_FBUFSIZE || !ztv->fbuffer) | ||
1470 | return -EINVAL; | ||
1471 | |||
1472 | /* start mapping the whole shabang to user memory */ | ||
1473 | pos = (unsigned long)ztv->fbuffer; | ||
1474 | while (size>0) { | ||
1475 | unsigned long pfn = virt_to_phys((void*)pos) >> PAGE_SHIFT; | ||
1476 | if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) | ||
1477 | return -EAGAIN; | ||
1478 | start += PAGE_SIZE; | ||
1479 | pos += PAGE_SIZE; | ||
1480 | size -= PAGE_SIZE; | ||
1481 | } | ||
1482 | return 0; | ||
1483 | } | ||
1484 | |||
1485 | static struct video_device zr36120_template= | ||
1486 | { | ||
1487 | .owner = THIS_MODULE, | ||
1488 | .name = "UNSET", | ||
1489 | .type = VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY, | ||
1490 | .hardware = VID_HARDWARE_ZR36120, | ||
1491 | .open = zoran_open, | ||
1492 | .close = zoran_close, | ||
1493 | .read = zoran_read, | ||
1494 | .write = zoran_write, | ||
1495 | .poll = zoran_poll, | ||
1496 | .ioctl = zoran_ioctl, | ||
1497 | .compat_ioctl = v4l_compat_ioctl32, | ||
1498 | .mmap = zoran_mmap, | ||
1499 | .minor = -1, | ||
1500 | }; | ||
1501 | |||
1502 | static | ||
1503 | int vbi_open(struct video_device *dev, int flags) | ||
1504 | { | ||
1505 | struct zoran *ztv = dev->priv; | ||
1506 | struct vidinfo* item; | ||
1507 | |||
1508 | DEBUG(printk(CARD_DEBUG "vbi_open(dev,%d)\n",CARD,flags)); | ||
1509 | |||
1510 | /* | ||
1511 | * During VBI device open, we continiously grab VBI-like | ||
1512 | * data in the vbi buffer when we have nothing to do. | ||
1513 | * Only when there is an explicit request for VBI data | ||
1514 | * (read call) we /force/ a read. | ||
1515 | */ | ||
1516 | |||
1517 | /* allocate buffers */ | ||
1518 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) | ||
1519 | { | ||
1520 | item->status = FBUFFER_FREE; | ||
1521 | |||
1522 | /* alloc */ | ||
1523 | if (!item->memadr) { | ||
1524 | item->memadr = bmalloc(ZORAN_VBI_BUFSIZE); | ||
1525 | if (!item->memadr) { | ||
1526 | /* could not get a buffer, bail out */ | ||
1527 | while (item != ztv->readinfo) { | ||
1528 | item--; | ||
1529 | bfree(item->memadr, ZORAN_VBI_BUFSIZE); | ||
1530 | item->memadr = 0; | ||
1531 | item->busadr = 0; | ||
1532 | } | ||
1533 | return -ENOBUFS; | ||
1534 | } | ||
1535 | } | ||
1536 | |||
1537 | /* determine the DMAable address */ | ||
1538 | item->busadr = virt_to_bus(item->memadr); | ||
1539 | } | ||
1540 | |||
1541 | /* do the common part of all open's */ | ||
1542 | zoran_common_open(ztv, flags); | ||
1543 | |||
1544 | set_bit(STATE_VBI, &ztv->state); | ||
1545 | /* start read-ahead */ | ||
1546 | zoran_cap(ztv, 1); | ||
1547 | |||
1548 | return 0; | ||
1549 | } | ||
1550 | |||
1551 | static | ||
1552 | void vbi_close(struct video_device *dev) | ||
1553 | { | ||
1554 | struct zoran *ztv = dev->priv; | ||
1555 | struct vidinfo* item; | ||
1556 | |||
1557 | DEBUG(printk(CARD_DEBUG "vbi_close(dev)\n",CARD)); | ||
1558 | |||
1559 | /* driver specific closure */ | ||
1560 | clear_bit(STATE_VBI, &ztv->state); | ||
1561 | |||
1562 | zoran_common_close(ztv); | ||
1563 | |||
1564 | /* | ||
1565 | * This is sucky but right now I can't find a good way to | ||
1566 | * be sure its safe to free the buffer. We wait 5-6 fields | ||
1567 | * which is more than sufficient to be sure. | ||
1568 | */ | ||
1569 | msleep(100); /* Wait 1/10th of a second */ | ||
1570 | |||
1571 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) | ||
1572 | { | ||
1573 | if (item->memadr) | ||
1574 | bfree(item->memadr, ZORAN_VBI_BUFSIZE); | ||
1575 | item->memadr = 0; | ||
1576 | } | ||
1577 | |||
1578 | } | ||
1579 | |||
1580 | /* | ||
1581 | * This read function could be used reentrant in a SMP situation. | ||
1582 | * | ||
1583 | * This is made possible by the spinlock which is kept till we | ||
1584 | * found and marked a buffer for our own use. The lock must | ||
1585 | * be released as soon as possible to prevent lock contention. | ||
1586 | */ | ||
1587 | static | ||
1588 | long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonblock) | ||
1589 | { | ||
1590 | struct zoran *ztv = dev->priv; | ||
1591 | unsigned long max; | ||
1592 | struct vidinfo* unused = 0; | ||
1593 | struct vidinfo* done = 0; | ||
1594 | |||
1595 | DEBUG(printk(CARD_DEBUG "vbi_read(0x%p,%ld,%d)\n",CARD,buf,count,nonblock)); | ||
1596 | |||
1597 | /* find ourself a free or completed buffer */ | ||
1598 | for (;;) { | ||
1599 | struct vidinfo* item; | ||
1600 | |||
1601 | write_lock_irq(&ztv->lock); | ||
1602 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) { | ||
1603 | if (!unused && item->status == FBUFFER_FREE) | ||
1604 | unused = item; | ||
1605 | if (!done && item->status == FBUFFER_DONE) | ||
1606 | done = item; | ||
1607 | } | ||
1608 | if (done || unused) | ||
1609 | break; | ||
1610 | |||
1611 | /* no more free buffers, wait for them. */ | ||
1612 | write_unlock_irq(&ztv->lock); | ||
1613 | if (nonblock) | ||
1614 | return -EWOULDBLOCK; | ||
1615 | interruptible_sleep_on(&ztv->vbiq); | ||
1616 | if (signal_pending(current)) | ||
1617 | return -EINTR; | ||
1618 | } | ||
1619 | |||
1620 | /* Do we have 'ready' data? */ | ||
1621 | if (!done) { | ||
1622 | /* no? than this will take a while... */ | ||
1623 | if (nonblock) { | ||
1624 | write_unlock_irq(&ztv->lock); | ||
1625 | return -EWOULDBLOCK; | ||
1626 | } | ||
1627 | |||
1628 | /* mark the unused buffer as wanted */ | ||
1629 | unused->status = FBUFFER_BUSY; | ||
1630 | unused->next = 0; | ||
1631 | { /* add to tail of queue */ | ||
1632 | struct vidinfo* oldframe = ztv->workqueue; | ||
1633 | if (!oldframe) ztv->workqueue = unused; | ||
1634 | else { | ||
1635 | while (oldframe->next) oldframe = oldframe->next; | ||
1636 | oldframe->next = unused; | ||
1637 | } | ||
1638 | } | ||
1639 | write_unlock_irq(&ztv->lock); | ||
1640 | |||
1641 | /* tell the state machine we want it filled /NOW/ */ | ||
1642 | zoran_cap(ztv, 1); | ||
1643 | |||
1644 | /* wait till this buffer gets grabbed */ | ||
1645 | wait_event_interruptible(ztv->vbiq, | ||
1646 | (unused->status != FBUFFER_BUSY)); | ||
1647 | /* see if a signal did it */ | ||
1648 | if (signal_pending(current)) | ||
1649 | return -EINTR; | ||
1650 | done = unused; | ||
1651 | } | ||
1652 | else | ||
1653 | write_unlock_irq(&ztv->lock); | ||
1654 | |||
1655 | /* Yes! we got data! */ | ||
1656 | max = done->bpl * -done->h; | ||
1657 | if (count > max) | ||
1658 | count = max; | ||
1659 | |||
1660 | /* check if the user gave us enough room to write the data */ | ||
1661 | if (!access_ok(VERIFY_WRITE, buf, count)) { | ||
1662 | count = -EFAULT; | ||
1663 | goto out; | ||
1664 | } | ||
1665 | |||
1666 | /* | ||
1667 | * Now transform/strip the data from YUV to Y-only | ||
1668 | * NB. Assume the Y is in the LSB of the YUV data. | ||
1669 | */ | ||
1670 | { | ||
1671 | unsigned char* optr = buf; | ||
1672 | unsigned char* eptr = buf+count; | ||
1673 | |||
1674 | /* are we beeing accessed from an old driver? */ | ||
1675 | if (count == 2*19*2048) { | ||
1676 | /* | ||
1677 | * Extreme HACK, old VBI programs expect 2048 points | ||
1678 | * of data, and we only got 864 orso. Double each | ||
1679 | * datapoint and clear the rest of the line. | ||
1680 | * This way we have appear to have a | ||
1681 | * sample_frequency of 29.5 Mc. | ||
1682 | */ | ||
1683 | int x,y; | ||
1684 | unsigned char* iptr = done->memadr+1; | ||
1685 | for (y=done->h; optr<eptr && y<0; y++) | ||
1686 | { | ||
1687 | /* copy to doubled data to userland */ | ||
1688 | for (x=0; optr+1<eptr && x<-done->w; x++) | ||
1689 | { | ||
1690 | unsigned char a = iptr[x*2]; | ||
1691 | __put_user(a, optr++); | ||
1692 | __put_user(a, optr++); | ||
1693 | } | ||
1694 | /* and clear the rest of the line */ | ||
1695 | for (x*=2; optr<eptr && x<done->bpl; x++) | ||
1696 | __put_user(0, optr++); | ||
1697 | /* next line */ | ||
1698 | iptr += done->bpl; | ||
1699 | } | ||
1700 | } | ||
1701 | else { | ||
1702 | /* | ||
1703 | * Other (probably newer) programs asked | ||
1704 | * us what geometry we are using, and are | ||
1705 | * reading the correct size. | ||
1706 | */ | ||
1707 | int x,y; | ||
1708 | unsigned char* iptr = done->memadr+1; | ||
1709 | for (y=done->h; optr<eptr && y<0; y++) | ||
1710 | { | ||
1711 | /* copy to doubled data to userland */ | ||
1712 | for (x=0; optr<eptr && x<-done->w; x++) | ||
1713 | __put_user(iptr[x*2], optr++); | ||
1714 | /* and clear the rest of the line */ | ||
1715 | for (;optr<eptr && x<done->bpl; x++) | ||
1716 | __put_user(0, optr++); | ||
1717 | /* next line */ | ||
1718 | iptr += done->bpl; | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | /* API compliance: | ||
1723 | * place the framenumber (half fieldnr) in the last long | ||
1724 | */ | ||
1725 | __put_user(done->fieldnr/2, ((ulong*)eptr)[-1]); | ||
1726 | } | ||
1727 | |||
1728 | /* keep the engine running */ | ||
1729 | done->status = FBUFFER_FREE; | ||
1730 | zoran_cap(ztv, 1); | ||
1731 | |||
1732 | /* tell listeners this buffer just became free */ | ||
1733 | wake_up_interruptible(&ztv->vbiq); | ||
1734 | |||
1735 | /* goodbye */ | ||
1736 | out: | ||
1737 | DEBUG(printk(CARD_DEBUG "vbi_read() returns %lu\n",CARD,count)); | ||
1738 | return count; | ||
1739 | } | ||
1740 | |||
1741 | static | ||
1742 | unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait) | ||
1743 | { | ||
1744 | struct zoran *ztv = dev->priv; | ||
1745 | struct vidinfo* item; | ||
1746 | unsigned int mask = 0; | ||
1747 | |||
1748 | poll_wait(file, &ztv->vbiq, wait); | ||
1749 | |||
1750 | for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) | ||
1751 | if (item->status == FBUFFER_DONE) | ||
1752 | { | ||
1753 | mask |= (POLLIN | POLLRDNORM); | ||
1754 | break; | ||
1755 | } | ||
1756 | |||
1757 | DEBUG(printk(CARD_DEBUG "vbi_poll()=%x\n",CARD,mask)); | ||
1758 | |||
1759 | return mask; | ||
1760 | } | ||
1761 | |||
1762 | static | ||
1763 | int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) | ||
1764 | { | ||
1765 | struct zoran* ztv = dev->priv; | ||
1766 | |||
1767 | switch (cmd) { | ||
1768 | case VIDIOCGVBIFMT: | ||
1769 | { | ||
1770 | struct vbi_format f; | ||
1771 | DEBUG(printk(CARD_DEBUG "VIDIOCGVBIINFO\n",CARD)); | ||
1772 | f.sampling_rate = 14750000UL; | ||
1773 | f.samples_per_line = -ztv->readinfo[0].w; | ||
1774 | f.sample_format = VIDEO_PALETTE_RAW; | ||
1775 | f.start[0] = f.start[1] = ztv->readinfo[0].y; | ||
1776 | f.start[1] += 312; | ||
1777 | f.count[0] = f.count[1] = -ztv->readinfo[0].h; | ||
1778 | f.flags = VBI_INTERLACED; | ||
1779 | if (copy_to_user(arg,&f,sizeof(f))) | ||
1780 | return -EFAULT; | ||
1781 | break; | ||
1782 | } | ||
1783 | case VIDIOCSVBIFMT: | ||
1784 | { | ||
1785 | struct vbi_format f; | ||
1786 | int i; | ||
1787 | if (copy_from_user(&f, arg,sizeof(f))) | ||
1788 | return -EFAULT; | ||
1789 | DEBUG(printk(CARD_DEBUG "VIDIOCSVBIINFO(%d,%d,%d,%d,%d,%d,%d,%x)\n",CARD,f.sampling_rate,f.samples_per_line,f.sample_format,f.start[0],f.start[1],f.count[0],f.count[1],f.flags)); | ||
1790 | |||
1791 | /* lots of parameters are fixed... (PAL) */ | ||
1792 | if (f.sampling_rate != 14750000UL || | ||
1793 | f.samples_per_line > 864 || | ||
1794 | f.sample_format != VIDEO_PALETTE_RAW || | ||
1795 | f.start[0] < 0 || | ||
1796 | f.start[0] != f.start[1]-312 || | ||
1797 | f.count[0] != f.count[1] || | ||
1798 | f.start[0]+f.count[0] >= 288 || | ||
1799 | f.flags != VBI_INTERLACED) | ||
1800 | return -EINVAL; | ||
1801 | |||
1802 | write_lock_irq(&ztv->lock); | ||
1803 | ztv->readinfo[0].y = f.start[0]; | ||
1804 | ztv->readinfo[0].w = -f.samples_per_line; | ||
1805 | ztv->readinfo[0].h = -f.count[0]; | ||
1806 | ztv->readinfo[0].bpl = f.samples_per_line*ztv->readinfo[0].bpp; | ||
1807 | for (i=1; i<ZORAN_VBI_BUFFERS; i++) | ||
1808 | ztv->readinfo[i] = ztv->readinfo[i]; | ||
1809 | write_unlock_irq(&ztv->lock); | ||
1810 | break; | ||
1811 | } | ||
1812 | default: | ||
1813 | return -ENOIOCTLCMD; | ||
1814 | } | ||
1815 | return 0; | ||
1816 | } | ||
1817 | |||
1818 | static struct video_device vbi_template= | ||
1819 | { | ||
1820 | .owner = THIS_MODULE, | ||
1821 | .name = "UNSET", | ||
1822 | .type = VID_TYPE_CAPTURE|VID_TYPE_TELETEXT, | ||
1823 | .hardware = VID_HARDWARE_ZR36120, | ||
1824 | .open = vbi_open, | ||
1825 | .close = vbi_close, | ||
1826 | .read = vbi_read, | ||
1827 | .write = zoran_write, | ||
1828 | .poll = vbi_poll, | ||
1829 | .ioctl = vbi_ioctl, | ||
1830 | .minor = -1, | ||
1831 | }; | ||
1832 | |||
1833 | /* | ||
1834 | * Scan for a Zoran chip, request the irq and map the io memory | ||
1835 | */ | ||
1836 | static | ||
1837 | int __init find_zoran(void) | ||
1838 | { | ||
1839 | int result; | ||
1840 | struct zoran *ztv; | ||
1841 | struct pci_dev *dev = NULL; | ||
1842 | unsigned char revision; | ||
1843 | int zoran_num = 0; | ||
1844 | |||
1845 | while ((dev = pci_get_device(PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, dev))) | ||
1846 | { | ||
1847 | /* Ok, a ZR36120/ZR36125 found! */ | ||
1848 | ztv = &zorans[zoran_num]; | ||
1849 | ztv->dev = dev; | ||
1850 | |||
1851 | if (pci_enable_device(dev)) | ||
1852 | continue; | ||
1853 | |||
1854 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &revision); | ||
1855 | printk(KERN_INFO "zoran: Zoran %x (rev %d) ", | ||
1856 | dev->device, revision); | ||
1857 | printk("bus: %d, devfn: %d, irq: %d, ", | ||
1858 | dev->bus->number, dev->devfn, dev->irq); | ||
1859 | printk("memory: 0x%08lx.\n", ztv->zoran_adr); | ||
1860 | |||
1861 | ztv->zoran_mem = ioremap(ztv->zoran_adr, 0x1000); | ||
1862 | DEBUG(printk(KERN_DEBUG "zoran: mapped-memory at 0x%p\n",ztv->zoran_mem)); | ||
1863 | |||
1864 | result = request_irq(dev->irq, zoran_irq, | ||
1865 | IRQF_SHARED|IRQF_DISABLED,"zoran", ztv); | ||
1866 | if (result==-EINVAL) | ||
1867 | { | ||
1868 | iounmap(ztv->zoran_mem); | ||
1869 | printk(KERN_ERR "zoran: Bad irq number or handler\n"); | ||
1870 | continue; | ||
1871 | } | ||
1872 | if (result==-EBUSY) | ||
1873 | printk(KERN_ERR "zoran: IRQ %d busy, change your PnP config in BIOS\n",dev->irq); | ||
1874 | if (result < 0) { | ||
1875 | iounmap(ztv->zoran_mem); | ||
1876 | continue; | ||
1877 | } | ||
1878 | /* Enable bus-mastering */ | ||
1879 | pci_set_master(dev); | ||
1880 | /* Keep a reference */ | ||
1881 | pci_dev_get(dev); | ||
1882 | zoran_num++; | ||
1883 | } | ||
1884 | if(zoran_num) | ||
1885 | printk(KERN_INFO "zoran: %d Zoran card(s) found.\n",zoran_num); | ||
1886 | return zoran_num; | ||
1887 | } | ||
1888 | |||
1889 | static | ||
1890 | int __init init_zoran(int card) | ||
1891 | { | ||
1892 | struct zoran *ztv = &zorans[card]; | ||
1893 | int i; | ||
1894 | |||
1895 | /* if the given cardtype valid? */ | ||
1896 | if (cardtype[card]>=NRTVCARDS) { | ||
1897 | printk(KERN_INFO "invalid cardtype(%d) detected\n",cardtype[card]); | ||
1898 | return -1; | ||
1899 | } | ||
1900 | |||
1901 | /* reset the zoran */ | ||
1902 | zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI); | ||
1903 | udelay(10); | ||
1904 | zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI); | ||
1905 | udelay(10); | ||
1906 | |||
1907 | /* zoran chip specific details */ | ||
1908 | ztv->card = tvcards+cardtype[card]; /* point to the selected card */ | ||
1909 | ztv->norm = 0; /* PAL */ | ||
1910 | ztv->tuner_freq = 0; | ||
1911 | |||
1912 | /* videocard details */ | ||
1913 | ztv->swidth = 800; | ||
1914 | ztv->sheight = 600; | ||
1915 | ztv->depth = 16; | ||
1916 | |||
1917 | /* State details */ | ||
1918 | ztv->fbuffer = 0; | ||
1919 | ztv->overinfo.kindof = FBUFFER_OVERLAY; | ||
1920 | ztv->overinfo.status = FBUFFER_FREE; | ||
1921 | ztv->overinfo.x = 0; | ||
1922 | ztv->overinfo.y = 0; | ||
1923 | ztv->overinfo.w = 768; /* 640 */ | ||
1924 | ztv->overinfo.h = 576; /* 480 */ | ||
1925 | ztv->overinfo.format = VIDEO_PALETTE_RGB565; | ||
1926 | ztv->overinfo.bpp = palette2fmt[ztv->overinfo.format].bpp; | ||
1927 | ztv->overinfo.bpl = ztv->overinfo.bpp*ztv->swidth; | ||
1928 | ztv->overinfo.busadr = 0; | ||
1929 | ztv->overinfo.memadr = 0; | ||
1930 | ztv->overinfo.overlay = 0; | ||
1931 | for (i=0; i<ZORAN_MAX_FBUFFERS; i++) { | ||
1932 | ztv->grabinfo[i] = ztv->overinfo; | ||
1933 | ztv->grabinfo[i].kindof = FBUFFER_GRAB; | ||
1934 | } | ||
1935 | init_waitqueue_head(&ztv->grabq); | ||
1936 | |||
1937 | /* VBI details */ | ||
1938 | ztv->readinfo[0] = ztv->overinfo; | ||
1939 | ztv->readinfo[0].kindof = FBUFFER_VBI; | ||
1940 | ztv->readinfo[0].w = -864; | ||
1941 | ztv->readinfo[0].h = -38; | ||
1942 | ztv->readinfo[0].format = VIDEO_PALETTE_YUV422; | ||
1943 | ztv->readinfo[0].bpp = palette2fmt[ztv->readinfo[0].format].bpp; | ||
1944 | ztv->readinfo[0].bpl = 1024*ztv->readinfo[0].bpp; | ||
1945 | for (i=1; i<ZORAN_VBI_BUFFERS; i++) | ||
1946 | ztv->readinfo[i] = ztv->readinfo[0]; | ||
1947 | init_waitqueue_head(&ztv->vbiq); | ||
1948 | |||
1949 | /* maintenance data */ | ||
1950 | ztv->have_decoder = 0; | ||
1951 | ztv->have_tuner = 0; | ||
1952 | ztv->tuner_type = 0; | ||
1953 | ztv->running = 0; | ||
1954 | ztv->users = 0; | ||
1955 | rwlock_init(&ztv->lock); | ||
1956 | ztv->workqueue = 0; | ||
1957 | ztv->fieldnr = 0; | ||
1958 | ztv->lastfieldnr = 0; | ||
1959 | |||
1960 | if (triton1) | ||
1961 | zrand(~ZORAN_VDC_TRICOM, ZORAN_VDC); | ||
1962 | |||
1963 | /* external FL determines TOP frame */ | ||
1964 | zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC); | ||
1965 | |||
1966 | /* set HSpol */ | ||
1967 | if (ztv->card->hsync_pos) | ||
1968 | zrwrite(ZORAN_VFEH_HSPOL, ZORAN_VFEH); | ||
1969 | /* set VSpol */ | ||
1970 | if (ztv->card->vsync_pos) | ||
1971 | zrwrite(ZORAN_VFEV_VSPOL, ZORAN_VFEV); | ||
1972 | |||
1973 | /* Set the proper General Purpuse register bits */ | ||
1974 | /* implicit: no softreset, 0 waitstates */ | ||
1975 | zrwrite(ZORAN_PCI_SOFTRESET|(ztv->card->gpdir<<0),ZORAN_PCI); | ||
1976 | /* implicit: 3 duration and recovery PCI clocks on guest 0-3 */ | ||
1977 | zrwrite(ztv->card->gpval<<24,ZORAN_GUEST); | ||
1978 | |||
1979 | /* clear interrupt status */ | ||
1980 | zrwrite(~0, ZORAN_ISR); | ||
1981 | |||
1982 | /* | ||
1983 | * i2c template | ||
1984 | */ | ||
1985 | ztv->i2c = zoran_i2c_bus_template; | ||
1986 | sprintf(ztv->i2c.name,"zoran-%d",card); | ||
1987 | ztv->i2c.data = ztv; | ||
1988 | |||
1989 | /* | ||
1990 | * Now add the template and register the device unit | ||
1991 | */ | ||
1992 | ztv->video_dev = zr36120_template; | ||
1993 | strcpy(ztv->video_dev.name, ztv->i2c.name); | ||
1994 | ztv->video_dev.priv = ztv; | ||
1995 | if (video_register_device(&ztv->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) | ||
1996 | return -1; | ||
1997 | |||
1998 | ztv->vbi_dev = vbi_template; | ||
1999 | strcpy(ztv->vbi_dev.name, ztv->i2c.name); | ||
2000 | ztv->vbi_dev.priv = ztv; | ||
2001 | if (video_register_device(&ztv->vbi_dev, VFL_TYPE_VBI, vbi_nr) < 0) { | ||
2002 | video_unregister_device(&ztv->video_dev); | ||
2003 | return -1; | ||
2004 | } | ||
2005 | i2c_register_bus(&ztv->i2c); | ||
2006 | |||
2007 | /* set interrupt mask - the PIN enable will be set later */ | ||
2008 | zrwrite(ZORAN_ICR_GIRQ0|ZORAN_ICR_GIRQ1|ZORAN_ICR_CODE, ZORAN_ICR); | ||
2009 | |||
2010 | printk(KERN_INFO "%s: installed %s\n",ztv->i2c.name,ztv->card->name); | ||
2011 | return 0; | ||
2012 | } | ||
2013 | |||
2014 | static | ||
2015 | void release_zoran(int max) | ||
2016 | { | ||
2017 | struct zoran *ztv; | ||
2018 | int i; | ||
2019 | |||
2020 | for (i=0;i<max; i++) | ||
2021 | { | ||
2022 | ztv = &zorans[i]; | ||
2023 | |||
2024 | /* turn off all capturing, DMA and IRQs */ | ||
2025 | /* reset the zoran */ | ||
2026 | zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI); | ||
2027 | udelay(10); | ||
2028 | zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI); | ||
2029 | udelay(10); | ||
2030 | |||
2031 | /* first disable interrupts before unmapping the memory! */ | ||
2032 | zrwrite(0, ZORAN_ICR); | ||
2033 | zrwrite(0xffffffffUL,ZORAN_ISR); | ||
2034 | |||
2035 | /* free it */ | ||
2036 | free_irq(ztv->dev->irq,ztv); | ||
2037 | |||
2038 | /* unregister i2c_bus */ | ||
2039 | i2c_unregister_bus((&ztv->i2c)); | ||
2040 | |||
2041 | /* unmap and free memory */ | ||
2042 | if (ztv->zoran_mem) | ||
2043 | iounmap(ztv->zoran_mem); | ||
2044 | |||
2045 | /* Drop PCI device */ | ||
2046 | pci_dev_put(ztv->dev); | ||
2047 | |||
2048 | video_unregister_device(&ztv->video_dev); | ||
2049 | video_unregister_device(&ztv->vbi_dev); | ||
2050 | } | ||
2051 | } | ||
2052 | |||
2053 | void __exit zr36120_exit(void) | ||
2054 | { | ||
2055 | release_zoran(zoran_cards); | ||
2056 | } | ||
2057 | |||
2058 | int __init zr36120_init(void) | ||
2059 | { | ||
2060 | int card; | ||
2061 | |||
2062 | handle_chipset(); | ||
2063 | zoran_cards = find_zoran(); | ||
2064 | if (zoran_cards <= 0) | ||
2065 | return -EIO; | ||
2066 | |||
2067 | /* initialize Zorans */ | ||
2068 | for (card=0; card<zoran_cards; card++) { | ||
2069 | if (init_zoran(card) < 0) { | ||
2070 | /* only release the zorans we have registered */ | ||
2071 | release_zoran(card); | ||
2072 | return -EIO; | ||
2073 | } | ||
2074 | } | ||
2075 | return 0; | ||
2076 | } | ||
2077 | |||
2078 | module_init(zr36120_init); | ||
2079 | module_exit(zr36120_exit); | ||
diff --git a/drivers/media/video/zr36120.h b/drivers/media/video/zr36120.h deleted file mode 100644 index a71e485b0f98..000000000000 --- a/drivers/media/video/zr36120.h +++ /dev/null | |||
@@ -1,279 +0,0 @@ | |||
1 | /* | ||
2 | zr36120.h - Zoran 36120/36125 based framegrabbers | ||
3 | |||
4 | Copyright (C) 1998-1999 Pauline Middelink (middelin@polyware.nl) | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef _ZR36120_H | ||
22 | #define _ZR36120_H | ||
23 | |||
24 | #ifdef __KERNEL__ | ||
25 | |||
26 | #include <linux/types.h> | ||
27 | #include <linux/wait.h> | ||
28 | |||
29 | #include <linux/i2c-old.h> | ||
30 | #include <linux/videodev.h> | ||
31 | |||
32 | #include <asm/io.h> | ||
33 | |||
34 | /* | ||
35 | * Debug macro's, place an x behind the ) for actual debug-compilation | ||
36 | * E.g. #define DEBUG(x...) x | ||
37 | */ | ||
38 | #define DEBUG(x...) /* Debug driver */ | ||
39 | #define IDEBUG(x...) /* Debug interrupt handler */ | ||
40 | #define PDEBUG 0 /* Debug PCI writes */ | ||
41 | |||
42 | /* defined in zr36120_i2c */ | ||
43 | extern struct i2c_bus zoran_i2c_bus_template; | ||
44 | |||
45 | #define ZORAN_MAX_FBUFFERS 2 | ||
46 | #define ZORAN_MAX_FBUFFER (768*576*2) | ||
47 | #define ZORAN_MAX_FBUFSIZE (ZORAN_MAX_FBUFFERS*ZORAN_MAX_FBUFFER) | ||
48 | |||
49 | #define ZORAN_VBI_BUFFERS 2 | ||
50 | #define ZORAN_VBI_BUFSIZE (22*1024*2) | ||
51 | |||
52 | struct tvcard { | ||
53 | char* name; /* name of the cardtype */ | ||
54 | int video_inputs; /* number of channels defined in video_mux */ | ||
55 | int audio_inputs; /* number of channels defined in audio_mux */ | ||
56 | __u32 swapi2c:1, /* need to swap i2c wires SDA/SCL? */ | ||
57 | usegirq1:1, /* VSYNC at GIRQ1 instead of GIRQ0? */ | ||
58 | vsync_pos:1, /* positive VSYNC signal? */ | ||
59 | hsync_pos:1, /* positive HSYNC signal? */ | ||
60 | gpdir:8, /* General Purpose Direction register */ | ||
61 | gpval:8; /* General Purpose Value register */ | ||
62 | int video_mux[6]; /* mapping channel number to physical input */ | ||
63 | #define IS_TUNER 0x80 | ||
64 | #define IS_SVHS 0x40 | ||
65 | #define CHANNEL_MASK 0x3F | ||
66 | int audio_mux[6]; /* mapping channel number to physical input */ | ||
67 | }; | ||
68 | #define TUNER(x) ((x)|IS_TUNER) | ||
69 | #define SVHS(x) ((x)|IS_SVHS) | ||
70 | |||
71 | struct vidinfo { | ||
72 | struct vidinfo* next; /* next active buffer */ | ||
73 | uint kindof; | ||
74 | #define FBUFFER_OVERLAY 0 | ||
75 | #define FBUFFER_GRAB 1 | ||
76 | #define FBUFFER_VBI 2 | ||
77 | uint status; | ||
78 | #define FBUFFER_FREE 0 | ||
79 | #define FBUFFER_BUSY 1 | ||
80 | #define FBUFFER_DONE 2 | ||
81 | ulong fieldnr; /* # of field, not framer! */ | ||
82 | uint x,y; | ||
83 | int w,h; /* w,h can be negative! */ | ||
84 | uint format; /* index in palette2fmt[] */ | ||
85 | uint bpp; /* lookup from palette2fmt[] */ | ||
86 | uint bpl; /* calc: width * bpp */ | ||
87 | ulong busadr; /* bus addr for DMA engine */ | ||
88 | char* memadr; /* kernel addr for making copies */ | ||
89 | ulong* overlay; /* kernel addr of overlay mask */ | ||
90 | }; | ||
91 | |||
92 | struct zoran | ||
93 | { | ||
94 | struct video_device video_dev; | ||
95 | #define CARD_DEBUG KERN_DEBUG "%s(%lu): " | ||
96 | #define CARD_INFO KERN_INFO "%s(%lu): " | ||
97 | #define CARD_ERR KERN_ERR "%s(%lu): " | ||
98 | #define CARD ztv->video_dev.name,ztv->fieldnr | ||
99 | |||
100 | /* zoran chip specific details */ | ||
101 | struct i2c_bus i2c; /* i2c registration data */ | ||
102 | struct pci_dev* dev; /* ptr to PCI device */ | ||
103 | ulong zoran_adr; /* bus address of IO memory */ | ||
104 | char* zoran_mem; /* kernel address of IO memory */ | ||
105 | struct tvcard* card; /* the cardtype */ | ||
106 | uint norm; /* 0=PAL, 1=NTSC, 2=SECAM */ | ||
107 | uint tuner_freq; /* Current freq in kHz */ | ||
108 | struct video_picture picture; /* Current picture params */ | ||
109 | |||
110 | /* videocard details */ | ||
111 | uint swidth; /* screen width */ | ||
112 | uint sheight; /* screen height */ | ||
113 | uint depth; /* depth in bits */ | ||
114 | |||
115 | /* State details */ | ||
116 | char* fbuffer; /* framebuffers for mmap */ | ||
117 | struct vidinfo overinfo; /* overlay data */ | ||
118 | struct vidinfo grabinfo[ZORAN_MAX_FBUFFERS]; /* grabbing data*/ | ||
119 | wait_queue_head_t grabq; /* grabbers queue */ | ||
120 | |||
121 | /* VBI details */ | ||
122 | struct video_device vbi_dev; | ||
123 | struct vidinfo readinfo[2]; /* VBI data - flip buffers */ | ||
124 | wait_queue_head_t vbiq; /* vbi queue */ | ||
125 | |||
126 | /* maintenance data */ | ||
127 | int have_decoder; /* did we detect a mux? */ | ||
128 | int have_tuner; /* did we detect a tuner? */ | ||
129 | int users; /* howmany video/vbi open? */ | ||
130 | int tuner_type; /* tuner type, when found */ | ||
131 | int running; /* are we rolling? */ | ||
132 | rwlock_t lock; | ||
133 | long state; /* what is requested of us? */ | ||
134 | #define STATE_OVERLAY 0 | ||
135 | #define STATE_VBI 1 | ||
136 | struct vidinfo* workqueue; /* buffers to grab, head is active */ | ||
137 | ulong fieldnr; /* #field, ticked every VSYNC */ | ||
138 | ulong lastfieldnr; /* #field, ticked every GRAB */ | ||
139 | |||
140 | int vidInterlace; /* calculated */ | ||
141 | int vidXshift; /* calculated */ | ||
142 | uint vidWidth; /* calculated */ | ||
143 | uint vidHeight; /* calculated */ | ||
144 | }; | ||
145 | |||
146 | #define zrwrite(dat,adr) writel((dat),(char *) (ztv->zoran_mem+(adr))) | ||
147 | #define zrread(adr) readl(ztv->zoran_mem+(adr)) | ||
148 | |||
149 | #if PDEBUG == 0 | ||
150 | #define zrand(dat,adr) zrwrite((dat) & zrread(adr), adr) | ||
151 | #define zror(dat,adr) zrwrite((dat) | zrread(adr), adr) | ||
152 | #define zraor(dat,mask,adr) zrwrite( ((dat)&~(mask)) | ((mask)&zrread(adr)), adr) | ||
153 | #else | ||
154 | #define zrand(dat, adr) \ | ||
155 | do { \ | ||
156 | ulong data = (dat) & zrread((adr)); \ | ||
157 | zrwrite(data, (adr)); \ | ||
158 | if (0 != (~(dat) & zrread((adr)))) \ | ||
159 | printk(KERN_DEBUG "zoran: zrand at %d(%d) detected set bits(%x)\n", __LINE__, (adr), (dat)); \ | ||
160 | } while(0) | ||
161 | |||
162 | #define zror(dat, adr) \ | ||
163 | do { \ | ||
164 | ulong data = (dat) | zrread((adr)); \ | ||
165 | zrwrite(data, (adr)); \ | ||
166 | if ((dat) != ((dat) & zrread(adr))) \ | ||
167 | printk(KERN_DEBUG "zoran: zror at %d(%d) detected unset bits(%x)\n", __LINE__, (adr), (dat)); \ | ||
168 | } while(0) | ||
169 | |||
170 | #define zraor(dat, mask, adr) \ | ||
171 | do { \ | ||
172 | ulong data; \ | ||
173 | if ((dat) & (mask)) \ | ||
174 | printk(KERN_DEBUG "zoran: zraor at %d(%d) detected bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \ | ||
175 | data = ((dat)&~(mask)) | ((mask) & zrread((adr))); \ | ||
176 | zrwrite(data,(adr)); \ | ||
177 | if ( (dat) != (~(mask) & zrread((adr))) ) \ | ||
178 | printk(KERN_DEBUG "zoran: zraor at %d(%d) could not set all bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \ | ||
179 | } while(0) | ||
180 | #endif | ||
181 | |||
182 | #endif | ||
183 | |||
184 | /* zoran PCI address space */ | ||
185 | #define ZORAN_VFEH 0x000 /* Video Front End Horizontal Conf. */ | ||
186 | #define ZORAN_VFEH_HSPOL (1<<30) | ||
187 | #define ZORAN_VFEH_HSTART (0x3FF<<10) | ||
188 | #define ZORAN_VFEH_HEND (0x3FF<<0) | ||
189 | |||
190 | #define ZORAN_VFEV 0x004 /* Video Front End Vertical Conf. */ | ||
191 | #define ZORAN_VFEV_VSPOL (1<<30) | ||
192 | #define ZORAN_VFEV_VSTART (0x3FF<<10) | ||
193 | #define ZORAN_VFEV_VEND (0x3FF<<0) | ||
194 | |||
195 | #define ZORAN_VFEC 0x008 /* Video Front End Scaler and Pixel */ | ||
196 | #define ZORAN_VFEC_EXTFL (1<<26) | ||
197 | #define ZORAN_VFEC_TOPFIELD (1<<25) | ||
198 | #define ZORAN_VFEC_VCLKPOL (1<<24) | ||
199 | #define ZORAN_VFEC_HFILTER (7<<21) | ||
200 | #define ZORAN_VFEC_HFILTER_1 (0<<21) /* no lumi, 3-tap chromo */ | ||
201 | #define ZORAN_VFEC_HFILTER_2 (1<<21) /* 3-tap lumi, 3-tap chromo */ | ||
202 | #define ZORAN_VFEC_HFILTER_3 (2<<21) /* 4-tap lumi, 4-tap chromo */ | ||
203 | #define ZORAN_VFEC_HFILTER_4 (3<<21) /* 5-tap lumi, 4-tap chromo */ | ||
204 | #define ZORAN_VFEC_HFILTER_5 (4<<21) /* 4-tap lumi, 4-tap chromo */ | ||
205 | #define ZORAN_VFEC_DUPFLD (1<<20) | ||
206 | #define ZORAN_VFEC_HORDCM (63<<14) | ||
207 | #define ZORAN_VFEC_VERDCM (63<<8) | ||
208 | #define ZORAN_VFEC_DISPMOD (1<<6) | ||
209 | #define ZORAN_VFEC_RGB (3<<3) | ||
210 | #define ZORAN_VFEC_RGB_YUV422 (0<<3) | ||
211 | #define ZORAN_VFEC_RGB_RGB888 (1<<3) | ||
212 | #define ZORAN_VFEC_RGB_RGB565 (2<<3) | ||
213 | #define ZORAN_VFEC_RGB_RGB555 (3<<3) | ||
214 | #define ZORAN_VFEC_ERRDIF (1<<2) | ||
215 | #define ZORAN_VFEC_PACK24 (1<<1) | ||
216 | #define ZORAN_VFEC_LE (1<<0) | ||
217 | |||
218 | #define ZORAN_VTOP 0x00C /* Video Display "Top" */ | ||
219 | |||
220 | #define ZORAN_VBOT 0x010 /* Video Display "Bottom" */ | ||
221 | |||
222 | #define ZORAN_VSTR 0x014 /* Video Display Stride */ | ||
223 | #define ZORAN_VSTR_DISPSTRIDE (0xFFFF<<16) | ||
224 | #define ZORAN_VSTR_VIDOVF (1<<8) | ||
225 | #define ZORAN_VSTR_SNAPSHOT (1<<1) | ||
226 | #define ZORAN_VSTR_GRAB (1<<0) | ||
227 | |||
228 | #define ZORAN_VDC 0x018 /* Video Display Conf. */ | ||
229 | #define ZORAN_VDC_VIDEN (1<<31) | ||
230 | #define ZORAN_VDC_MINPIX (0x1F<<25) | ||
231 | #define ZORAN_VDC_TRICOM (1<<24) | ||
232 | #define ZORAN_VDC_VIDWINHT (0x3FF<<12) | ||
233 | #define ZORAN_VDC_VIDWINWID (0x3FF<<0) | ||
234 | |||
235 | #define ZORAN_MTOP 0x01C /* Masking Map "Top" */ | ||
236 | |||
237 | #define ZORAN_MBOT 0x020 /* Masking Map "Bottom" */ | ||
238 | |||
239 | #define ZORAN_OCR 0x024 /* Overlay Control */ | ||
240 | #define ZORAN_OCR_OVLEN (1<<15) | ||
241 | #define ZORAN_OCR_MASKSTRIDE (0xFF<<0) | ||
242 | |||
243 | #define ZORAN_PCI 0x028 /* System, PCI and GPP Control */ | ||
244 | #define ZORAN_PCI_SOFTRESET (1<<24) | ||
245 | #define ZORAN_PCI_WAITSTATE (3<<16) | ||
246 | #define ZORAN_PCI_GENPURDIR (0xFF<<0) | ||
247 | |||
248 | #define ZORAN_GUEST 0x02C /* GuestBus Control */ | ||
249 | |||
250 | #define ZORAN_CSOURCE 0x030 /* Code Source Address */ | ||
251 | |||
252 | #define ZORAN_CTRANS 0x034 /* Code Transfer Control */ | ||
253 | |||
254 | #define ZORAN_CMEM 0x038 /* Code Memory Pointer */ | ||
255 | |||
256 | #define ZORAN_ISR 0x03C /* Interrupt Status Register */ | ||
257 | #define ZORAN_ISR_CODE (1<<28) | ||
258 | #define ZORAN_ISR_GIRQ0 (1<<29) | ||
259 | #define ZORAN_ISR_GIRQ1 (1<<30) | ||
260 | |||
261 | #define ZORAN_ICR 0x040 /* Interrupt Control Register */ | ||
262 | #define ZORAN_ICR_EN (1<<24) | ||
263 | #define ZORAN_ICR_CODE (1<<28) | ||
264 | #define ZORAN_ICR_GIRQ0 (1<<29) | ||
265 | #define ZORAN_ICR_GIRQ1 (1<<30) | ||
266 | |||
267 | #define ZORAN_I2C 0x044 /* I2C-Bus */ | ||
268 | #define ZORAN_I2C_SCL (1<<1) | ||
269 | #define ZORAN_I2C_SDA (1<<0) | ||
270 | |||
271 | #define ZORAN_POST 0x48 /* PostOffice */ | ||
272 | #define ZORAN_POST_PEN (1<<25) | ||
273 | #define ZORAN_POST_TIME (1<<24) | ||
274 | #define ZORAN_POST_DIR (1<<23) | ||
275 | #define ZORAN_POST_GUESTID (3<<20) | ||
276 | #define ZORAN_POST_GUEST (7<<16) | ||
277 | #define ZORAN_POST_DATA (0xFF<<0) | ||
278 | |||
279 | #endif | ||
diff --git a/drivers/media/video/zr36120_i2c.c b/drivers/media/video/zr36120_i2c.c deleted file mode 100644 index 21fde43a6aed..000000000000 --- a/drivers/media/video/zr36120_i2c.c +++ /dev/null | |||
@@ -1,132 +0,0 @@ | |||
1 | /* | ||
2 | zr36120_i2c.c - Zoran 36120/36125 based framegrabbers | ||
3 | |||
4 | Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <asm/io.h> | ||
24 | |||
25 | #include <linux/video_decoder.h> | ||
26 | #include <asm/uaccess.h> | ||
27 | |||
28 | #include "tuner.h" | ||
29 | #include "zr36120.h" | ||
30 | |||
31 | /* ----------------------------------------------------------------------- */ | ||
32 | /* I2C functions */ | ||
33 | /* ----------------------------------------------------------------------- */ | ||
34 | |||
35 | /* software I2C functions */ | ||
36 | |||
37 | #define I2C_DELAY 10 | ||
38 | |||
39 | static void i2c_setlines(struct i2c_bus *bus,int ctrl,int data) | ||
40 | { | ||
41 | struct zoran *ztv = (struct zoran*)bus->data; | ||
42 | unsigned int b = 0; | ||
43 | if (data) b |= ztv->card->swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA; | ||
44 | if (ctrl) b |= ztv->card->swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL; | ||
45 | zrwrite(b, ZORAN_I2C); | ||
46 | udelay(I2C_DELAY); | ||
47 | } | ||
48 | |||
49 | static int i2c_getdataline(struct i2c_bus *bus) | ||
50 | { | ||
51 | struct zoran *ztv = (struct zoran*)bus->data; | ||
52 | if (ztv->card->swapi2c) | ||
53 | return zrread(ZORAN_I2C) & ZORAN_I2C_SCL; | ||
54 | return zrread(ZORAN_I2C) & ZORAN_I2C_SDA; | ||
55 | } | ||
56 | |||
57 | static | ||
58 | void attach_inform(struct i2c_bus *bus, int id) | ||
59 | { | ||
60 | struct zoran *ztv = (struct zoran*)bus->data; | ||
61 | struct video_decoder_capability dc; | ||
62 | int rv; | ||
63 | |||
64 | switch (id) { | ||
65 | case I2C_DRIVERID_VIDEODECODER: | ||
66 | DEBUG(printk(CARD_INFO "decoder attached\n",CARD)); | ||
67 | |||
68 | /* fetch the capabilities of the decoder */ | ||
69 | rv = i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_CAPABILITIES, &dc); | ||
70 | if (rv) { | ||
71 | DEBUG(printk(CARD_DEBUG "decoder is not V4L aware!\n",CARD)); | ||
72 | break; | ||
73 | } | ||
74 | DEBUG(printk(CARD_DEBUG "capabilities %d %d %d\n",CARD,dc.flags,dc.inputs,dc.outputs)); | ||
75 | |||
76 | /* Test if the decoder can de VBI transfers */ | ||
77 | if (dc.flags & 16 /*VIDEO_DECODER_VBI*/) | ||
78 | ztv->have_decoder = 2; | ||
79 | else | ||
80 | ztv->have_decoder = 1; | ||
81 | break; | ||
82 | case I2C_DRIVERID_TUNER: | ||
83 | ztv->have_tuner = 1; | ||
84 | DEBUG(printk(CARD_INFO "tuner attached\n",CARD)); | ||
85 | if (ztv->tuner_type >= 0) | ||
86 | { | ||
87 | if (i2c_control_device(&ztv->i2c,I2C_DRIVERID_TUNER,TUNER_SET_TYPE,&ztv->tuner_type)<0) | ||
88 | DEBUG(printk(CARD_INFO "attach_inform; tuner won't be set to type %d\n",CARD,ztv->tuner_type)); | ||
89 | } | ||
90 | break; | ||
91 | default: | ||
92 | DEBUG(printk(CARD_INFO "attach_inform; unknown device id=%d\n",CARD,id)); | ||
93 | break; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static | ||
98 | void detach_inform(struct i2c_bus *bus, int id) | ||
99 | { | ||
100 | struct zoran *ztv = (struct zoran*)bus->data; | ||
101 | |||
102 | switch (id) { | ||
103 | case I2C_DRIVERID_VIDEODECODER: | ||
104 | ztv->have_decoder = 0; | ||
105 | DEBUG(printk(CARD_INFO "decoder detached\n",CARD)); | ||
106 | break; | ||
107 | case I2C_DRIVERID_TUNER: | ||
108 | ztv->have_tuner = 0; | ||
109 | DEBUG(printk(CARD_INFO "tuner detached\n",CARD)); | ||
110 | break; | ||
111 | default: | ||
112 | DEBUG(printk(CARD_INFO "detach_inform; unknown device id=%d\n",CARD,id)); | ||
113 | break; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | struct i2c_bus zoran_i2c_bus_template = | ||
118 | { | ||
119 | "ZR36120", | ||
120 | I2C_BUSID_ZORAN, | ||
121 | NULL, | ||
122 | |||
123 | SPIN_LOCK_UNLOCKED, | ||
124 | |||
125 | attach_inform, | ||
126 | detach_inform, | ||
127 | |||
128 | i2c_setlines, | ||
129 | i2c_getdataline, | ||
130 | NULL, | ||
131 | NULL | ||
132 | }; | ||
diff --git a/drivers/media/video/zr36120_mem.c b/drivers/media/video/zr36120_mem.c deleted file mode 100644 index 416eaa93b8a4..000000000000 --- a/drivers/media/video/zr36120_mem.c +++ /dev/null | |||
@@ -1,78 +0,0 @@ | |||
1 | /* | ||
2 | zr36120_mem.c - Zoran 36120/36125 based framegrabbers | ||
3 | |||
4 | Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/mm.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <asm/io.h> | ||
26 | #ifdef CONFIG_BIGPHYS_AREA | ||
27 | #include <linux/bigphysarea.h> | ||
28 | #endif | ||
29 | |||
30 | #include "zr36120.h" | ||
31 | #include "zr36120_mem.h" | ||
32 | |||
33 | /*******************************/ | ||
34 | /* Memory management functions */ | ||
35 | /*******************************/ | ||
36 | |||
37 | void* bmalloc(unsigned long size) | ||
38 | { | ||
39 | void* mem; | ||
40 | #ifdef CONFIG_BIGPHYS_AREA | ||
41 | mem = bigphysarea_alloc_pages(size/PAGE_SIZE, 1, GFP_KERNEL); | ||
42 | #else | ||
43 | /* | ||
44 | * The following function got a lot of memory at boottime, | ||
45 | * so we know its always there... | ||
46 | */ | ||
47 | mem = (void*)__get_free_pages(GFP_USER|GFP_DMA,get_order(size)); | ||
48 | #endif | ||
49 | if (mem) { | ||
50 | unsigned long adr = (unsigned long)mem; | ||
51 | while (size > 0) { | ||
52 | SetPageReserved(virt_to_page(phys_to_virt(adr))); | ||
53 | adr += PAGE_SIZE; | ||
54 | size -= PAGE_SIZE; | ||
55 | } | ||
56 | } | ||
57 | return mem; | ||
58 | } | ||
59 | |||
60 | void bfree(void* mem, unsigned long size) | ||
61 | { | ||
62 | if (mem) { | ||
63 | unsigned long adr = (unsigned long)mem; | ||
64 | unsigned long siz = size; | ||
65 | while (siz > 0) { | ||
66 | ClearPageReserved(virt_to_page(phys_to_virt(adr))); | ||
67 | adr += PAGE_SIZE; | ||
68 | siz -= PAGE_SIZE; | ||
69 | } | ||
70 | #ifdef CONFIG_BIGPHYS_AREA | ||
71 | bigphysarea_free_pages(mem); | ||
72 | #else | ||
73 | free_pages((unsigned long)mem,get_order(size)); | ||
74 | #endif | ||
75 | } | ||
76 | } | ||
77 | |||
78 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/zr36120_mem.h b/drivers/media/video/zr36120_mem.h deleted file mode 100644 index aad117acc91d..000000000000 --- a/drivers/media/video/zr36120_mem.h +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | /* either kmalloc() or bigphysarea() alloced memory - continuous */ | ||
2 | void* bmalloc(unsigned long size); | ||
3 | void bfree(void* mem, unsigned long size); | ||