diff options
Diffstat (limited to 'drivers/media/video')
120 files changed, 13206 insertions, 3739 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 6b4197018561..824a63c92629 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -224,6 +224,12 @@ config VIDEO_ZORAN_LML33R10 | |||
224 | support for the Linux Media Labs LML33R10 MJPEG capture/playback | 224 | support for the Linux Media Labs LML33R10 MJPEG capture/playback |
225 | card. | 225 | card. |
226 | 226 | ||
227 | config VIDEO_ZORAN_AVS6EYES | ||
228 | tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" | ||
229 | depends on VIDEO_ZORAN && EXPERIMENTAL && VIDEO_V4L1 | ||
230 | help | ||
231 | Support for the AverMedia 6 Eyes video surveillance card. | ||
232 | |||
227 | config VIDEO_ZR36120 | 233 | config VIDEO_ZR36120 |
228 | tristate "Zoran ZR36120/36125 Video For Linux" | 234 | tristate "Zoran ZR36120/36125 Video For Linux" |
229 | depends on PCI && I2C && VIDEO_V4L1 && BROKEN | 235 | depends on PCI && I2C && VIDEO_V4L1 && BROKEN |
@@ -306,17 +312,6 @@ config VIDEO_HEXIUM_GEMINI | |||
306 | 312 | ||
307 | source "drivers/media/video/cx88/Kconfig" | 313 | source "drivers/media/video/cx88/Kconfig" |
308 | 314 | ||
309 | config VIDEO_OVCAMCHIP | ||
310 | tristate "OmniVision Camera Chip support" | ||
311 | depends on I2C && VIDEO_V4L1 | ||
312 | ---help--- | ||
313 | Support for the OmniVision OV6xxx and OV7xxx series of camera chips. | ||
314 | This driver is intended to be used with the ov511 and w9968cf USB | ||
315 | camera drivers. | ||
316 | |||
317 | To compile this driver as a module, choose M here: the | ||
318 | module will be called ovcamchip. | ||
319 | |||
320 | config VIDEO_M32R_AR | 315 | config VIDEO_M32R_AR |
321 | tristate "AR devices" | 316 | tristate "AR devices" |
322 | depends on M32R && VIDEO_V4L1 | 317 | depends on M32R && VIDEO_V4L1 |
@@ -357,6 +352,15 @@ config VIDEO_CS53L32A | |||
357 | To compile this driver as a module, choose M here: the | 352 | To compile this driver as a module, choose M here: the |
358 | module will be called cs53l32a. | 353 | module will be called cs53l32a. |
359 | 354 | ||
355 | config VIDEO_TLV320AIC23B | ||
356 | tristate "Texas Instruments TLV320AIC23B audio codec" | ||
357 | depends on VIDEO_DEV && I2C && EXPERIMENTAL | ||
358 | ---help--- | ||
359 | Support for the Texas Instruments TLV320AIC23B audio codec. | ||
360 | |||
361 | To compile this driver as a module, choose M here: the | ||
362 | module will be called tlv320aic23b. | ||
363 | |||
360 | config VIDEO_WM8775 | 364 | config VIDEO_WM8775 |
361 | tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer" | 365 | tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer" |
362 | depends on VIDEO_DEV && I2C && EXPERIMENTAL | 366 | depends on VIDEO_DEV && I2C && EXPERIMENTAL |
@@ -380,10 +384,10 @@ config VIDEO_WM8739 | |||
380 | source "drivers/media/video/cx25840/Kconfig" | 384 | source "drivers/media/video/cx25840/Kconfig" |
381 | 385 | ||
382 | config VIDEO_SAA711X | 386 | config VIDEO_SAA711X |
383 | tristate "Philips SAA7113/4/5 video decoders (OBSOLETED)" | 387 | tristate "Philips SAA7113/4/5 video decoders" |
384 | depends on VIDEO_V4L1 && I2C && EXPERIMENTAL | 388 | depends on VIDEO_DEV && I2C && EXPERIMENTAL |
385 | ---help--- | 389 | ---help--- |
386 | Old support for the Philips SAA7113/4 video decoders. | 390 | Support for the Philips SAA7113/4/5 video decoders. |
387 | 391 | ||
388 | To compile this driver as a module, choose M here: the | 392 | To compile this driver as a module, choose M here: the |
389 | module will be called saa7115. | 393 | module will be called saa7115. |
@@ -447,6 +451,35 @@ source "drivers/media/video/usbvideo/Kconfig" | |||
447 | 451 | ||
448 | source "drivers/media/video/et61x251/Kconfig" | 452 | source "drivers/media/video/et61x251/Kconfig" |
449 | 453 | ||
454 | config VIDEO_OVCAMCHIP | ||
455 | tristate "OmniVision Camera Chip support" | ||
456 | depends on I2C && VIDEO_V4L1 | ||
457 | ---help--- | ||
458 | Support for the OmniVision OV6xxx and OV7xxx series of camera chips. | ||
459 | This driver is intended to be used with the ov511 and w9968cf USB | ||
460 | camera drivers. | ||
461 | |||
462 | To compile this driver as a module, choose M here: the | ||
463 | module will be called ovcamchip. | ||
464 | |||
465 | config USB_W9968CF | ||
466 | tristate "USB W996[87]CF JPEG Dual Mode Camera support" | ||
467 | depends on USB && VIDEO_V4L1 && I2C | ||
468 | select VIDEO_OVCAMCHIP | ||
469 | ---help--- | ||
470 | Say Y here if you want support for cameras based on OV681 or | ||
471 | Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. | ||
472 | |||
473 | This driver has an optional plugin, which is distributed as a | ||
474 | separate module only (released under GPL). It allows to use higher | ||
475 | resolutions and framerates, but cannot be included in the official | ||
476 | Linux kernel for performance purposes. | ||
477 | |||
478 | See <file:Documentation/video4linux/w9968cf.txt> for more info. | ||
479 | |||
480 | To compile this driver as a module, choose M here: the | ||
481 | module will be called w9968cf. | ||
482 | |||
450 | config USB_OV511 | 483 | config USB_OV511 |
451 | tristate "USB OV511 Camera support" | 484 | tristate "USB OV511 Camera support" |
452 | depends on USB && VIDEO_V4L1 | 485 | depends on USB && VIDEO_V4L1 |
@@ -483,24 +516,6 @@ config USB_STV680 | |||
483 | To compile this driver as a module, choose M here: the | 516 | To compile this driver as a module, choose M here: the |
484 | module will be called stv680. | 517 | module will be called stv680. |
485 | 518 | ||
486 | config USB_W9968CF | ||
487 | tristate "USB W996[87]CF JPEG Dual Mode Camera support" | ||
488 | depends on USB && VIDEO_V4L1 && I2C | ||
489 | select VIDEO_OVCAMCHIP | ||
490 | ---help--- | ||
491 | Say Y here if you want support for cameras based on OV681 or | ||
492 | Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. | ||
493 | |||
494 | This driver has an optional plugin, which is distributed as a | ||
495 | separate module only (released under GPL). It allows to use higher | ||
496 | resolutions and framerates, but cannot be included in the official | ||
497 | Linux kernel for performance purposes. | ||
498 | |||
499 | See <file:Documentation/video4linux/w9968cf.txt> for more info. | ||
500 | |||
501 | To compile this driver as a module, choose M here: the | ||
502 | module will be called w9968cf. | ||
503 | |||
504 | source "drivers/media/video/zc0301/Kconfig" | 519 | source "drivers/media/video/zc0301/Kconfig" |
505 | 520 | ||
506 | source "drivers/media/video/pwc/Kconfig" | 521 | source "drivers/media/video/pwc/Kconfig" |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index e5bf2687b76d..6c401b46398a 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -6,7 +6,7 @@ zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o | |||
6 | zr36067-objs := zoran_procfs.o zoran_device.o \ | 6 | zr36067-objs := zoran_procfs.o zoran_device.o \ |
7 | zoran_driver.o zoran_card.o | 7 | zoran_driver.o zoran_card.o |
8 | tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ | 8 | tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ |
9 | mt20xx.o tda8290.o tea5767.o | 9 | mt20xx.o tda8290.o tea5767.o tda9887.o |
10 | 10 | ||
11 | msp3400-objs := msp3400-driver.o msp3400-kthreads.o | 11 | msp3400-objs := msp3400-driver.o msp3400-kthreads.o |
12 | 12 | ||
@@ -33,6 +33,7 @@ obj-$(CONFIG_VIDEO_ZORAN_DC30) += adv7175.o vpx3220.o zr36050.o \ | |||
33 | zr36016.o | 33 | zr36016.o |
34 | obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o zr36060.o | 34 | obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o zr36060.o |
35 | obj-$(CONFIG_VIDEO_ZORAN_LML33R10) += saa7114.o adv7170.o zr36060.o | 35 | obj-$(CONFIG_VIDEO_ZORAN_LML33R10) += saa7114.o adv7170.o zr36060.o |
36 | obj-$(CONFIG_VIDEO_ZORAN_AVS6EYES) += bt866.o ks0127.o zr36060.o | ||
36 | obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o | 37 | obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o |
37 | obj-$(CONFIG_VIDEO_PMS) += pms.o | 38 | obj-$(CONFIG_VIDEO_PMS) += pms.o |
38 | obj-$(CONFIG_VIDEO_PLANB) += planb.o | 39 | obj-$(CONFIG_VIDEO_PLANB) += planb.o |
@@ -48,6 +49,7 @@ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ | |||
48 | obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o | 49 | obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o |
49 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o | 50 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o |
50 | obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o | 51 | obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o |
52 | obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o | ||
51 | obj-$(CONFIG_VIDEO_WM8775) += wm8775.o | 53 | obj-$(CONFIG_VIDEO_WM8775) += wm8775.o |
52 | obj-$(CONFIG_VIDEO_WM8739) += wm8739.o | 54 | obj-$(CONFIG_VIDEO_WM8739) += wm8739.o |
53 | obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ | 55 | obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ |
@@ -58,7 +60,7 @@ obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o | |||
58 | obj-$(CONFIG_VIDEO_DPC) += saa7111.o dpc7146.o | 60 | obj-$(CONFIG_VIDEO_DPC) += saa7111.o dpc7146.o |
59 | obj-$(CONFIG_TUNER_3036) += tuner-3036.o | 61 | obj-$(CONFIG_TUNER_3036) += tuner-3036.o |
60 | 62 | ||
61 | obj-$(CONFIG_VIDEO_TUNER) += tuner.o tda9887.o | 63 | obj-$(CONFIG_VIDEO_TUNER) += tuner.o |
62 | obj-$(CONFIG_VIDEO_BUF) += video-buf.o | 64 | obj-$(CONFIG_VIDEO_BUF) += video-buf.o |
63 | obj-$(CONFIG_VIDEO_BUF_DVB) += video-buf-dvb.o | 65 | obj-$(CONFIG_VIDEO_BUF_DVB) += video-buf-dvb.o |
64 | obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o | 66 | obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o |
@@ -71,6 +73,7 @@ obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o | |||
71 | obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o | 73 | obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o |
72 | obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o | 74 | obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o |
73 | obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o | 75 | obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o |
76 | obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o | ||
74 | 77 | ||
75 | obj-$(CONFIG_USB_DABUSB) += dabusb.o | 78 | obj-$(CONFIG_USB_DABUSB) += dabusb.o |
76 | obj-$(CONFIG_USB_DSBR) += dsbr100.o | 79 | obj-$(CONFIG_USB_DSBR) += dsbr100.o |
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index dbe025170599..6e08e32346eb 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <linux/videodev.h> | 33 | #include <linux/videodev.h> |
34 | #include <media/v4l2-common.h> | ||
34 | #include <linux/mutex.h> | 35 | #include <linux/mutex.h> |
35 | 36 | ||
36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
@@ -212,7 +213,7 @@ void init_iic(void) | |||
212 | ar_outl(0x0300, PLDI2CMOD); /* I2CMOD ACK/8b-data/7b-addr/auto */ | 213 | ar_outl(0x0300, PLDI2CMOD); /* I2CMOD ACK/8b-data/7b-addr/auto */ |
213 | ar_outl(0x1, PLDI2CACK); /* I2CACK ACK */ | 214 | ar_outl(0x1, PLDI2CACK); /* I2CACK ACK */ |
214 | 215 | ||
215 | /* I2C CLK */ | 216 | /* I2C CLK */ |
216 | /* 50MH-100k */ | 217 | /* 50MH-100k */ |
217 | if (freq == 75) { | 218 | if (freq == 75) { |
218 | ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */ | 219 | ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */ |
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c new file mode 100644 index 000000000000..05e42bbcfc3d --- /dev/null +++ b/drivers/media/video/bt866.c | |||
@@ -0,0 +1,377 @@ | |||
1 | /* | ||
2 | bt866 - BT866 Digital Video Encoder (Rockwell Part) | ||
3 | |||
4 | Copyright (C) 1999 Mike Bernson <mike@mlb.org> | ||
5 | Copyright (C) 1998 Dave Perks <dperks@ibm.net> | ||
6 | |||
7 | Modifications for LML33/DC10plus unified driver | ||
8 | Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx> | ||
9 | |||
10 | This code was modify/ported from the saa7111 driver written | ||
11 | by Dave Perks. | ||
12 | |||
13 | This code was adapted for the bt866 by Christer Weinigel and ported | ||
14 | to 2.6 by Martin Samuelsson. | ||
15 | |||
16 | This program is free software; you can redistribute it and/or modify | ||
17 | it under the terms of the GNU General Public License as published by | ||
18 | the Free Software Foundation; either version 2 of the License, or | ||
19 | (at your option) any later version. | ||
20 | |||
21 | This program is distributed in the hope that it will be useful, | ||
22 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | GNU General Public License for more details. | ||
25 | |||
26 | You should have received a copy of the GNU General Public License | ||
27 | along with this program; if not, write to the Free Software | ||
28 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
29 | */ | ||
30 | |||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/delay.h> | ||
34 | #include <linux/errno.h> | ||
35 | #include <linux/fs.h> | ||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/major.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/mm.h> | ||
40 | #include <linux/pci.h> | ||
41 | #include <linux/signal.h> | ||
42 | #include <asm/io.h> | ||
43 | #include <asm/pgtable.h> | ||
44 | #include <asm/page.h> | ||
45 | #include <linux/sched.h> | ||
46 | #include <linux/types.h> | ||
47 | #include <linux/i2c.h> | ||
48 | |||
49 | #include <linux/videodev.h> | ||
50 | #include <asm/uaccess.h> | ||
51 | |||
52 | #include <linux/video_encoder.h> | ||
53 | |||
54 | MODULE_LICENSE("GPL"); | ||
55 | |||
56 | #define BT866_DEVNAME "bt866" | ||
57 | #define I2C_BT866 0x88 | ||
58 | |||
59 | MODULE_LICENSE("GPL"); | ||
60 | |||
61 | #define DEBUG(x) /* Debug driver */ | ||
62 | |||
63 | /* ----------------------------------------------------------------------- */ | ||
64 | |||
65 | struct bt866 { | ||
66 | struct i2c_client *i2c; | ||
67 | int addr; | ||
68 | unsigned char reg[128]; | ||
69 | |||
70 | int norm; | ||
71 | int enable; | ||
72 | int bright; | ||
73 | int contrast; | ||
74 | int hue; | ||
75 | int sat; | ||
76 | }; | ||
77 | |||
78 | static int bt866_write(struct bt866 *dev, | ||
79 | unsigned char subaddr, unsigned char data); | ||
80 | |||
81 | static int bt866_do_command(struct bt866 *encoder, | ||
82 | unsigned int cmd, void *arg) | ||
83 | { | ||
84 | switch (cmd) { | ||
85 | case ENCODER_GET_CAPABILITIES: | ||
86 | { | ||
87 | struct video_encoder_capability *cap = arg; | ||
88 | |||
89 | DEBUG(printk | ||
90 | (KERN_INFO "%s: get capabilities\n", | ||
91 | encoder->i2c->name)); | ||
92 | |||
93 | cap->flags | ||
94 | = VIDEO_ENCODER_PAL | ||
95 | | VIDEO_ENCODER_NTSC | ||
96 | | VIDEO_ENCODER_CCIR; | ||
97 | cap->inputs = 2; | ||
98 | cap->outputs = 1; | ||
99 | } | ||
100 | break; | ||
101 | |||
102 | case ENCODER_SET_NORM: | ||
103 | { | ||
104 | int *iarg = arg; | ||
105 | |||
106 | DEBUG(printk(KERN_INFO "%s: set norm %d\n", | ||
107 | encoder->i2c->name, *iarg)); | ||
108 | |||
109 | switch (*iarg) { | ||
110 | |||
111 | case VIDEO_MODE_NTSC: | ||
112 | break; | ||
113 | |||
114 | case VIDEO_MODE_PAL: | ||
115 | break; | ||
116 | |||
117 | default: | ||
118 | return -EINVAL; | ||
119 | |||
120 | } | ||
121 | encoder->norm = *iarg; | ||
122 | } | ||
123 | break; | ||
124 | |||
125 | case ENCODER_SET_INPUT: | ||
126 | { | ||
127 | int *iarg = arg; | ||
128 | static const __u8 init[] = { | ||
129 | 0xc8, 0xcc, /* CRSCALE */ | ||
130 | 0xca, 0x91, /* CBSCALE */ | ||
131 | 0xcc, 0x24, /* YC16 | OSDNUM */ | ||
132 | 0xda, 0x00, /* */ | ||
133 | 0xdc, 0x24, /* SETMODE | PAL */ | ||
134 | 0xde, 0x02, /* EACTIVE */ | ||
135 | |||
136 | /* overlay colors */ | ||
137 | 0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */ | ||
138 | 0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */ | ||
139 | 0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */ | ||
140 | 0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */ | ||
141 | 0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */ | ||
142 | 0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */ | ||
143 | 0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */ | ||
144 | 0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */ | ||
145 | |||
146 | 0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */ | ||
147 | 0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */ | ||
148 | 0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */ | ||
149 | 0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */ | ||
150 | 0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */ | ||
151 | 0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */ | ||
152 | 0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */ | ||
153 | 0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */ | ||
154 | }; | ||
155 | int i; | ||
156 | u8 val; | ||
157 | |||
158 | for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2) | ||
159 | bt866_write(encoder, init[i], init[i+1]); | ||
160 | |||
161 | val = encoder->reg[0xdc]; | ||
162 | |||
163 | if (*iarg == 0) | ||
164 | val |= 0x40; /* CBSWAP */ | ||
165 | else | ||
166 | val &= ~0x40; /* !CBSWAP */ | ||
167 | |||
168 | bt866_write(encoder, 0xdc, val); | ||
169 | |||
170 | val = encoder->reg[0xcc]; | ||
171 | if (*iarg == 2) | ||
172 | val |= 0x01; /* OSDBAR */ | ||
173 | else | ||
174 | val &= ~0x01; /* !OSDBAR */ | ||
175 | bt866_write(encoder, 0xcc, val); | ||
176 | |||
177 | DEBUG(printk(KERN_INFO "%s: set input %d\n", | ||
178 | encoder->i2c->name, *iarg)); | ||
179 | |||
180 | switch (*iarg) { | ||
181 | case 0: | ||
182 | break; | ||
183 | case 1: | ||
184 | break; | ||
185 | default: | ||
186 | return -EINVAL; | ||
187 | |||
188 | } | ||
189 | } | ||
190 | break; | ||
191 | |||
192 | case ENCODER_SET_OUTPUT: | ||
193 | { | ||
194 | int *iarg = arg; | ||
195 | |||
196 | DEBUG(printk(KERN_INFO "%s: set output %d\n", | ||
197 | encoder->i2c->name, *iarg)); | ||
198 | |||
199 | /* not much choice of outputs */ | ||
200 | if (*iarg != 0) | ||
201 | return -EINVAL; | ||
202 | } | ||
203 | break; | ||
204 | |||
205 | case ENCODER_ENABLE_OUTPUT: | ||
206 | { | ||
207 | int *iarg = arg; | ||
208 | encoder->enable = !!*iarg; | ||
209 | |||
210 | DEBUG(printk | ||
211 | (KERN_INFO "%s: enable output %d\n", | ||
212 | encoder->i2c->name, encoder->enable)); | ||
213 | } | ||
214 | break; | ||
215 | |||
216 | case 4711: | ||
217 | { | ||
218 | int *iarg = arg; | ||
219 | __u8 val; | ||
220 | |||
221 | printk("bt866: square = %d\n", *iarg); | ||
222 | |||
223 | val = encoder->reg[0xdc]; | ||
224 | if (*iarg) | ||
225 | val |= 1; /* SQUARE */ | ||
226 | else | ||
227 | val &= ~1; /* !SQUARE */ | ||
228 | bt866_write(encoder, 0xdc, val); | ||
229 | break; | ||
230 | } | ||
231 | |||
232 | default: | ||
233 | return -EINVAL; | ||
234 | } | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int bt866_write(struct bt866 *encoder, | ||
240 | unsigned char subaddr, unsigned char data) | ||
241 | { | ||
242 | unsigned char buffer[2]; | ||
243 | int err; | ||
244 | |||
245 | buffer[0] = subaddr; | ||
246 | buffer[1] = data; | ||
247 | |||
248 | encoder->reg[subaddr] = data; | ||
249 | |||
250 | DEBUG(printk | ||
251 | ("%s: write 0x%02X = 0x%02X\n", | ||
252 | encoder->i2c->name, subaddr, data)); | ||
253 | |||
254 | for (err = 0; err < 3;) { | ||
255 | if (i2c_master_send(encoder->i2c, buffer, 2) == 2) | ||
256 | break; | ||
257 | err++; | ||
258 | printk(KERN_WARNING "%s: I/O error #%d " | ||
259 | "(write 0x%02x/0x%02x)\n", | ||
260 | encoder->i2c->name, err, encoder->addr, subaddr); | ||
261 | schedule_timeout_interruptible(HZ/10); | ||
262 | } | ||
263 | if (err == 3) { | ||
264 | printk(KERN_WARNING "%s: giving up\n", | ||
265 | encoder->i2c->name); | ||
266 | return -1; | ||
267 | } | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int bt866_attach(struct i2c_adapter *adapter); | ||
273 | static int bt866_detach(struct i2c_client *client); | ||
274 | static int bt866_command(struct i2c_client *client, | ||
275 | unsigned int cmd, void *arg); | ||
276 | |||
277 | |||
278 | /* Addresses to scan */ | ||
279 | static unsigned short normal_i2c[] = {I2C_BT866>>1, I2C_CLIENT_END}; | ||
280 | static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; | ||
281 | static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; | ||
282 | |||
283 | static struct i2c_client_address_data addr_data = { | ||
284 | normal_i2c, | ||
285 | probe, | ||
286 | ignore, | ||
287 | }; | ||
288 | |||
289 | static struct i2c_driver i2c_driver_bt866 = { | ||
290 | .driver.name = BT866_DEVNAME, | ||
291 | .id = I2C_DRIVERID_BT866, | ||
292 | .attach_adapter = bt866_attach, | ||
293 | .detach_client = bt866_detach, | ||
294 | .command = bt866_command | ||
295 | }; | ||
296 | |||
297 | |||
298 | static struct i2c_client bt866_client_tmpl = | ||
299 | { | ||
300 | .name = "(nil)", | ||
301 | .addr = 0, | ||
302 | .adapter = NULL, | ||
303 | .driver = &i2c_driver_bt866, | ||
304 | .usage_count = 0 | ||
305 | }; | ||
306 | |||
307 | static int bt866_found_proc(struct i2c_adapter *adapter, | ||
308 | int addr, int kind) | ||
309 | { | ||
310 | struct bt866 *encoder; | ||
311 | struct i2c_client *client; | ||
312 | |||
313 | client = kzalloc(sizeof(*client), GFP_KERNEL); | ||
314 | if (client == NULL) | ||
315 | return -ENOMEM; | ||
316 | memcpy(client, &bt866_client_tmpl, sizeof(*client)); | ||
317 | |||
318 | encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); | ||
319 | if (encoder == NULL) { | ||
320 | kfree(client); | ||
321 | return -ENOMEM; | ||
322 | } | ||
323 | |||
324 | i2c_set_clientdata(client, encoder); | ||
325 | client->adapter = adapter; | ||
326 | client->addr = addr; | ||
327 | sprintf(client->name, "%s-%02x", BT866_DEVNAME, adapter->id); | ||
328 | |||
329 | encoder->i2c = client; | ||
330 | encoder->addr = addr; | ||
331 | //encoder->encoder_type = ENCODER_TYPE_UNKNOWN; | ||
332 | |||
333 | /* initialize */ | ||
334 | |||
335 | i2c_attach_client(client); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static int bt866_attach(struct i2c_adapter *adapter) | ||
341 | { | ||
342 | if (adapter->id == I2C_HW_B_ZR36067) | ||
343 | return i2c_probe(adapter, &addr_data, bt866_found_proc); | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static int bt866_detach(struct i2c_client *client) | ||
348 | { | ||
349 | struct bt866 *encoder = i2c_get_clientdata(client); | ||
350 | |||
351 | i2c_detach_client(client); | ||
352 | kfree(encoder); | ||
353 | kfree(client); | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static int bt866_command(struct i2c_client *client, | ||
359 | unsigned int cmd, void *arg) | ||
360 | { | ||
361 | struct bt866 *encoder = i2c_get_clientdata(client); | ||
362 | return bt866_do_command(encoder, cmd, arg); | ||
363 | } | ||
364 | |||
365 | static int __devinit bt866_init(void) | ||
366 | { | ||
367 | i2c_add_driver(&i2c_driver_bt866); | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static void __devexit bt866_exit(void) | ||
372 | { | ||
373 | i2c_del_driver(&i2c_driver_bt866); | ||
374 | } | ||
375 | |||
376 | module_init(bt866_init); | ||
377 | module_exit(bt866_exit); | ||
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 2b64aa835b42..3116345c93b1 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c | |||
@@ -269,7 +269,7 @@ static struct CARD { | |||
269 | { 0x41a0a051, BTTV_BOARD_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" }, | 269 | { 0x41a0a051, BTTV_BOARD_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" }, |
270 | { 0x18501f7f, BTTV_BOARD_FLYVIDEO_98, "Lifeview Flyvideo 98" }, | 270 | { 0x18501f7f, BTTV_BOARD_FLYVIDEO_98, "Lifeview Flyvideo 98" }, |
271 | 271 | ||
272 | { 0x010115cb, BTTV_BOARD_GMV1, "AG GMV1" }, | 272 | { 0x010115cb, BTTV_BOARD_GMV1, "AG GMV1" }, |
273 | { 0x010114c7, BTTV_BOARD_MODTEC_205, "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" }, | 273 | { 0x010114c7, BTTV_BOARD_MODTEC_205, "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" }, |
274 | 274 | ||
275 | { 0x10b42636, BTTV_BOARD_HAUPPAUGE878, "STB ???" }, | 275 | { 0x10b42636, BTTV_BOARD_HAUPPAUGE878, "STB ???" }, |
@@ -309,6 +309,7 @@ static struct CARD { | |||
309 | { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, | 309 | { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, |
310 | { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, | 310 | { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, |
311 | { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, | 311 | { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, |
312 | { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "}, | ||
312 | 313 | ||
313 | { 0, -1, NULL } | 314 | { 0, -1, NULL } |
314 | }; | 315 | }; |
@@ -1903,7 +1904,7 @@ struct tvcard bttv_tvcards[] = { | |||
1903 | .no_tda7432 = 1, | 1904 | .no_tda7432 = 1, |
1904 | }, | 1905 | }, |
1905 | [BTTV_BOARD_OSPREY2x0] = { | 1906 | [BTTV_BOARD_OSPREY2x0] = { |
1906 | .name = "Osprey 210/220", /* 0x1(A|B)-04C0-C1 */ | 1907 | .name = "Osprey 210/220/230", /* 0x1(A|B)-04C0-C1 */ |
1907 | .video_inputs = 2, | 1908 | .video_inputs = 2, |
1908 | .audio_inputs = 1, | 1909 | .audio_inputs = 1, |
1909 | .tuner = -1, | 1910 | .tuner = -1, |
@@ -2745,7 +2746,7 @@ struct tvcard bttv_tvcards[] = { | |||
2745 | /* Michael Krufky <mkrufky@m1k.net> */ | 2746 | /* Michael Krufky <mkrufky@m1k.net> */ |
2746 | .name = "DViCO FusionHDTV 5 Lite", | 2747 | .name = "DViCO FusionHDTV 5 Lite", |
2747 | .tuner = 0, | 2748 | .tuner = 0, |
2748 | .tuner_type = TUNER_LG_TDVS_H062F, | 2749 | .tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */ |
2749 | .tuner_addr = ADDR_UNSET, | 2750 | .tuner_addr = ADDR_UNSET, |
2750 | .radio_addr = ADDR_UNSET, | 2751 | .radio_addr = ADDR_UNSET, |
2751 | .video_inputs = 3, | 2752 | .video_inputs = 3, |
@@ -2762,7 +2763,7 @@ struct tvcard bttv_tvcards[] = { | |||
2762 | }, | 2763 | }, |
2763 | /* ---- card 0x88---------------------------------- */ | 2764 | /* ---- card 0x88---------------------------------- */ |
2764 | [BTTV_BOARD_ACORP_Y878F] = { | 2765 | [BTTV_BOARD_ACORP_Y878F] = { |
2765 | /* Mauro Carvalho Chehab <mchehab@brturbo.com.br> */ | 2766 | /* Mauro Carvalho Chehab <mchehab@infradead.org> */ |
2766 | .name = "Acorp Y878F", | 2767 | .name = "Acorp Y878F", |
2767 | .video_inputs = 3, | 2768 | .video_inputs = 3, |
2768 | .audio_inputs = 1, | 2769 | .audio_inputs = 1, |
@@ -3790,6 +3791,7 @@ static void __devinit osprey_eeprom(struct bttv *btv) | |||
3790 | break; | 3791 | break; |
3791 | case 0x0060: | 3792 | case 0x0060: |
3792 | case 0x0070: | 3793 | case 0x0070: |
3794 | case 0x00A0: | ||
3793 | btv->c.type = BTTV_BOARD_OSPREY2x0; | 3795 | btv->c.type = BTTV_BOARD_OSPREY2x0; |
3794 | /* enable output on select control lines */ | 3796 | /* enable output on select control lines */ |
3795 | gpio_inout(0xffffff,0x000303); | 3797 | gpio_inout(0xffffff,0x000303); |
diff --git a/drivers/media/video/bt8xx/bttv-gpio.c b/drivers/media/video/bt8xx/bttv-gpio.c index c4d5e2b70c28..ba081f6f8c82 100644 --- a/drivers/media/video/bt8xx/bttv-gpio.c +++ b/drivers/media/video/bt8xx/bttv-gpio.c | |||
@@ -118,20 +118,6 @@ int bttv_sub_del_devices(struct bttv_core *core) | |||
118 | return 0; | 118 | return 0; |
119 | } | 119 | } |
120 | 120 | ||
121 | void bttv_gpio_irq(struct bttv_core *core) | ||
122 | { | ||
123 | struct bttv_sub_driver *drv; | ||
124 | struct bttv_sub_device *dev; | ||
125 | struct list_head *item; | ||
126 | |||
127 | list_for_each(item,&core->subs) { | ||
128 | dev = list_entry(item,struct bttv_sub_device,list); | ||
129 | drv = to_bttv_sub_drv(dev->dev.driver); | ||
130 | if (drv && drv->gpio_irq) | ||
131 | drv->gpio_irq(dev); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | /* ----------------------------------------------------------------------- */ | 121 | /* ----------------------------------------------------------------------- */ |
136 | /* external: sub-driver register/unregister */ | 122 | /* external: sub-driver register/unregister */ |
137 | 123 | ||
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 69efa0e5174d..b41f81d2372c 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
@@ -355,7 +355,7 @@ int bttv_input_init(struct bttv *btv) | |||
355 | 355 | ||
356 | if (ir->rc5_gpio) { | 356 | if (ir->rc5_gpio) { |
357 | u32 gpio; | 357 | u32 gpio; |
358 | /* enable remote irq */ | 358 | /* enable remote irq */ |
359 | bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4); | 359 | bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4); |
360 | gpio = bttv_gpio_read(&btv->c); | 360 | gpio = bttv_gpio_read(&btv->c); |
361 | bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); | 361 | bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); |
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 3a23265c1538..f9c9e3c4d111 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h | |||
@@ -350,7 +350,6 @@ struct bttv_sub_driver { | |||
350 | char wanted[BUS_ID_SIZE]; | 350 | char wanted[BUS_ID_SIZE]; |
351 | int (*probe)(struct bttv_sub_device *sub); | 351 | int (*probe)(struct bttv_sub_device *sub); |
352 | void (*remove)(struct bttv_sub_device *sub); | 352 | void (*remove)(struct bttv_sub_device *sub); |
353 | void (*gpio_irq)(struct bttv_sub_device *sub); | ||
354 | }; | 353 | }; |
355 | #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) | 354 | #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) |
356 | 355 | ||
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index ee989d2e15d9..d2956010f763 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
34 | #include <linux/i2c-algo-bit.h> | 34 | #include <linux/i2c-algo-bit.h> |
35 | #include <linux/videodev.h> | 35 | #include <linux/videodev.h> |
36 | #include <media/v4l2-common.h> | ||
36 | #include <linux/pci.h> | 37 | #include <linux/pci.h> |
37 | #include <linux/input.h> | 38 | #include <linux/input.h> |
38 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
@@ -214,7 +215,6 @@ extern struct videobuf_queue_ops bttv_vbi_qops; | |||
214 | extern struct bus_type bttv_sub_bus_type; | 215 | extern struct bus_type bttv_sub_bus_type; |
215 | int bttv_sub_add_device(struct bttv_core *core, char *name); | 216 | int bttv_sub_add_device(struct bttv_core *core, char *name); |
216 | int bttv_sub_del_devices(struct bttv_core *core); | 217 | int bttv_sub_del_devices(struct bttv_core *core); |
217 | void bttv_gpio_irq(struct bttv_core *core); | ||
218 | 218 | ||
219 | 219 | ||
220 | /* ---------------------------------------------------------- */ | 220 | /* ---------------------------------------------------------- */ |
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index cf61c590f4ad..7d0b6e59c6e2 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c | |||
@@ -73,6 +73,7 @@ OTHER DEALINGS IN THE SOFTWARE. | |||
73 | #include <linux/parport.h> | 73 | #include <linux/parport.h> |
74 | #include <linux/sched.h> | 74 | #include <linux/sched.h> |
75 | #include <linux/videodev.h> | 75 | #include <linux/videodev.h> |
76 | #include <media/v4l2-common.h> | ||
76 | #include <linux/mutex.h> | 77 | #include <linux/mutex.h> |
77 | #include <asm/uaccess.h> | 78 | #include <asm/uaccess.h> |
78 | 79 | ||
@@ -759,7 +760,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file, | |||
759 | { | 760 | { |
760 | struct video_picture *p = arg; | 761 | struct video_picture *p = arg; |
761 | if(p->palette!=VIDEO_PALETTE_GREY) | 762 | if(p->palette!=VIDEO_PALETTE_GREY) |
762 | return -EINVAL; | 763 | return -EINVAL; |
763 | if(p->depth!=4 && p->depth!=6) | 764 | if(p->depth!=4 && p->depth!=6) |
764 | return -EINVAL; | 765 | return -EINVAL; |
765 | 766 | ||
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 22a7386bbea6..a3989bd2f81b 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/parport.h> | 34 | #include <linux/parport.h> |
35 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
36 | #include <linux/videodev.h> | 36 | #include <linux/videodev.h> |
37 | #include <media/v4l2-common.h> | ||
37 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
38 | 39 | ||
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 85d84e89d8f4..95c5aceecc5b 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c | |||
@@ -47,13 +47,6 @@ | |||
47 | 47 | ||
48 | #include "cpia.h" | 48 | #include "cpia.h" |
49 | 49 | ||
50 | #ifdef CONFIG_VIDEO_CPIA_PP | ||
51 | extern int cpia_pp_init(void); | ||
52 | #endif | ||
53 | #ifdef CONFIG_VIDEO_CPIA_USB | ||
54 | extern int cpia_usb_init(void); | ||
55 | #endif | ||
56 | |||
57 | static int video_nr = -1; | 50 | static int video_nr = -1; |
58 | 51 | ||
59 | #ifdef MODULE | 52 | #ifdef MODULE |
@@ -67,10 +60,10 @@ MODULE_SUPPORTED_DEVICE("video"); | |||
67 | static unsigned short colorspace_conv; | 60 | static unsigned short colorspace_conv; |
68 | module_param(colorspace_conv, ushort, 0444); | 61 | module_param(colorspace_conv, ushort, 0444); |
69 | MODULE_PARM_DESC(colorspace_conv, | 62 | MODULE_PARM_DESC(colorspace_conv, |
70 | " Colorspace conversion:" | 63 | " Colorspace conversion:" |
71 | "\n 0 = disable, 1 = enable" | 64 | "\n 0 = disable, 1 = enable" |
72 | "\n Default value is 0" | 65 | "\n Default value is 0" |
73 | ); | 66 | ); |
74 | 67 | ||
75 | #define ABOUT "V4L-Driver for Vision CPiA based cameras" | 68 | #define ABOUT "V4L-Driver for Vision CPiA based cameras" |
76 | 69 | ||
@@ -4047,13 +4040,6 @@ static int __init cpia_init(void) | |||
4047 | proc_cpia_create(); | 4040 | proc_cpia_create(); |
4048 | #endif | 4041 | #endif |
4049 | 4042 | ||
4050 | #ifdef CONFIG_VIDEO_CPIA_PP | ||
4051 | cpia_pp_init(); | ||
4052 | #endif | ||
4053 | #ifdef CONFIG_VIDEO_CPIA_USB | ||
4054 | cpia_usb_init(); | ||
4055 | #endif | ||
4056 | |||
4057 | return 0; | 4043 | return 0; |
4058 | } | 4044 | } |
4059 | 4045 | ||
diff --git a/drivers/media/video/cpia.h b/drivers/media/video/cpia.h index dde27a6a4a09..6eaa692021c5 100644 --- a/drivers/media/video/cpia.h +++ b/drivers/media/video/cpia.h | |||
@@ -45,6 +45,7 @@ | |||
45 | 45 | ||
46 | #include <asm/uaccess.h> | 46 | #include <asm/uaccess.h> |
47 | #include <linux/videodev.h> | 47 | #include <linux/videodev.h> |
48 | #include <media/v4l2-common.h> | ||
48 | #include <linux/list.h> | 49 | #include <linux/list.h> |
49 | #include <linux/smp_lock.h> | 50 | #include <linux/smp_lock.h> |
50 | #include <linux/mutex.h> | 51 | #include <linux/mutex.h> |
@@ -247,7 +248,7 @@ enum v4l_camstates { | |||
247 | struct cam_data { | 248 | struct cam_data { |
248 | struct list_head cam_data_list; | 249 | struct list_head cam_data_list; |
249 | 250 | ||
250 | struct mutex busy_lock; /* guard against SMP multithreading */ | 251 | struct mutex busy_lock; /* guard against SMP multithreading */ |
251 | struct cpia_camera_ops *ops; /* lowlevel driver operations */ | 252 | struct cpia_camera_ops *ops; /* lowlevel driver operations */ |
252 | void *lowlevel_data; /* private data for lowlevel driver */ | 253 | void *lowlevel_data; /* private data for lowlevel driver */ |
253 | u8 *raw_image; /* buffer for raw image data */ | 254 | u8 *raw_image; /* buffer for raw image data */ |
diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h index 1764991b0ac9..c5ecb2be5f93 100644 --- a/drivers/media/video/cpia2/cpia2.h +++ b/drivers/media/video/cpia2/cpia2.h | |||
@@ -33,6 +33,7 @@ | |||
33 | 33 | ||
34 | #include <linux/version.h> | 34 | #include <linux/version.h> |
35 | #include <linux/videodev.h> | 35 | #include <linux/videodev.h> |
36 | #include <media/v4l2-common.h> | ||
36 | #include <linux/usb.h> | 37 | #include <linux/usb.h> |
37 | #include <linux/poll.h> | 38 | #include <linux/poll.h> |
38 | 39 | ||
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 481e178ef56d..d129db57fcd4 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c | |||
@@ -343,7 +343,9 @@ static int cpia2_close(struct inode *inode, struct file *file) | |||
343 | cpia2_free_buffers(cam); | 343 | cpia2_free_buffers(cam); |
344 | if (!cam->present) { | 344 | if (!cam->present) { |
345 | video_unregister_device(dev); | 345 | video_unregister_device(dev); |
346 | mutex_unlock(&cam->busy_lock); | ||
346 | kfree(cam); | 347 | kfree(cam); |
348 | return 0; | ||
347 | } | 349 | } |
348 | } | 350 | } |
349 | 351 | ||
@@ -1167,9 +1169,9 @@ static int ioctl_g_ctrl(void *arg,struct camera_data *cam) | |||
1167 | } else { | 1169 | } else { |
1168 | if(cam->params.flicker_control.cam_register & | 1170 | if(cam->params.flicker_control.cam_register & |
1169 | CPIA2_VP_FLICKER_MODES_50HZ) { | 1171 | CPIA2_VP_FLICKER_MODES_50HZ) { |
1170 | mode = FLICKER_50; | 1172 | mode = FLICKER_50; |
1171 | } else { | 1173 | } else { |
1172 | mode = FLICKER_60; | 1174 | mode = FLICKER_60; |
1173 | } | 1175 | } |
1174 | } | 1176 | } |
1175 | for(i=0; i<NUM_FLICKER_CONTROLS; i++) { | 1177 | for(i=0; i<NUM_FLICKER_CONTROLS; i++) { |
diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c index 0b00e6027dfb..4c89bd395d3e 100644 --- a/drivers/media/video/cpia_pp.c +++ b/drivers/media/video/cpia_pp.c | |||
@@ -803,7 +803,7 @@ static struct parport_driver cpia_pp_driver = { | |||
803 | .detach = cpia_pp_detach, | 803 | .detach = cpia_pp_detach, |
804 | }; | 804 | }; |
805 | 805 | ||
806 | int cpia_pp_init(void) | 806 | static int cpia_pp_init(void) |
807 | { | 807 | { |
808 | printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, | 808 | printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, |
809 | CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER); | 809 | CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER); |
@@ -860,6 +860,8 @@ void cleanup_module(void) | |||
860 | 860 | ||
861 | static int __init cpia_pp_setup(char *str) | 861 | static int __init cpia_pp_setup(char *str) |
862 | { | 862 | { |
863 | int err; | ||
864 | |||
863 | if (!strncmp(str, "parport", 7)) { | 865 | if (!strncmp(str, "parport", 7)) { |
864 | int n = simple_strtoul(str + 7, NULL, 10); | 866 | int n = simple_strtoul(str + 7, NULL, 10); |
865 | if (parport_ptr < PARPORT_MAX) { | 867 | if (parport_ptr < PARPORT_MAX) { |
@@ -873,6 +875,10 @@ static int __init cpia_pp_setup(char *str) | |||
873 | parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE; | 875 | parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE; |
874 | } | 876 | } |
875 | 877 | ||
878 | err=cpia_pp_init(); | ||
879 | if (err) | ||
880 | return err; | ||
881 | |||
876 | return 1; | 882 | return 1; |
877 | } | 883 | } |
878 | 884 | ||
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c index 9c49a4b00116..2ee34a3b9280 100644 --- a/drivers/media/video/cpia_usb.c +++ b/drivers/media/video/cpia_usb.c | |||
@@ -474,12 +474,6 @@ static int cpia_usb_close(void *privdata) | |||
474 | return 0; | 474 | return 0; |
475 | } | 475 | } |
476 | 476 | ||
477 | int cpia_usb_init(void) | ||
478 | { | ||
479 | /* return -ENODEV; */ | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | /* Probing and initializing */ | 477 | /* Probing and initializing */ |
484 | 478 | ||
485 | static int cpia_probe(struct usb_interface *intf, | 479 | static int cpia_probe(struct usb_interface *intf, |
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c new file mode 100644 index 000000000000..554813e6f65d --- /dev/null +++ b/drivers/media/video/cx2341x.c | |||
@@ -0,0 +1,915 @@ | |||
1 | /* | ||
2 | * cx2341x - generic code for cx23415/6 based devices | ||
3 | * | ||
4 | * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.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 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/videodev2.h> | ||
29 | #include <linux/i2c.h> | ||
30 | |||
31 | #include <media/tuner.h> | ||
32 | #include <media/cx2341x.h> | ||
33 | #include <media/v4l2-common.h> | ||
34 | |||
35 | MODULE_DESCRIPTION("cx23415/6 driver"); | ||
36 | MODULE_AUTHOR("Hans Verkuil"); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | static int debug = 0; | ||
40 | module_param(debug, int, 0644); | ||
41 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | ||
42 | |||
43 | const u32 cx2341x_mpeg_ctrls[] = { | ||
44 | V4L2_CID_MPEG_CLASS, | ||
45 | V4L2_CID_MPEG_STREAM_TYPE, | ||
46 | V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, | ||
47 | V4L2_CID_MPEG_AUDIO_ENCODING, | ||
48 | V4L2_CID_MPEG_AUDIO_L2_BITRATE, | ||
49 | V4L2_CID_MPEG_AUDIO_MODE, | ||
50 | V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, | ||
51 | V4L2_CID_MPEG_AUDIO_EMPHASIS, | ||
52 | V4L2_CID_MPEG_AUDIO_CRC, | ||
53 | V4L2_CID_MPEG_VIDEO_ENCODING, | ||
54 | V4L2_CID_MPEG_VIDEO_ASPECT, | ||
55 | V4L2_CID_MPEG_VIDEO_B_FRAMES, | ||
56 | V4L2_CID_MPEG_VIDEO_GOP_SIZE, | ||
57 | V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, | ||
58 | V4L2_CID_MPEG_VIDEO_PULLDOWN, | ||
59 | V4L2_CID_MPEG_VIDEO_BITRATE_MODE, | ||
60 | V4L2_CID_MPEG_VIDEO_BITRATE, | ||
61 | V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, | ||
62 | V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, | ||
63 | V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE, | ||
64 | V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, | ||
65 | V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE, | ||
66 | V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE, | ||
67 | V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE, | ||
68 | V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER, | ||
69 | V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE, | ||
70 | V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM, | ||
71 | V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP, | ||
72 | V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, | ||
73 | V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP, | ||
74 | 0 | ||
75 | }; | ||
76 | |||
77 | |||
78 | /* Map the control ID to the correct field in the cx2341x_mpeg_params | ||
79 | struct. Return -EINVAL if the ID is unknown, else return 0. */ | ||
80 | static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params, | ||
81 | struct v4l2_ext_control *ctrl) | ||
82 | { | ||
83 | switch (ctrl->id) { | ||
84 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | ||
85 | ctrl->value = params->audio_sampling_freq; | ||
86 | break; | ||
87 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
88 | ctrl->value = params->audio_encoding; | ||
89 | break; | ||
90 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | ||
91 | ctrl->value = params->audio_l2_bitrate; | ||
92 | break; | ||
93 | case V4L2_CID_MPEG_AUDIO_MODE: | ||
94 | ctrl->value = params->audio_mode; | ||
95 | break; | ||
96 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | ||
97 | ctrl->value = params->audio_mode_extension; | ||
98 | break; | ||
99 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: | ||
100 | ctrl->value = params->audio_emphasis; | ||
101 | break; | ||
102 | case V4L2_CID_MPEG_AUDIO_CRC: | ||
103 | ctrl->value = params->audio_crc; | ||
104 | break; | ||
105 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
106 | ctrl->value = params->video_encoding; | ||
107 | break; | ||
108 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
109 | ctrl->value = params->video_aspect; | ||
110 | break; | ||
111 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: | ||
112 | ctrl->value = params->video_b_frames; | ||
113 | break; | ||
114 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: | ||
115 | ctrl->value = params->video_gop_size; | ||
116 | break; | ||
117 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: | ||
118 | ctrl->value = params->video_gop_closure; | ||
119 | break; | ||
120 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: | ||
121 | ctrl->value = params->video_pulldown; | ||
122 | break; | ||
123 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
124 | ctrl->value = params->video_bitrate_mode; | ||
125 | break; | ||
126 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
127 | ctrl->value = params->video_bitrate; | ||
128 | break; | ||
129 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
130 | ctrl->value = params->video_bitrate_peak; | ||
131 | break; | ||
132 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: | ||
133 | ctrl->value = params->video_temporal_decimation; | ||
134 | break; | ||
135 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
136 | ctrl->value = params->stream_type; | ||
137 | break; | ||
138 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
139 | ctrl->value = params->video_spatial_filter_mode; | ||
140 | break; | ||
141 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: | ||
142 | ctrl->value = params->video_spatial_filter; | ||
143 | break; | ||
144 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | ||
145 | ctrl->value = params->video_luma_spatial_filter_type; | ||
146 | break; | ||
147 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: | ||
148 | ctrl->value = params->video_chroma_spatial_filter_type; | ||
149 | break; | ||
150 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
151 | ctrl->value = params->video_temporal_filter_mode; | ||
152 | break; | ||
153 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: | ||
154 | ctrl->value = params->video_temporal_filter; | ||
155 | break; | ||
156 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
157 | ctrl->value = params->video_median_filter_type; | ||
158 | break; | ||
159 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: | ||
160 | ctrl->value = params->video_luma_median_filter_top; | ||
161 | break; | ||
162 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: | ||
163 | ctrl->value = params->video_luma_median_filter_bottom; | ||
164 | break; | ||
165 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: | ||
166 | ctrl->value = params->video_chroma_median_filter_top; | ||
167 | break; | ||
168 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: | ||
169 | ctrl->value = params->video_chroma_median_filter_bottom; | ||
170 | break; | ||
171 | default: | ||
172 | return -EINVAL; | ||
173 | } | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | /* Map the control ID to the correct field in the cx2341x_mpeg_params | ||
178 | struct. Return -EINVAL if the ID is unknown, else return 0. */ | ||
179 | static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, | ||
180 | struct v4l2_ext_control *ctrl) | ||
181 | { | ||
182 | switch (ctrl->id) { | ||
183 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | ||
184 | params->audio_sampling_freq = ctrl->value; | ||
185 | break; | ||
186 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
187 | params->audio_encoding = ctrl->value; | ||
188 | break; | ||
189 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | ||
190 | params->audio_l2_bitrate = ctrl->value; | ||
191 | break; | ||
192 | case V4L2_CID_MPEG_AUDIO_MODE: | ||
193 | params->audio_mode = ctrl->value; | ||
194 | break; | ||
195 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | ||
196 | params->audio_mode_extension = ctrl->value; | ||
197 | break; | ||
198 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: | ||
199 | params->audio_emphasis = ctrl->value; | ||
200 | break; | ||
201 | case V4L2_CID_MPEG_AUDIO_CRC: | ||
202 | params->audio_crc = ctrl->value; | ||
203 | break; | ||
204 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
205 | params->video_aspect = ctrl->value; | ||
206 | break; | ||
207 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: { | ||
208 | int b = ctrl->value + 1; | ||
209 | int gop = params->video_gop_size; | ||
210 | params->video_b_frames = ctrl->value; | ||
211 | params->video_gop_size = b * ((gop + b - 1) / b); | ||
212 | /* Max GOP size = 34 */ | ||
213 | while (params->video_gop_size > 34) | ||
214 | params->video_gop_size -= b; | ||
215 | break; | ||
216 | } | ||
217 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: { | ||
218 | int b = params->video_b_frames + 1; | ||
219 | int gop = ctrl->value; | ||
220 | params->video_gop_size = b * ((gop + b - 1) / b); | ||
221 | /* Max GOP size = 34 */ | ||
222 | while (params->video_gop_size > 34) | ||
223 | params->video_gop_size -= b; | ||
224 | ctrl->value = params->video_gop_size; | ||
225 | break; | ||
226 | } | ||
227 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: | ||
228 | params->video_gop_closure = ctrl->value; | ||
229 | break; | ||
230 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: | ||
231 | params->video_pulldown = ctrl->value; | ||
232 | break; | ||
233 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
234 | /* MPEG-1 only allows CBR */ | ||
235 | if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 && | ||
236 | ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) | ||
237 | return -EINVAL; | ||
238 | params->video_bitrate_mode = ctrl->value; | ||
239 | break; | ||
240 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
241 | params->video_bitrate = ctrl->value; | ||
242 | break; | ||
243 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
244 | params->video_bitrate_peak = ctrl->value; | ||
245 | break; | ||
246 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: | ||
247 | params->video_temporal_decimation = ctrl->value; | ||
248 | break; | ||
249 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
250 | params->stream_type = ctrl->value; | ||
251 | params->video_encoding = | ||
252 | (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS || | ||
253 | params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ? | ||
254 | V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2; | ||
255 | if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) { | ||
256 | /* MPEG-1 implies CBR */ | ||
257 | params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; | ||
258 | } | ||
259 | break; | ||
260 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
261 | params->video_spatial_filter_mode = ctrl->value; | ||
262 | break; | ||
263 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: | ||
264 | params->video_spatial_filter = ctrl->value; | ||
265 | break; | ||
266 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | ||
267 | params->video_luma_spatial_filter_type = ctrl->value; | ||
268 | break; | ||
269 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: | ||
270 | params->video_chroma_spatial_filter_type = ctrl->value; | ||
271 | break; | ||
272 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
273 | params->video_temporal_filter_mode = ctrl->value; | ||
274 | break; | ||
275 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: | ||
276 | params->video_temporal_filter = ctrl->value; | ||
277 | break; | ||
278 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
279 | params->video_median_filter_type = ctrl->value; | ||
280 | break; | ||
281 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: | ||
282 | params->video_luma_median_filter_top = ctrl->value; | ||
283 | break; | ||
284 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: | ||
285 | params->video_luma_median_filter_bottom = ctrl->value; | ||
286 | break; | ||
287 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: | ||
288 | params->video_chroma_median_filter_top = ctrl->value; | ||
289 | break; | ||
290 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: | ||
291 | params->video_chroma_median_filter_bottom = ctrl->value; | ||
292 | break; | ||
293 | default: | ||
294 | return -EINVAL; | ||
295 | } | ||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) | ||
300 | { | ||
301 | const char *name; | ||
302 | |||
303 | qctrl->flags = 0; | ||
304 | switch (qctrl->id) { | ||
305 | /* MPEG controls */ | ||
306 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
307 | name = "Spatial Filter Mode"; | ||
308 | break; | ||
309 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: | ||
310 | name = "Spatial Filter"; | ||
311 | break; | ||
312 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | ||
313 | name = "Spatial Luma Filter Type"; | ||
314 | break; | ||
315 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: | ||
316 | name = "Spatial Chroma Filter Type"; | ||
317 | break; | ||
318 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
319 | name = "Temporal Filter Mode"; | ||
320 | break; | ||
321 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: | ||
322 | name = "Temporal Filter"; | ||
323 | break; | ||
324 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
325 | name = "Median Filter Type"; | ||
326 | break; | ||
327 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: | ||
328 | name = "Median Luma Filter Maximum"; | ||
329 | break; | ||
330 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: | ||
331 | name = "Median Luma Filter Minimum"; | ||
332 | break; | ||
333 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: | ||
334 | name = "Median Chroma Filter Maximum"; | ||
335 | break; | ||
336 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: | ||
337 | name = "Median Chroma Filter Minimum"; | ||
338 | break; | ||
339 | |||
340 | default: | ||
341 | return v4l2_ctrl_query_fill(qctrl, min, max, step, def); | ||
342 | } | ||
343 | switch (qctrl->id) { | ||
344 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
345 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | ||
346 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: | ||
347 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
348 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
349 | qctrl->type = V4L2_CTRL_TYPE_MENU; | ||
350 | min = 0; | ||
351 | step = 1; | ||
352 | break; | ||
353 | default: | ||
354 | qctrl->type = V4L2_CTRL_TYPE_INTEGER; | ||
355 | break; | ||
356 | } | ||
357 | switch (qctrl->id) { | ||
358 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
359 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
360 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
361 | qctrl->flags |= V4L2_CTRL_FLAG_UPDATE; | ||
362 | break; | ||
363 | } | ||
364 | qctrl->minimum = min; | ||
365 | qctrl->maximum = max; | ||
366 | qctrl->step = step; | ||
367 | qctrl->default_value = def; | ||
368 | qctrl->reserved[0] = qctrl->reserved[1] = 0; | ||
369 | snprintf(qctrl->name, sizeof(qctrl->name), name); | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl) | ||
374 | { | ||
375 | int err; | ||
376 | |||
377 | switch (qctrl->id) { | ||
378 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
379 | return v4l2_ctrl_query_fill(qctrl, | ||
380 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | ||
381 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1, | ||
382 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | ||
383 | |||
384 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | ||
385 | return v4l2_ctrl_query_fill(qctrl, | ||
386 | V4L2_MPEG_AUDIO_L2_BITRATE_192K, | ||
387 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, | ||
388 | V4L2_MPEG_AUDIO_L2_BITRATE_224K); | ||
389 | |||
390 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: | ||
391 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: | ||
392 | return -EINVAL; | ||
393 | |||
394 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | ||
395 | err = v4l2_ctrl_query_fill_std(qctrl); | ||
396 | if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) | ||
397 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
398 | return err; | ||
399 | |||
400 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
401 | /* this setting is read-only for the cx2341x since the | ||
402 | V4L2_CID_MPEG_STREAM_TYPE really determines the | ||
403 | MPEG-1/2 setting */ | ||
404 | err = v4l2_ctrl_query_fill_std(qctrl); | ||
405 | if (err == 0) | ||
406 | qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||
407 | return err; | ||
408 | |||
409 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
410 | err = v4l2_ctrl_query_fill_std(qctrl); | ||
411 | if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) | ||
412 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
413 | return err; | ||
414 | |||
415 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
416 | err = v4l2_ctrl_query_fill_std(qctrl); | ||
417 | if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) | ||
418 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
419 | return err; | ||
420 | |||
421 | /* CX23415/6 specific */ | ||
422 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
423 | return cx2341x_ctrl_query_fill(qctrl, | ||
424 | V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, | ||
425 | V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1, | ||
426 | V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL); | ||
427 | |||
428 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: | ||
429 | cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0); | ||
430 | qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; | ||
431 | if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) | ||
432 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
433 | return 0; | ||
434 | |||
435 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | ||
436 | cx2341x_ctrl_query_fill(qctrl, | ||
437 | V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF, | ||
438 | V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1, | ||
439 | V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF); | ||
440 | if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) | ||
441 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
442 | return 0; | ||
443 | |||
444 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: | ||
445 | cx2341x_ctrl_query_fill(qctrl, | ||
446 | V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF, | ||
447 | V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1, | ||
448 | V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF); | ||
449 | if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) | ||
450 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
451 | return 0; | ||
452 | |||
453 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
454 | return cx2341x_ctrl_query_fill(qctrl, | ||
455 | V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, | ||
456 | V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1, | ||
457 | V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL); | ||
458 | |||
459 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: | ||
460 | cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0); | ||
461 | qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; | ||
462 | if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO) | ||
463 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
464 | return 0; | ||
465 | |||
466 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
467 | return cx2341x_ctrl_query_fill(qctrl, | ||
468 | V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, | ||
469 | V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1, | ||
470 | V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF); | ||
471 | |||
472 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: | ||
473 | cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255); | ||
474 | qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; | ||
475 | if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) | ||
476 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
477 | return 0; | ||
478 | |||
479 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: | ||
480 | cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0); | ||
481 | qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; | ||
482 | if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) | ||
483 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
484 | return 0; | ||
485 | |||
486 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: | ||
487 | cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255); | ||
488 | qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; | ||
489 | if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) | ||
490 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
491 | return 0; | ||
492 | |||
493 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: | ||
494 | cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0); | ||
495 | qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; | ||
496 | if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) | ||
497 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
498 | return 0; | ||
499 | |||
500 | default: | ||
501 | return v4l2_ctrl_query_fill_std(qctrl); | ||
502 | |||
503 | } | ||
504 | } | ||
505 | |||
506 | const char **cx2341x_ctrl_get_menu(u32 id) | ||
507 | { | ||
508 | static const char *mpeg_stream_type[] = { | ||
509 | "MPEG-2 Program Stream", | ||
510 | "", | ||
511 | "MPEG-1 System Stream", | ||
512 | "MPEG-2 DVD-compatible Stream", | ||
513 | "MPEG-1 VCD-compatible Stream", | ||
514 | "MPEG-2 SVCD-compatible Stream", | ||
515 | NULL | ||
516 | }; | ||
517 | |||
518 | static const char *cx2341x_video_spatial_filter_mode_menu[] = { | ||
519 | "Manual", | ||
520 | "Auto", | ||
521 | NULL | ||
522 | }; | ||
523 | |||
524 | static const char *cx2341x_video_luma_spatial_filter_type_menu[] = { | ||
525 | "Off", | ||
526 | "1D Horizontal", | ||
527 | "1D Vertical", | ||
528 | "2D H/V Separable", | ||
529 | "2D Symmetric non-separable", | ||
530 | NULL | ||
531 | }; | ||
532 | |||
533 | static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = { | ||
534 | "Off", | ||
535 | "1D Horizontal", | ||
536 | NULL | ||
537 | }; | ||
538 | |||
539 | static const char *cx2341x_video_temporal_filter_mode_menu[] = { | ||
540 | "Manual", | ||
541 | "Auto", | ||
542 | NULL | ||
543 | }; | ||
544 | |||
545 | static const char *cx2341x_video_median_filter_type_menu[] = { | ||
546 | "Off", | ||
547 | "Horizontal", | ||
548 | "Vertical", | ||
549 | "Horizontal/Vertical", | ||
550 | "Diagonal", | ||
551 | NULL | ||
552 | }; | ||
553 | |||
554 | switch (id) { | ||
555 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
556 | return mpeg_stream_type; | ||
557 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: | ||
558 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: | ||
559 | return NULL; | ||
560 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
561 | return cx2341x_video_spatial_filter_mode_menu; | ||
562 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | ||
563 | return cx2341x_video_luma_spatial_filter_type_menu; | ||
564 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: | ||
565 | return cx2341x_video_chroma_spatial_filter_type_menu; | ||
566 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
567 | return cx2341x_video_temporal_filter_mode_menu; | ||
568 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
569 | return cx2341x_video_median_filter_type_menu; | ||
570 | default: | ||
571 | return v4l2_ctrl_get_menu(id); | ||
572 | } | ||
573 | } | ||
574 | |||
575 | static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) | ||
576 | { | ||
577 | params->audio_properties = (params->audio_sampling_freq << 0) | | ||
578 | ((3 - params->audio_encoding) << 2) | | ||
579 | ((1 + params->audio_l2_bitrate) << 4) | | ||
580 | (params->audio_mode << 8) | | ||
581 | (params->audio_mode_extension << 10) | | ||
582 | (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ? | ||
583 | 3 : | ||
584 | params->audio_emphasis) << 12) | | ||
585 | (params->audio_crc << 14); | ||
586 | } | ||
587 | |||
588 | int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, | ||
589 | struct v4l2_ext_controls *ctrls, int cmd) | ||
590 | { | ||
591 | int err = 0; | ||
592 | int i; | ||
593 | |||
594 | if (cmd == VIDIOC_G_EXT_CTRLS) { | ||
595 | for (i = 0; i < ctrls->count; i++) { | ||
596 | struct v4l2_ext_control *ctrl = ctrls->controls + i; | ||
597 | |||
598 | err = cx2341x_get_ctrl(params, ctrl); | ||
599 | if (err) { | ||
600 | ctrls->error_idx = i; | ||
601 | break; | ||
602 | } | ||
603 | } | ||
604 | return err; | ||
605 | } | ||
606 | for (i = 0; i < ctrls->count; i++) { | ||
607 | struct v4l2_ext_control *ctrl = ctrls->controls + i; | ||
608 | struct v4l2_queryctrl qctrl; | ||
609 | const char **menu_items = NULL; | ||
610 | |||
611 | qctrl.id = ctrl->id; | ||
612 | err = cx2341x_ctrl_query(params, &qctrl); | ||
613 | if (err) | ||
614 | break; | ||
615 | if (qctrl.type == V4L2_CTRL_TYPE_MENU) | ||
616 | menu_items = cx2341x_ctrl_get_menu(qctrl.id); | ||
617 | err = v4l2_ctrl_check(ctrl, &qctrl, menu_items); | ||
618 | if (err) | ||
619 | break; | ||
620 | err = cx2341x_set_ctrl(params, ctrl); | ||
621 | if (err) | ||
622 | break; | ||
623 | } | ||
624 | if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && | ||
625 | params->video_bitrate_peak < params->video_bitrate) { | ||
626 | err = -ERANGE; | ||
627 | ctrls->error_idx = ctrls->count; | ||
628 | } | ||
629 | if (err) { | ||
630 | ctrls->error_idx = i; | ||
631 | } | ||
632 | else { | ||
633 | cx2341x_calc_audio_properties(params); | ||
634 | } | ||
635 | return err; | ||
636 | } | ||
637 | |||
638 | void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p) | ||
639 | { | ||
640 | static struct cx2341x_mpeg_params default_params = { | ||
641 | /* misc */ | ||
642 | .port = CX2341X_PORT_MEMORY, | ||
643 | .width = 720, | ||
644 | .height = 480, | ||
645 | .is_50hz = 0, | ||
646 | |||
647 | /* stream */ | ||
648 | .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS, | ||
649 | |||
650 | /* audio */ | ||
651 | .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, | ||
652 | .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | ||
653 | .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K, | ||
654 | .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO, | ||
655 | .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, | ||
656 | .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE, | ||
657 | .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE, | ||
658 | |||
659 | /* video */ | ||
660 | .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2, | ||
661 | .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3, | ||
662 | .video_b_frames = 2, | ||
663 | .video_gop_size = 12, | ||
664 | .video_gop_closure = 1, | ||
665 | .video_pulldown = 0, | ||
666 | .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, | ||
667 | .video_bitrate = 6000000, | ||
668 | .video_bitrate_peak = 8000000, | ||
669 | .video_temporal_decimation = 0, | ||
670 | |||
671 | /* encoding filters */ | ||
672 | .video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, | ||
673 | .video_spatial_filter = 0, | ||
674 | .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR, | ||
675 | .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, | ||
676 | .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, | ||
677 | .video_temporal_filter = 0, | ||
678 | .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, | ||
679 | .video_luma_median_filter_top = 255, | ||
680 | .video_luma_median_filter_bottom = 0, | ||
681 | .video_chroma_median_filter_top = 255, | ||
682 | .video_chroma_median_filter_bottom = 0, | ||
683 | }; | ||
684 | |||
685 | *p = default_params; | ||
686 | cx2341x_calc_audio_properties(p); | ||
687 | } | ||
688 | |||
689 | static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...) | ||
690 | { | ||
691 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
692 | va_list vargs; | ||
693 | int i; | ||
694 | |||
695 | va_start(vargs, args); | ||
696 | |||
697 | for (i = 0; i < args; i++) { | ||
698 | data[i] = va_arg(vargs, int); | ||
699 | } | ||
700 | va_end(vargs); | ||
701 | return func(priv, cmd, args, 0, data); | ||
702 | } | ||
703 | |||
704 | int cx2341x_update(void *priv, cx2341x_mbox_func func, | ||
705 | const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new) | ||
706 | { | ||
707 | static int mpeg_stream_type[] = { | ||
708 | 0, /* MPEG-2 PS */ | ||
709 | 1, /* MPEG-2 TS */ | ||
710 | 2, /* MPEG-1 SS */ | ||
711 | 14, /* DVD */ | ||
712 | 11, /* VCD */ | ||
713 | 12, /* SVCD */ | ||
714 | }; | ||
715 | |||
716 | int err = 0; | ||
717 | |||
718 | cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0); | ||
719 | |||
720 | if (old == NULL || old->is_50hz != new->is_50hz) { | ||
721 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz); | ||
722 | if (err) return err; | ||
723 | } | ||
724 | |||
725 | if (old == NULL || old->width != new->width || old->height != new->height || | ||
726 | old->video_encoding != new->video_encoding) { | ||
727 | u16 w = new->width; | ||
728 | u16 h = new->height; | ||
729 | |||
730 | if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) { | ||
731 | w /= 2; | ||
732 | h /= 2; | ||
733 | } | ||
734 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w); | ||
735 | if (err) return err; | ||
736 | } | ||
737 | |||
738 | if (old == NULL || old->stream_type != new->stream_type) { | ||
739 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]); | ||
740 | if (err) return err; | ||
741 | } | ||
742 | if (old == NULL || old->video_aspect != new->video_aspect) { | ||
743 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect); | ||
744 | if (err) return err; | ||
745 | } | ||
746 | if (old == NULL || old->video_b_frames != new->video_b_frames || | ||
747 | old->video_gop_size != new->video_gop_size) { | ||
748 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2, | ||
749 | new->video_gop_size, new->video_b_frames + 1); | ||
750 | if (err) return err; | ||
751 | } | ||
752 | if (old == NULL || old->video_gop_closure != new->video_gop_closure) { | ||
753 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure); | ||
754 | if (err) return err; | ||
755 | } | ||
756 | if (old == NULL || old->video_pulldown != new->video_pulldown) { | ||
757 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown); | ||
758 | if (err) return err; | ||
759 | } | ||
760 | if (old == NULL || old->audio_properties != new->audio_properties) { | ||
761 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties); | ||
762 | if (err) return err; | ||
763 | } | ||
764 | if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode || | ||
765 | old->video_bitrate != new->video_bitrate || | ||
766 | old->video_bitrate_peak != new->video_bitrate_peak) { | ||
767 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5, | ||
768 | new->video_bitrate_mode, new->video_bitrate, | ||
769 | new->video_bitrate_peak / 400, 0, 0); | ||
770 | if (err) return err; | ||
771 | } | ||
772 | if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode || | ||
773 | old->video_temporal_filter_mode != new->video_temporal_filter_mode || | ||
774 | old->video_median_filter_type != new->video_median_filter_type) { | ||
775 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2, | ||
776 | new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1), | ||
777 | new->video_median_filter_type); | ||
778 | if (err) return err; | ||
779 | } | ||
780 | if (old == NULL || | ||
781 | old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom || | ||
782 | old->video_luma_median_filter_top != new->video_luma_median_filter_top || | ||
783 | old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom || | ||
784 | old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) { | ||
785 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4, | ||
786 | new->video_luma_median_filter_bottom, | ||
787 | new->video_luma_median_filter_top, | ||
788 | new->video_chroma_median_filter_bottom, | ||
789 | new->video_chroma_median_filter_top); | ||
790 | if (err) return err; | ||
791 | } | ||
792 | if (old == NULL || | ||
793 | old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type || | ||
794 | old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) { | ||
795 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2, | ||
796 | new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type); | ||
797 | if (err) return err; | ||
798 | } | ||
799 | if (old == NULL || | ||
800 | old->video_spatial_filter != new->video_spatial_filter || | ||
801 | old->video_temporal_filter != new->video_temporal_filter) { | ||
802 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2, | ||
803 | new->video_spatial_filter, new->video_temporal_filter); | ||
804 | if (err) return err; | ||
805 | } | ||
806 | if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) { | ||
807 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1, | ||
808 | new->video_temporal_decimation); | ||
809 | if (err) return err; | ||
810 | } | ||
811 | return 0; | ||
812 | } | ||
813 | |||
814 | static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id) | ||
815 | { | ||
816 | const char **menu = cx2341x_ctrl_get_menu(id); | ||
817 | struct v4l2_ext_control ctrl; | ||
818 | |||
819 | if (menu == NULL) | ||
820 | goto invalid; | ||
821 | ctrl.id = id; | ||
822 | if (cx2341x_get_ctrl(p, &ctrl)) | ||
823 | goto invalid; | ||
824 | while (ctrl.value-- && *menu) menu++; | ||
825 | if (*menu == NULL) | ||
826 | goto invalid; | ||
827 | return *menu; | ||
828 | |||
829 | invalid: | ||
830 | return "<invalid>"; | ||
831 | } | ||
832 | |||
833 | void cx2341x_log_status(struct cx2341x_mpeg_params *p, int card_id) | ||
834 | { | ||
835 | int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; | ||
836 | |||
837 | /* Stream */ | ||
838 | printk(KERN_INFO "cx2341x-%d: Stream: %s\n", | ||
839 | card_id, | ||
840 | cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE)); | ||
841 | |||
842 | /* Video */ | ||
843 | printk(KERN_INFO "cx2341x-%d: Video: %dx%d, %d fps\n", | ||
844 | card_id, | ||
845 | p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1), | ||
846 | p->is_50hz ? 25 : 30); | ||
847 | printk(KERN_INFO "cx2341x-%d: Video: %s, %s, %s, %d", | ||
848 | card_id, | ||
849 | cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING), | ||
850 | cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT), | ||
851 | cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE), | ||
852 | p->video_bitrate); | ||
853 | if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { | ||
854 | printk(", Peak %d", p->video_bitrate_peak); | ||
855 | } | ||
856 | printk("\n"); | ||
857 | printk(KERN_INFO "cx2341x-%d: Video: GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n", | ||
858 | card_id, | ||
859 | p->video_gop_size, p->video_b_frames, | ||
860 | p->video_gop_closure ? "" : "No ", | ||
861 | p->video_pulldown ? "" : "No "); | ||
862 | if (p->video_temporal_decimation) { | ||
863 | printk(KERN_INFO "cx2341x-%d: Video: Temporal Decimation %d\n", | ||
864 | card_id, p->video_temporal_decimation); | ||
865 | } | ||
866 | |||
867 | /* Audio */ | ||
868 | printk(KERN_INFO "cx2341x-%d: Audio: %s, %s, %s, %s", | ||
869 | card_id, | ||
870 | cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ), | ||
871 | cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING), | ||
872 | cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE), | ||
873 | cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE)); | ||
874 | if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) { | ||
875 | printk(", %s", | ||
876 | cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION)); | ||
877 | } | ||
878 | printk(", %s, %s\n", | ||
879 | cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS), | ||
880 | cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC)); | ||
881 | |||
882 | /* Encoding filters */ | ||
883 | printk(KERN_INFO "cx2341x-%d: Spatial Filter: %s, Luma %s, Chroma %s, %d\n", | ||
884 | card_id, | ||
885 | cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE), | ||
886 | cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE), | ||
887 | cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE), | ||
888 | p->video_spatial_filter); | ||
889 | printk(KERN_INFO "cx2341x-%d: Temporal Filter: %s, %d\n", | ||
890 | card_id, | ||
891 | cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE), | ||
892 | p->video_temporal_filter); | ||
893 | printk(KERN_INFO "cx2341x-%d: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n", | ||
894 | card_id, | ||
895 | cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE), | ||
896 | p->video_luma_median_filter_bottom, | ||
897 | p->video_luma_median_filter_top, | ||
898 | p->video_chroma_median_filter_bottom, | ||
899 | p->video_chroma_median_filter_top); | ||
900 | } | ||
901 | |||
902 | EXPORT_SYMBOL(cx2341x_fill_defaults); | ||
903 | EXPORT_SYMBOL(cx2341x_ctrl_query); | ||
904 | EXPORT_SYMBOL(cx2341x_ctrl_get_menu); | ||
905 | EXPORT_SYMBOL(cx2341x_ext_ctrls); | ||
906 | EXPORT_SYMBOL(cx2341x_update); | ||
907 | EXPORT_SYMBOL(cx2341x_log_status); | ||
908 | EXPORT_SYMBOL(cx2341x_mpeg_ctrls); | ||
909 | |||
910 | /* | ||
911 | * Local variables: | ||
912 | * c-basic-offset: 8 | ||
913 | * End: | ||
914 | */ | ||
915 | |||
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index 9a4b813152e5..f897c1ebd5f3 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c | |||
@@ -30,9 +30,6 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
30 | if (freq != 32000 && freq != 44100 && freq != 48000) | 30 | if (freq != 32000 && freq != 44100 && freq != 48000) |
31 | return -EINVAL; | 31 | return -EINVAL; |
32 | 32 | ||
33 | /* assert soft reset */ | ||
34 | cx25840_and_or(client, 0x810, ~0x1, 0x01); | ||
35 | |||
36 | /* common for all inputs and rates */ | 33 | /* common for all inputs and rates */ |
37 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ | 34 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ |
38 | cx25840_write(client, 0x127, 0x50); | 35 | cx25840_write(client, 0x127, 0x50); |
@@ -46,6 +43,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
46 | /* AUX_PLL_FRAC */ | 43 | /* AUX_PLL_FRAC */ |
47 | cx25840_write4(client, 0x110, 0xee39bb01); | 44 | cx25840_write4(client, 0x110, 0xee39bb01); |
48 | 45 | ||
46 | if (state->is_cx25836) | ||
47 | break; | ||
48 | |||
49 | /* src3/4/6_ctl = 0x0801f77f */ | 49 | /* src3/4/6_ctl = 0x0801f77f */ |
50 | cx25840_write4(client, 0x900, 0x7ff70108); | 50 | cx25840_write4(client, 0x900, 0x7ff70108); |
51 | cx25840_write4(client, 0x904, 0x7ff70108); | 51 | cx25840_write4(client, 0x904, 0x7ff70108); |
@@ -59,6 +59,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
59 | /* AUX_PLL_FRAC */ | 59 | /* AUX_PLL_FRAC */ |
60 | cx25840_write4(client, 0x110, 0xd66bec00); | 60 | cx25840_write4(client, 0x110, 0xd66bec00); |
61 | 61 | ||
62 | if (state->is_cx25836) | ||
63 | break; | ||
64 | |||
62 | /* src3/4/6_ctl = 0x08016d59 */ | 65 | /* src3/4/6_ctl = 0x08016d59 */ |
63 | cx25840_write4(client, 0x900, 0x596d0108); | 66 | cx25840_write4(client, 0x900, 0x596d0108); |
64 | cx25840_write4(client, 0x904, 0x596d0108); | 67 | cx25840_write4(client, 0x904, 0x596d0108); |
@@ -72,6 +75,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
72 | /* AUX_PLL_FRAC */ | 75 | /* AUX_PLL_FRAC */ |
73 | cx25840_write4(client, 0x110, 0xe5d69800); | 76 | cx25840_write4(client, 0x110, 0xe5d69800); |
74 | 77 | ||
78 | if (state->is_cx25836) | ||
79 | break; | ||
80 | |||
75 | /* src3/4/6_ctl = 0x08014faa */ | 81 | /* src3/4/6_ctl = 0x08014faa */ |
76 | cx25840_write4(client, 0x900, 0xaa4f0108); | 82 | cx25840_write4(client, 0x900, 0xaa4f0108); |
77 | cx25840_write4(client, 0x904, 0xaa4f0108); | 83 | cx25840_write4(client, 0x904, 0xaa4f0108); |
@@ -87,6 +93,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
87 | /* AUX_PLL_FRAC */ | 93 | /* AUX_PLL_FRAC */ |
88 | cx25840_write4(client, 0x110, 0x69082a01); | 94 | cx25840_write4(client, 0x110, 0x69082a01); |
89 | 95 | ||
96 | if (state->is_cx25836) | ||
97 | break; | ||
98 | |||
90 | /* src1_ctl = 0x08010000 */ | 99 | /* src1_ctl = 0x08010000 */ |
91 | cx25840_write4(client, 0x8f8, 0x00000108); | 100 | cx25840_write4(client, 0x8f8, 0x00000108); |
92 | 101 | ||
@@ -106,6 +115,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
106 | /* AUX_PLL_FRAC */ | 115 | /* AUX_PLL_FRAC */ |
107 | cx25840_write4(client, 0x110, 0xd66bec00); | 116 | cx25840_write4(client, 0x110, 0xd66bec00); |
108 | 117 | ||
118 | if (state->is_cx25836) | ||
119 | break; | ||
120 | |||
109 | /* src1_ctl = 0x08010000 */ | 121 | /* src1_ctl = 0x08010000 */ |
110 | cx25840_write4(client, 0x8f8, 0xcd600108); | 122 | cx25840_write4(client, 0x8f8, 0xcd600108); |
111 | 123 | ||
@@ -122,6 +134,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
122 | /* AUX_PLL_FRAC */ | 134 | /* AUX_PLL_FRAC */ |
123 | cx25840_write4(client, 0x110, 0xe5d69800); | 135 | cx25840_write4(client, 0x110, 0xe5d69800); |
124 | 136 | ||
137 | if (state->is_cx25836) | ||
138 | break; | ||
139 | |||
125 | /* src1_ctl = 0x08010000 */ | 140 | /* src1_ctl = 0x08010000 */ |
126 | cx25840_write4(client, 0x8f8, 0x00800108); | 141 | cx25840_write4(client, 0x8f8, 0x00800108); |
127 | 142 | ||
@@ -133,9 +148,6 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
133 | } | 148 | } |
134 | } | 149 | } |
135 | 150 | ||
136 | /* deassert soft reset */ | ||
137 | cx25840_and_or(client, 0x810, ~0x1, 0x00); | ||
138 | |||
139 | state->audclk_freq = freq; | 151 | state->audclk_freq = freq; |
140 | 152 | ||
141 | return 0; | 153 | return 0; |
@@ -148,6 +160,10 @@ void cx25840_audio_set_path(struct i2c_client *client) | |||
148 | /* stop microcontroller */ | 160 | /* stop microcontroller */ |
149 | cx25840_and_or(client, 0x803, ~0x10, 0); | 161 | cx25840_and_or(client, 0x803, ~0x10, 0); |
150 | 162 | ||
163 | /* assert soft reset */ | ||
164 | if (!state->is_cx25836) | ||
165 | cx25840_and_or(client, 0x810, ~0x1, 0x01); | ||
166 | |||
151 | /* Mute everything to prevent the PFFT! */ | 167 | /* Mute everything to prevent the PFFT! */ |
152 | cx25840_write(client, 0x8d3, 0x1f); | 168 | cx25840_write(client, 0x8d3, 0x1f); |
153 | 169 | ||
@@ -161,13 +177,19 @@ void cx25840_audio_set_path(struct i2c_client *client) | |||
161 | } else { | 177 | } else { |
162 | /* Set Path1 to Analog Demod Main Channel */ | 178 | /* Set Path1 to Analog Demod Main Channel */ |
163 | cx25840_write4(client, 0x8d0, 0x7038061f); | 179 | cx25840_write4(client, 0x8d0, 0x7038061f); |
180 | } | ||
164 | 181 | ||
182 | set_audclk_freq(client, state->audclk_freq); | ||
183 | |||
184 | /* deassert soft reset */ | ||
185 | if (!state->is_cx25836) | ||
186 | cx25840_and_or(client, 0x810, ~0x1, 0x00); | ||
187 | |||
188 | if (state->aud_input != CX25840_AUDIO_SERIAL) { | ||
165 | /* When the microcontroller detects the | 189 | /* When the microcontroller detects the |
166 | * audio format, it will unmute the lines */ | 190 | * audio format, it will unmute the lines */ |
167 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | 191 | cx25840_and_or(client, 0x803, ~0x10, 0x10); |
168 | } | 192 | } |
169 | |||
170 | set_audclk_freq(client, state->audclk_freq); | ||
171 | } | 193 | } |
172 | 194 | ||
173 | static int get_volume(struct i2c_client *client) | 195 | static int get_volume(struct i2c_client *client) |
@@ -291,11 +313,25 @@ static void set_mute(struct i2c_client *client, int mute) | |||
291 | 313 | ||
292 | int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) | 314 | int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) |
293 | { | 315 | { |
316 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
294 | struct v4l2_control *ctrl = arg; | 317 | struct v4l2_control *ctrl = arg; |
318 | int retval; | ||
295 | 319 | ||
296 | switch (cmd) { | 320 | switch (cmd) { |
297 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | 321 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: |
298 | return set_audclk_freq(client, *(u32 *)arg); | 322 | if (state->aud_input != CX25840_AUDIO_SERIAL) { |
323 | cx25840_and_or(client, 0x803, ~0x10, 0); | ||
324 | cx25840_write(client, 0x8d3, 0x1f); | ||
325 | } | ||
326 | if (!state->is_cx25836) | ||
327 | cx25840_and_or(client, 0x810, ~0x1, 1); | ||
328 | retval = set_audclk_freq(client, *(u32 *)arg); | ||
329 | if (!state->is_cx25836) | ||
330 | cx25840_and_or(client, 0x810, ~0x1, 0); | ||
331 | if (state->aud_input != CX25840_AUDIO_SERIAL) { | ||
332 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
333 | } | ||
334 | return retval; | ||
299 | 335 | ||
300 | case VIDIOC_G_CTRL: | 336 | case VIDIOC_G_CTRL: |
301 | switch (ctrl->id) { | 337 | switch (ctrl->id) { |
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index a961bb2ab0fd..5c2036b40ea1 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -10,6 +10,9 @@ | |||
10 | * | 10 | * |
11 | * VBI support by Hans Verkuil <hverkuil@xs4all.nl>. | 11 | * VBI support by Hans Verkuil <hverkuil@xs4all.nl>. |
12 | * | 12 | * |
13 | * NTSC sliced VBI support by Christopher Neufeld <television@cneufeld.ca> | ||
14 | * with additional fixes by Hans Verkuil <hverkuil@xs4all.nl>. | ||
15 | * | ||
13 | * This program is free software; you can redistribute it and/or | 16 | * This program is free software; you can redistribute it and/or |
14 | * modify it under the terms of the GNU General Public License | 17 | * modify it under the terms of the GNU General Public License |
15 | * as published by the Free Software Foundation; either version 2 | 18 | * as published by the Free Software Foundation; either version 2 |
@@ -43,7 +46,7 @@ MODULE_LICENSE("GPL"); | |||
43 | static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; | 46 | static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; |
44 | 47 | ||
45 | 48 | ||
46 | static int cx25840_debug; | 49 | int cx25840_debug; |
47 | 50 | ||
48 | module_param_named(debug,cx25840_debug, int, 0644); | 51 | module_param_named(debug,cx25840_debug, int, 0644); |
49 | 52 | ||
@@ -105,7 +108,7 @@ u32 cx25840_read4(struct i2c_client * client, u16 addr) | |||
105 | (buffer[2] << 8) | buffer[3]; | 108 | (buffer[2] << 8) | buffer[3]; |
106 | } | 109 | } |
107 | 110 | ||
108 | int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask, | 111 | int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask, |
109 | u8 or_value) | 112 | u8 or_value) |
110 | { | 113 | { |
111 | return cx25840_write(client, addr, | 114 | return cx25840_write(client, addr, |
@@ -117,7 +120,8 @@ int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask, | |||
117 | 120 | ||
118 | static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, | 121 | static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, |
119 | enum cx25840_audio_input aud_input); | 122 | enum cx25840_audio_input aud_input); |
120 | static void log_status(struct i2c_client *client); | 123 | static void log_audio_status(struct i2c_client *client); |
124 | static void log_video_status(struct i2c_client *client); | ||
121 | 125 | ||
122 | /* ----------------------------------------------------------------------- */ | 126 | /* ----------------------------------------------------------------------- */ |
123 | 127 | ||
@@ -147,6 +151,33 @@ static void init_dll2(struct i2c_client *client) | |||
147 | cx25840_write(client, 0x15d, 0xe1); | 151 | cx25840_write(client, 0x15d, 0xe1); |
148 | } | 152 | } |
149 | 153 | ||
154 | static void cx25836_initialize(struct i2c_client *client) | ||
155 | { | ||
156 | /* reset configuration is described on page 3-77 of the CX25836 datasheet */ | ||
157 | /* 2. */ | ||
158 | cx25840_and_or(client, 0x000, ~0x01, 0x01); | ||
159 | cx25840_and_or(client, 0x000, ~0x01, 0x00); | ||
160 | /* 3a. */ | ||
161 | cx25840_and_or(client, 0x15a, ~0x70, 0x00); | ||
162 | /* 3b. */ | ||
163 | cx25840_and_or(client, 0x15b, ~0x1e, 0x06); | ||
164 | /* 3c. */ | ||
165 | cx25840_and_or(client, 0x159, ~0x02, 0x02); | ||
166 | /* 3d. */ | ||
167 | /* There should be a 10-us delay here, but since the | ||
168 | i2c bus already has a 10-us delay we don't need to do | ||
169 | anything */ | ||
170 | /* 3e. */ | ||
171 | cx25840_and_or(client, 0x159, ~0x02, 0x00); | ||
172 | /* 3f. */ | ||
173 | cx25840_and_or(client, 0x159, ~0xc0, 0xc0); | ||
174 | /* 3g. */ | ||
175 | cx25840_and_or(client, 0x159, ~0x01, 0x00); | ||
176 | cx25840_and_or(client, 0x159, ~0x01, 0x01); | ||
177 | /* 3h. */ | ||
178 | cx25840_and_or(client, 0x15b, ~0x1e, 0x10); | ||
179 | } | ||
180 | |||
150 | static void cx25840_initialize(struct i2c_client *client, int loadfw) | 181 | static void cx25840_initialize(struct i2c_client *client, int loadfw) |
151 | { | 182 | { |
152 | struct cx25840_state *state = i2c_get_clientdata(client); | 183 | struct cx25840_state *state = i2c_get_clientdata(client); |
@@ -220,17 +251,7 @@ static void input_change(struct i2c_client *client) | |||
220 | cx25840_and_or(client, 0x401, ~0x60, 0); | 251 | cx25840_and_or(client, 0x401, ~0x60, 0); |
221 | cx25840_and_or(client, 0x401, ~0x60, 0x60); | 252 | cx25840_and_or(client, 0x401, ~0x60, 0x60); |
222 | 253 | ||
223 | /* Note: perhaps V4L2_STD_PAL_M should be handled as V4L2_STD_NTSC | 254 | if (std & V4L2_STD_525_60) { |
224 | instead of V4L2_STD_PAL. Someone needs to test this. */ | ||
225 | if (std & V4L2_STD_PAL) { | ||
226 | /* Follow tuner change procedure for PAL */ | ||
227 | cx25840_write(client, 0x808, 0xff); | ||
228 | cx25840_write(client, 0x80b, 0x10); | ||
229 | } else if (std & V4L2_STD_SECAM) { | ||
230 | /* Select autodetect for SECAM */ | ||
231 | cx25840_write(client, 0x808, 0xff); | ||
232 | cx25840_write(client, 0x80b, 0x10); | ||
233 | } else if (std & V4L2_STD_NTSC) { | ||
234 | /* Certain Hauppauge PVR150 models have a hardware bug | 255 | /* Certain Hauppauge PVR150 models have a hardware bug |
235 | that causes audio to drop out. For these models the | 256 | that causes audio to drop out. For these models the |
236 | audio standard must be set explicitly. | 257 | audio standard must be set explicitly. |
@@ -249,6 +270,14 @@ static void input_change(struct i2c_client *client) | |||
249 | cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6); | 270 | cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6); |
250 | } | 271 | } |
251 | cx25840_write(client, 0x80b, 0x00); | 272 | cx25840_write(client, 0x80b, 0x00); |
273 | } else if (std & V4L2_STD_PAL) { | ||
274 | /* Follow tuner change procedure for PAL */ | ||
275 | cx25840_write(client, 0x808, 0xff); | ||
276 | cx25840_write(client, 0x80b, 0x10); | ||
277 | } else if (std & V4L2_STD_SECAM) { | ||
278 | /* Select autodetect for SECAM */ | ||
279 | cx25840_write(client, 0x808, 0xff); | ||
280 | cx25840_write(client, 0x80b, 0x10); | ||
252 | } | 281 | } |
253 | 282 | ||
254 | if (cx25840_read(client, 0x803) & 0x10) { | 283 | if (cx25840_read(client, 0x803) & 0x10) { |
@@ -319,8 +348,10 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
319 | 348 | ||
320 | state->vid_input = vid_input; | 349 | state->vid_input = vid_input; |
321 | state->aud_input = aud_input; | 350 | state->aud_input = aud_input; |
322 | cx25840_audio_set_path(client); | 351 | if (!state->is_cx25836) { |
323 | input_change(client); | 352 | cx25840_audio_set_path(client); |
353 | input_change(client); | ||
354 | } | ||
324 | return 0; | 355 | return 0; |
325 | } | 356 | } |
326 | 357 | ||
@@ -354,6 +385,8 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) | |||
354 | } | 385 | } |
355 | } | 386 | } |
356 | 387 | ||
388 | v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt); | ||
389 | |||
357 | /* Follow step 9 of section 3.16 in the cx25840 datasheet. | 390 | /* Follow step 9 of section 3.16 in the cx25840 datasheet. |
358 | Without this PAL may display a vertical ghosting effect. | 391 | Without this PAL may display a vertical ghosting effect. |
359 | This happens for example with the Yuan MPC622. */ | 392 | This happens for example with the Yuan MPC622. */ |
@@ -370,6 +403,7 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) | |||
370 | 403 | ||
371 | v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) | 404 | v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) |
372 | { | 405 | { |
406 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
373 | /* check VID_FMT_SEL first */ | 407 | /* check VID_FMT_SEL first */ |
374 | u8 fmt = cx25840_read(client, 0x400) & 0xf; | 408 | u8 fmt = cx25840_read(client, 0x400) & 0xf; |
375 | 409 | ||
@@ -383,7 +417,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) | |||
383 | { | 417 | { |
384 | /* if the audio std is A2-M, then this is the South Korean | 418 | /* if the audio std is A2-M, then this is the South Korean |
385 | NTSC standard */ | 419 | NTSC standard */ |
386 | if (cx25840_read(client, 0x805) == 2) | 420 | if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2) |
387 | return V4L2_STD_NTSC_M_KR; | 421 | return V4L2_STD_NTSC_M_KR; |
388 | return V4L2_STD_NTSC_M; | 422 | return V4L2_STD_NTSC_M; |
389 | } | 423 | } |
@@ -456,6 +490,8 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | |||
456 | case V4L2_CID_AUDIO_TREBLE: | 490 | case V4L2_CID_AUDIO_TREBLE: |
457 | case V4L2_CID_AUDIO_BALANCE: | 491 | case V4L2_CID_AUDIO_BALANCE: |
458 | case V4L2_CID_AUDIO_MUTE: | 492 | case V4L2_CID_AUDIO_MUTE: |
493 | if (state->is_cx25836) | ||
494 | return -EINVAL; | ||
459 | return cx25840_audio(client, VIDIOC_S_CTRL, ctrl); | 495 | return cx25840_audio(client, VIDIOC_S_CTRL, ctrl); |
460 | 496 | ||
461 | default: | 497 | default: |
@@ -490,6 +526,8 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | |||
490 | case V4L2_CID_AUDIO_TREBLE: | 526 | case V4L2_CID_AUDIO_TREBLE: |
491 | case V4L2_CID_AUDIO_BALANCE: | 527 | case V4L2_CID_AUDIO_BALANCE: |
492 | case V4L2_CID_AUDIO_MUTE: | 528 | case V4L2_CID_AUDIO_MUTE: |
529 | if (state->is_cx25836) | ||
530 | return -EINVAL; | ||
493 | return cx25840_audio(client, VIDIOC_G_CTRL, ctrl); | 531 | return cx25840_audio(client, VIDIOC_G_CTRL, ctrl); |
494 | default: | 532 | default: |
495 | return -EINVAL; | 533 | return -EINVAL; |
@@ -579,91 +617,6 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | |||
579 | 617 | ||
580 | /* ----------------------------------------------------------------------- */ | 618 | /* ----------------------------------------------------------------------- */ |
581 | 619 | ||
582 | static struct v4l2_queryctrl cx25840_qctrl[] = { | ||
583 | { | ||
584 | .id = V4L2_CID_BRIGHTNESS, | ||
585 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
586 | .name = "Brightness", | ||
587 | .minimum = 0, | ||
588 | .maximum = 255, | ||
589 | .step = 1, | ||
590 | .default_value = 128, | ||
591 | .flags = 0, | ||
592 | }, { | ||
593 | .id = V4L2_CID_CONTRAST, | ||
594 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
595 | .name = "Contrast", | ||
596 | .minimum = 0, | ||
597 | .maximum = 127, | ||
598 | .step = 1, | ||
599 | .default_value = 64, | ||
600 | .flags = 0, | ||
601 | }, { | ||
602 | .id = V4L2_CID_SATURATION, | ||
603 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
604 | .name = "Saturation", | ||
605 | .minimum = 0, | ||
606 | .maximum = 127, | ||
607 | .step = 1, | ||
608 | .default_value = 64, | ||
609 | .flags = 0, | ||
610 | }, { | ||
611 | .id = V4L2_CID_HUE, | ||
612 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
613 | .name = "Hue", | ||
614 | .minimum = -128, | ||
615 | .maximum = 127, | ||
616 | .step = 1, | ||
617 | .default_value = 0, | ||
618 | .flags = 0, | ||
619 | }, { | ||
620 | .id = V4L2_CID_AUDIO_VOLUME, | ||
621 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
622 | .name = "Volume", | ||
623 | .minimum = 0, | ||
624 | .maximum = 65535, | ||
625 | .step = 65535/100, | ||
626 | .default_value = 58880, | ||
627 | .flags = 0, | ||
628 | }, { | ||
629 | .id = V4L2_CID_AUDIO_BALANCE, | ||
630 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
631 | .name = "Balance", | ||
632 | .minimum = 0, | ||
633 | .maximum = 65535, | ||
634 | .step = 65535/100, | ||
635 | .default_value = 32768, | ||
636 | .flags = 0, | ||
637 | }, { | ||
638 | .id = V4L2_CID_AUDIO_MUTE, | ||
639 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
640 | .name = "Mute", | ||
641 | .minimum = 0, | ||
642 | .maximum = 1, | ||
643 | .step = 1, | ||
644 | .default_value = 1, | ||
645 | .flags = 0, | ||
646 | }, { | ||
647 | .id = V4L2_CID_AUDIO_BASS, | ||
648 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
649 | .name = "Bass", | ||
650 | .minimum = 0, | ||
651 | .maximum = 65535, | ||
652 | .step = 65535/100, | ||
653 | .default_value = 32768, | ||
654 | }, { | ||
655 | .id = V4L2_CID_AUDIO_TREBLE, | ||
656 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
657 | .name = "Treble", | ||
658 | .minimum = 0, | ||
659 | .maximum = 65535, | ||
660 | .step = 65535/100, | ||
661 | .default_value = 32768, | ||
662 | }, | ||
663 | }; | ||
664 | |||
665 | /* ----------------------------------------------------------------------- */ | ||
666 | |||
667 | static int cx25840_command(struct i2c_client *client, unsigned int cmd, | 620 | static int cx25840_command(struct i2c_client *client, unsigned int cmd, |
668 | void *arg) | 621 | void *arg) |
669 | { | 622 | { |
@@ -706,8 +659,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
706 | 659 | ||
707 | case VIDIOC_STREAMON: | 660 | case VIDIOC_STREAMON: |
708 | v4l_dbg(1, cx25840_debug, client, "enable output\n"); | 661 | v4l_dbg(1, cx25840_debug, client, "enable output\n"); |
709 | cx25840_write(client, 0x115, 0x8c); | 662 | cx25840_write(client, 0x115, state->is_cx25836 ? 0x0c : 0x8c); |
710 | cx25840_write(client, 0x116, 0x07); | 663 | cx25840_write(client, 0x116, state->is_cx25836 ? 0x04 : 0x07); |
711 | break; | 664 | break; |
712 | 665 | ||
713 | case VIDIOC_STREAMOFF: | 666 | case VIDIOC_STREAMOFF: |
@@ -717,7 +670,9 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
717 | break; | 670 | break; |
718 | 671 | ||
719 | case VIDIOC_LOG_STATUS: | 672 | case VIDIOC_LOG_STATUS: |
720 | log_status(client); | 673 | log_video_status(client); |
674 | if (!state->is_cx25836) | ||
675 | log_audio_status(client); | ||
721 | break; | 676 | break; |
722 | 677 | ||
723 | case VIDIOC_G_CTRL: | 678 | case VIDIOC_G_CTRL: |
@@ -729,13 +684,29 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
729 | case VIDIOC_QUERYCTRL: | 684 | case VIDIOC_QUERYCTRL: |
730 | { | 685 | { |
731 | struct v4l2_queryctrl *qc = arg; | 686 | struct v4l2_queryctrl *qc = arg; |
732 | int i; | ||
733 | 687 | ||
734 | for (i = 0; i < ARRAY_SIZE(cx25840_qctrl); i++) | 688 | switch (qc->id) { |
735 | if (qc->id && qc->id == cx25840_qctrl[i].id) { | 689 | case V4L2_CID_BRIGHTNESS: |
736 | memcpy(qc, &cx25840_qctrl[i], sizeof(*qc)); | 690 | case V4L2_CID_CONTRAST: |
737 | return 0; | 691 | case V4L2_CID_SATURATION: |
738 | } | 692 | case V4L2_CID_HUE: |
693 | return v4l2_ctrl_query_fill_std(qc); | ||
694 | default: | ||
695 | break; | ||
696 | } | ||
697 | if (state->is_cx25836) | ||
698 | return -EINVAL; | ||
699 | |||
700 | switch (qc->id) { | ||
701 | case V4L2_CID_AUDIO_VOLUME: | ||
702 | case V4L2_CID_AUDIO_MUTE: | ||
703 | case V4L2_CID_AUDIO_BALANCE: | ||
704 | case V4L2_CID_AUDIO_BASS: | ||
705 | case V4L2_CID_AUDIO_TREBLE: | ||
706 | return v4l2_ctrl_query_fill_std(qc); | ||
707 | default: | ||
708 | return -EINVAL; | ||
709 | } | ||
739 | return -EINVAL; | 710 | return -EINVAL; |
740 | } | 711 | } |
741 | 712 | ||
@@ -760,31 +731,41 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
760 | return set_input(client, route->input, state->aud_input); | 731 | return set_input(client, route->input, state->aud_input); |
761 | 732 | ||
762 | case VIDIOC_INT_G_AUDIO_ROUTING: | 733 | case VIDIOC_INT_G_AUDIO_ROUTING: |
734 | if (state->is_cx25836) | ||
735 | return -EINVAL; | ||
763 | route->input = state->aud_input; | 736 | route->input = state->aud_input; |
764 | route->output = 0; | 737 | route->output = 0; |
765 | break; | 738 | break; |
766 | 739 | ||
767 | case VIDIOC_INT_S_AUDIO_ROUTING: | 740 | case VIDIOC_INT_S_AUDIO_ROUTING: |
741 | if (state->is_cx25836) | ||
742 | return -EINVAL; | ||
768 | return set_input(client, state->vid_input, route->input); | 743 | return set_input(client, state->vid_input, route->input); |
769 | 744 | ||
770 | case VIDIOC_S_FREQUENCY: | 745 | case VIDIOC_S_FREQUENCY: |
771 | input_change(client); | 746 | if (!state->is_cx25836) { |
747 | input_change(client); | ||
748 | } | ||
772 | break; | 749 | break; |
773 | 750 | ||
774 | case VIDIOC_G_TUNER: | 751 | case VIDIOC_G_TUNER: |
775 | { | 752 | { |
776 | u8 mode = cx25840_read(client, 0x804); | 753 | u8 vpres = cx25840_read(client, 0x40e) & 0x20; |
777 | u8 vpres = cx25840_read(client, 0x80a) & 0x10; | 754 | u8 mode; |
778 | int val = 0; | 755 | int val = 0; |
779 | 756 | ||
780 | if (state->radio) | 757 | if (state->radio) |
781 | break; | 758 | break; |
782 | 759 | ||
760 | vt->signal = vpres ? 0xffff : 0x0; | ||
761 | if (state->is_cx25836) | ||
762 | break; | ||
763 | |||
783 | vt->capability |= | 764 | vt->capability |= |
784 | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | | 765 | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | |
785 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; | 766 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; |
786 | 767 | ||
787 | vt->signal = vpres ? 0xffff : 0x0; | 768 | mode = cx25840_read(client, 0x804); |
788 | 769 | ||
789 | /* get rxsubchans and audmode */ | 770 | /* get rxsubchans and audmode */ |
790 | if ((mode & 0xf) == 1) | 771 | if ((mode & 0xf) == 1) |
@@ -804,7 +785,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
804 | } | 785 | } |
805 | 786 | ||
806 | case VIDIOC_S_TUNER: | 787 | case VIDIOC_S_TUNER: |
807 | if (state->radio) | 788 | if (state->radio || state->is_cx25836) |
808 | break; | 789 | break; |
809 | 790 | ||
810 | switch (vt->audmode) { | 791 | switch (vt->audmode) { |
@@ -846,12 +827,14 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
846 | return set_v4lfmt(client, (struct v4l2_format *)arg); | 827 | return set_v4lfmt(client, (struct v4l2_format *)arg); |
847 | 828 | ||
848 | case VIDIOC_INT_RESET: | 829 | case VIDIOC_INT_RESET: |
849 | cx25840_initialize(client, 0); | 830 | if (state->is_cx25836) |
831 | cx25836_initialize(client); | ||
832 | else | ||
833 | cx25840_initialize(client, 0); | ||
850 | break; | 834 | break; |
851 | 835 | ||
852 | case VIDIOC_INT_G_CHIP_IDENT: | 836 | case VIDIOC_INT_G_CHIP_IDENT: |
853 | *(enum v4l2_chip_ident *)arg = | 837 | *(enum v4l2_chip_ident *)arg = state->id; |
854 | V4L2_IDENT_CX25840 + ((cx25840_read(client, 0x100) >> 4) & 0xf); | ||
855 | break; | 838 | break; |
856 | 839 | ||
857 | default: | 840 | default: |
@@ -870,6 +853,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, | |||
870 | { | 853 | { |
871 | struct i2c_client *client; | 854 | struct i2c_client *client; |
872 | struct cx25840_state *state; | 855 | struct cx25840_state *state; |
856 | enum v4l2_chip_ident id; | ||
873 | u16 device_id; | 857 | u16 device_id; |
874 | 858 | ||
875 | /* Check if the adapter supports the needed features | 859 | /* Check if the adapter supports the needed features |
@@ -878,10 +862,11 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, | |||
878 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) | 862 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) |
879 | return 0; | 863 | return 0; |
880 | 864 | ||
881 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | 865 | state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); |
882 | if (client == 0) | 866 | if (state == 0) |
883 | return -ENOMEM; | 867 | return -ENOMEM; |
884 | 868 | ||
869 | client = &state->c; | ||
885 | client->addr = address; | 870 | client->addr = address; |
886 | client->adapter = adapter; | 871 | client->adapter = adapter; |
887 | client->driver = &i2c_driver_cx25840; | 872 | client->driver = &i2c_driver_cx25840; |
@@ -893,10 +878,18 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, | |||
893 | device_id |= cx25840_read(client, 0x100); | 878 | device_id |= cx25840_read(client, 0x100); |
894 | 879 | ||
895 | /* The high byte of the device ID should be | 880 | /* The high byte of the device ID should be |
896 | * 0x84 if chip is present */ | 881 | * 0x83 for the cx2583x and 0x84 for the cx2584x */ |
897 | if ((device_id & 0xff00) != 0x8400) { | 882 | if ((device_id & 0xff00) == 0x8300) { |
883 | id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; | ||
884 | state->is_cx25836 = 1; | ||
885 | } | ||
886 | else if ((device_id & 0xff00) == 0x8400) { | ||
887 | id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); | ||
888 | state->is_cx25836 = 0; | ||
889 | } | ||
890 | else { | ||
898 | v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); | 891 | v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); |
899 | kfree(client); | 892 | kfree(state); |
900 | return 0; | 893 | return 0; |
901 | } | 894 | } |
902 | 895 | ||
@@ -905,21 +898,19 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, | |||
905 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3, | 898 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3, |
906 | address << 1, adapter->name); | 899 | address << 1, adapter->name); |
907 | 900 | ||
908 | state = kmalloc(sizeof(struct cx25840_state), GFP_KERNEL); | ||
909 | if (state == NULL) { | ||
910 | kfree(client); | ||
911 | return -ENOMEM; | ||
912 | } | ||
913 | |||
914 | i2c_set_clientdata(client, state); | 901 | i2c_set_clientdata(client, state); |
915 | memset(state, 0, sizeof(struct cx25840_state)); | ||
916 | state->vid_input = CX25840_COMPOSITE7; | 902 | state->vid_input = CX25840_COMPOSITE7; |
917 | state->aud_input = CX25840_AUDIO8; | 903 | state->aud_input = CX25840_AUDIO8; |
918 | state->audclk_freq = 48000; | 904 | state->audclk_freq = 48000; |
919 | state->pvr150_workaround = 0; | 905 | state->pvr150_workaround = 0; |
920 | state->audmode = V4L2_TUNER_MODE_LANG1; | 906 | state->audmode = V4L2_TUNER_MODE_LANG1; |
907 | state->vbi_line_offset = 8; | ||
908 | state->id = id; | ||
921 | 909 | ||
922 | cx25840_initialize(client, 1); | 910 | if (state->is_cx25836) |
911 | cx25836_initialize(client); | ||
912 | else | ||
913 | cx25840_initialize(client, 1); | ||
923 | 914 | ||
924 | i2c_attach_client(client); | 915 | i2c_attach_client(client); |
925 | 916 | ||
@@ -944,7 +935,6 @@ static int cx25840_detach_client(struct i2c_client *client) | |||
944 | } | 935 | } |
945 | 936 | ||
946 | kfree(state); | 937 | kfree(state); |
947 | kfree(client); | ||
948 | 938 | ||
949 | return 0; | 939 | return 0; |
950 | } | 940 | } |
@@ -977,7 +967,7 @@ module_exit(m__exit); | |||
977 | 967 | ||
978 | /* ----------------------------------------------------------------------- */ | 968 | /* ----------------------------------------------------------------------- */ |
979 | 969 | ||
980 | static void log_status(struct i2c_client *client) | 970 | static void log_video_status(struct i2c_client *client) |
981 | { | 971 | { |
982 | static const char *const fmt_strs[] = { | 972 | static const char *const fmt_strs[] = { |
983 | "0x0", | 973 | "0x0", |
@@ -989,9 +979,36 @@ static void log_status(struct i2c_client *client) | |||
989 | }; | 979 | }; |
990 | 980 | ||
991 | struct cx25840_state *state = i2c_get_clientdata(client); | 981 | struct cx25840_state *state = i2c_get_clientdata(client); |
992 | u8 microctrl_vidfmt = cx25840_read(client, 0x80a); | ||
993 | u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; | 982 | u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; |
994 | u8 gen_stat1 = cx25840_read(client, 0x40d); | 983 | u8 gen_stat1 = cx25840_read(client, 0x40d); |
984 | u8 gen_stat2 = cx25840_read(client, 0x40e); | ||
985 | int vid_input = state->vid_input; | ||
986 | |||
987 | v4l_info(client, "Video signal: %spresent\n", | ||
988 | (gen_stat2 & 0x20) ? "" : "not "); | ||
989 | v4l_info(client, "Detected format: %s\n", | ||
990 | fmt_strs[gen_stat1 & 0xf]); | ||
991 | |||
992 | v4l_info(client, "Specified standard: %s\n", | ||
993 | vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); | ||
994 | |||
995 | if (vid_input >= CX25840_COMPOSITE1 && | ||
996 | vid_input <= CX25840_COMPOSITE8) { | ||
997 | v4l_info(client, "Specified video input: Composite %d\n", | ||
998 | vid_input - CX25840_COMPOSITE1 + 1); | ||
999 | } else { | ||
1000 | v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n", | ||
1001 | (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8); | ||
1002 | } | ||
1003 | |||
1004 | v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq); | ||
1005 | } | ||
1006 | |||
1007 | /* ----------------------------------------------------------------------- */ | ||
1008 | |||
1009 | static void log_audio_status(struct i2c_client *client) | ||
1010 | { | ||
1011 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
995 | u8 download_ctl = cx25840_read(client, 0x803); | 1012 | u8 download_ctl = cx25840_read(client, 0x803); |
996 | u8 mod_det_stat0 = cx25840_read(client, 0x804); | 1013 | u8 mod_det_stat0 = cx25840_read(client, 0x804); |
997 | u8 mod_det_stat1 = cx25840_read(client, 0x805); | 1014 | u8 mod_det_stat1 = cx25840_read(client, 0x805); |
@@ -999,15 +1016,9 @@ static void log_status(struct i2c_client *client) | |||
999 | u8 pref_mode = cx25840_read(client, 0x809); | 1016 | u8 pref_mode = cx25840_read(client, 0x809); |
1000 | u8 afc0 = cx25840_read(client, 0x80b); | 1017 | u8 afc0 = cx25840_read(client, 0x80b); |
1001 | u8 mute_ctl = cx25840_read(client, 0x8d3); | 1018 | u8 mute_ctl = cx25840_read(client, 0x8d3); |
1002 | int vid_input = state->vid_input; | ||
1003 | int aud_input = state->aud_input; | 1019 | int aud_input = state->aud_input; |
1004 | char *p; | 1020 | char *p; |
1005 | 1021 | ||
1006 | v4l_info(client, "Video signal: %spresent\n", | ||
1007 | (microctrl_vidfmt & 0x10) ? "" : "not "); | ||
1008 | v4l_info(client, "Detected format: %s\n", | ||
1009 | fmt_strs[gen_stat1 & 0xf]); | ||
1010 | |||
1011 | switch (mod_det_stat0) { | 1022 | switch (mod_det_stat0) { |
1012 | case 0x00: p = "mono"; break; | 1023 | case 0x00: p = "mono"; break; |
1013 | case 0x01: p = "stereo"; break; | 1024 | case 0x01: p = "stereo"; break; |
@@ -1107,25 +1118,12 @@ static void log_status(struct i2c_client *client) | |||
1107 | v4l_info(client, "Configured audio system: %s\n", p); | 1118 | v4l_info(client, "Configured audio system: %s\n", p); |
1108 | } | 1119 | } |
1109 | 1120 | ||
1110 | v4l_info(client, "Specified standard: %s\n", | ||
1111 | vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); | ||
1112 | |||
1113 | if (vid_input >= CX25840_COMPOSITE1 && | ||
1114 | vid_input <= CX25840_COMPOSITE8) { | ||
1115 | v4l_info(client, "Specified video input: Composite %d\n", | ||
1116 | vid_input - CX25840_COMPOSITE1 + 1); | ||
1117 | } else { | ||
1118 | v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n", | ||
1119 | (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8); | ||
1120 | } | ||
1121 | if (aud_input) { | 1121 | if (aud_input) { |
1122 | v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input); | 1122 | v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input); |
1123 | } else { | 1123 | } else { |
1124 | v4l_info(client, "Specified audio input: External\n"); | 1124 | v4l_info(client, "Specified audio input: External\n"); |
1125 | } | 1125 | } |
1126 | 1126 | ||
1127 | v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq); | ||
1128 | |||
1129 | switch (pref_mode & 0xf) { | 1127 | switch (pref_mode & 0xf) { |
1130 | case 0: p = "mono/language A"; break; | 1128 | case 0: p = "mono/language A"; break; |
1131 | case 1: p = "language B"; break; | 1129 | case 1: p = "language B"; break; |
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index 1736929fc204..28049064dd7d 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/videodev2.h> | 24 | #include <linux/videodev2.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | 26 | ||
27 | extern int cx25840_debug; | ||
28 | |||
27 | /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is | 29 | /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is |
28 | present in Hauppauge PVR-150 (and possibly PVR-500) cards that have | 30 | present in Hauppauge PVR-150 (and possibly PVR-500) cards that have |
29 | certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The | 31 | certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The |
@@ -33,12 +35,16 @@ | |||
33 | #define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0) | 35 | #define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0) |
34 | 36 | ||
35 | struct cx25840_state { | 37 | struct cx25840_state { |
38 | struct i2c_client c; | ||
36 | int pvr150_workaround; | 39 | int pvr150_workaround; |
37 | int radio; | 40 | int radio; |
38 | enum cx25840_video_input vid_input; | 41 | enum cx25840_video_input vid_input; |
39 | enum cx25840_audio_input aud_input; | 42 | enum cx25840_audio_input aud_input; |
40 | u32 audclk_freq; | 43 | u32 audclk_freq; |
41 | int audmode; | 44 | int audmode; |
45 | int vbi_line_offset; | ||
46 | enum v4l2_chip_ident id; | ||
47 | int is_cx25836; | ||
42 | }; | 48 | }; |
43 | 49 | ||
44 | /* ----------------------------------------------------------------------- */ | 50 | /* ----------------------------------------------------------------------- */ |
@@ -47,7 +53,7 @@ int cx25840_write(struct i2c_client *client, u16 addr, u8 value); | |||
47 | int cx25840_write4(struct i2c_client *client, u16 addr, u32 value); | 53 | int cx25840_write4(struct i2c_client *client, u16 addr, u32 value); |
48 | u8 cx25840_read(struct i2c_client *client, u16 addr); | 54 | u8 cx25840_read(struct i2c_client *client, u16 addr); |
49 | u32 cx25840_read4(struct i2c_client *client, u16 addr); | 55 | u32 cx25840_read4(struct i2c_client *client, u16 addr); |
50 | int cx25840_and_or(struct i2c_client *client, u16 addr, u8 mask, u8 value); | 56 | int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value); |
51 | v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client); | 57 | v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client); |
52 | 58 | ||
53 | /* ----------------------------------------------------------------------- */ | 59 | /* ----------------------------------------------------------------------- */ |
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 57feca288d2b..6cc8bf215e85 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c | |||
@@ -84,67 +84,140 @@ static int decode_vps(u8 * dst, u8 * p) | |||
84 | 84 | ||
85 | void cx25840_vbi_setup(struct i2c_client *client) | 85 | void cx25840_vbi_setup(struct i2c_client *client) |
86 | { | 86 | { |
87 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
87 | v4l2_std_id std = cx25840_get_v4lstd(client); | 88 | v4l2_std_id std = cx25840_get_v4lstd(client); |
89 | int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation; | ||
90 | int luma_lpf,uv_lpf, comb; | ||
91 | u32 pll_int,pll_frac,pll_post; | ||
88 | 92 | ||
93 | /* datasheet startup, step 8d */ | ||
89 | if (std & ~V4L2_STD_NTSC) { | 94 | if (std & ~V4L2_STD_NTSC) { |
90 | /* datasheet startup, step 8d */ | ||
91 | cx25840_write(client, 0x49f, 0x11); | 95 | cx25840_write(client, 0x49f, 0x11); |
96 | } else { | ||
97 | cx25840_write(client, 0x49f, 0x14); | ||
98 | } | ||
92 | 99 | ||
93 | cx25840_write(client, 0x470, 0x84); | 100 | if (std & V4L2_STD_625_50) { |
94 | cx25840_write(client, 0x471, 0x00); | 101 | hblank=0x084; |
95 | cx25840_write(client, 0x472, 0x2d); | 102 | hactive=0x2d0; |
96 | cx25840_write(client, 0x473, 0x5d); | 103 | burst=0x5d; |
97 | 104 | vblank=0x024; | |
98 | cx25840_write(client, 0x474, 0x24); | 105 | vactive=0x244; |
99 | cx25840_write(client, 0x475, 0x40); | 106 | vblank656=0x28; |
100 | cx25840_write(client, 0x476, 0x24); | 107 | src_decimation=0x21f; |
101 | cx25840_write(client, 0x477, 0x28); | ||
102 | |||
103 | cx25840_write(client, 0x478, 0x1f); | ||
104 | cx25840_write(client, 0x479, 0x02); | ||
105 | 108 | ||
109 | luma_lpf=2; | ||
106 | if (std & V4L2_STD_SECAM) { | 110 | if (std & V4L2_STD_SECAM) { |
107 | cx25840_write(client, 0x47a, 0x80); | 111 | uv_lpf=0; |
108 | cx25840_write(client, 0x47b, 0x00); | 112 | comb=0; |
109 | cx25840_write(client, 0x47c, 0x5f); | 113 | sc=0x0a425f; |
110 | cx25840_write(client, 0x47d, 0x42); | ||
111 | } else { | 114 | } else { |
112 | cx25840_write(client, 0x47a, 0x90); | 115 | uv_lpf=1; |
113 | cx25840_write(client, 0x47b, 0x20); | 116 | comb=0x20; |
114 | cx25840_write(client, 0x47c, 0x63); | 117 | sc=0x0a8263; |
115 | cx25840_write(client, 0x47d, 0x82); | ||
116 | } | 118 | } |
117 | |||
118 | cx25840_write(client, 0x47e, 0x0a); | ||
119 | cx25840_write(client, 0x47f, 0x01); | ||
120 | } else { | 119 | } else { |
121 | /* datasheet startup, step 8d */ | 120 | hactive=720; |
122 | cx25840_write(client, 0x49f, 0x14); | 121 | hblank=122; |
122 | vactive=487; | ||
123 | luma_lpf=1; | ||
124 | uv_lpf=1; | ||
125 | |||
126 | src_decimation=0x21f; | ||
127 | if (std == V4L2_STD_PAL_M) { | ||
128 | vblank=20; | ||
129 | vblank656=24; | ||
130 | burst=0x61; | ||
131 | comb=0x20; | ||
132 | |||
133 | sc=555452; | ||
134 | } else { | ||
135 | vblank=26; | ||
136 | vblank656=26; | ||
137 | burst=0x5b; | ||
138 | comb=0x66; | ||
139 | sc=556063; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | /* DEBUG: Displays configured PLL frequency */ | ||
144 | pll_int=cx25840_read(client, 0x108); | ||
145 | pll_frac=cx25840_read4(client, 0x10c)&0x1ffffff; | ||
146 | pll_post=cx25840_read(client, 0x109); | ||
147 | v4l_dbg(1, cx25840_debug, client, | ||
148 | "PLL regs = int: %u, frac: %u, post: %u\n", | ||
149 | pll_int,pll_frac,pll_post); | ||
150 | |||
151 | if (pll_post) { | ||
152 | int fin, fsc; | ||
153 | int pll= (28636363L*((((u64)pll_int)<<25L)+pll_frac)) >>25L; | ||
154 | |||
155 | pll/=pll_post; | ||
156 | v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n", | ||
157 | pll/1000000, pll%1000000); | ||
158 | v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n", | ||
159 | pll/8000000, (pll/8)%1000000); | ||
160 | |||
161 | fin=((u64)src_decimation*pll)>>12; | ||
162 | v4l_dbg(1, cx25840_debug, client, "ADC Sampling freq = " | ||
163 | "%d.%06d MHz\n", | ||
164 | fin/1000000,fin%1000000); | ||
165 | |||
166 | fsc= (((u64)sc)*pll) >> 24L; | ||
167 | v4l_dbg(1, cx25840_debug, client, "Chroma sub-carrier freq = " | ||
168 | "%d.%06d MHz\n", | ||
169 | fsc/1000000,fsc%1000000); | ||
170 | |||
171 | v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, " | ||
172 | "vblank %i , vactive %i, vblank656 %i, src_dec %i," | ||
173 | "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x," | ||
174 | " sc 0x%06x\n", | ||
175 | hblank, hactive, vblank, vactive, vblank656, | ||
176 | src_decimation, burst, luma_lpf, uv_lpf, comb, sc); | ||
177 | } | ||
178 | |||
179 | /* Sets horizontal blanking delay and active lines */ | ||
180 | cx25840_write(client, 0x470, hblank); | ||
181 | cx25840_write(client, 0x471, 0xff&(((hblank>>8)&0x3)|(hactive <<4))); | ||
182 | cx25840_write(client, 0x472, hactive>>4); | ||
183 | |||
184 | /* Sets burst gate delay */ | ||
185 | cx25840_write(client, 0x473, burst); | ||
123 | 186 | ||
124 | cx25840_write(client, 0x470, 0x7a); | 187 | /* Sets vertical blanking delay and active duration */ |
125 | cx25840_write(client, 0x471, 0x00); | 188 | cx25840_write(client, 0x474, vblank); |
126 | cx25840_write(client, 0x472, 0x2d); | 189 | cx25840_write(client, 0x475, 0xff&(((vblank>>8)&0x3)|(vactive <<4))); |
127 | cx25840_write(client, 0x473, 0x5b); | 190 | cx25840_write(client, 0x476, vactive>>4); |
191 | cx25840_write(client, 0x477, vblank656); | ||
128 | 192 | ||
129 | cx25840_write(client, 0x474, 0x1a); | 193 | /* Sets src decimation rate */ |
130 | cx25840_write(client, 0x475, 0x70); | 194 | cx25840_write(client, 0x478, 0xff&src_decimation); |
131 | cx25840_write(client, 0x476, 0x1e); | 195 | cx25840_write(client, 0x479, 0xff&(src_decimation>>8)); |
132 | cx25840_write(client, 0x477, 0x1e); | ||
133 | 196 | ||
134 | cx25840_write(client, 0x478, 0x1f); | 197 | /* Sets Luma and UV Low pass filters */ |
135 | cx25840_write(client, 0x479, 0x02); | 198 | cx25840_write(client, 0x47a, luma_lpf<<6|((uv_lpf<<4)&0x30)); |
136 | cx25840_write(client, 0x47a, 0x50); | ||
137 | cx25840_write(client, 0x47b, 0x66); | ||
138 | 199 | ||
139 | cx25840_write(client, 0x47c, 0x1f); | 200 | /* Enables comb filters */ |
140 | cx25840_write(client, 0x47d, 0x7c); | 201 | cx25840_write(client, 0x47b, comb); |
141 | cx25840_write(client, 0x47e, 0x08); | 202 | |
203 | /* Sets SC Step*/ | ||
204 | cx25840_write(client, 0x47c, sc); | ||
205 | cx25840_write(client, 0x47d, 0xff&sc>>8); | ||
206 | cx25840_write(client, 0x47e, 0xff&sc>>16); | ||
207 | |||
208 | /* Sets VBI parameters */ | ||
209 | if (std & V4L2_STD_625_50) { | ||
210 | cx25840_write(client, 0x47f, 0x01); | ||
211 | state->vbi_line_offset = 5; | ||
212 | } else { | ||
142 | cx25840_write(client, 0x47f, 0x00); | 213 | cx25840_write(client, 0x47f, 0x00); |
214 | state->vbi_line_offset = 8; | ||
143 | } | 215 | } |
144 | } | 216 | } |
145 | 217 | ||
146 | int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | 218 | int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) |
147 | { | 219 | { |
220 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
148 | struct v4l2_format *fmt; | 221 | struct v4l2_format *fmt; |
149 | struct v4l2_sliced_vbi_format *svbi; | 222 | struct v4l2_sliced_vbi_format *svbi; |
150 | 223 | ||
@@ -182,7 +255,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | |||
182 | 255 | ||
183 | case VIDIOC_S_FMT: | 256 | case VIDIOC_S_FMT: |
184 | { | 257 | { |
185 | int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); | 258 | int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); |
186 | int vbi_offset = is_pal ? 1 : 0; | 259 | int vbi_offset = is_pal ? 1 : 0; |
187 | int i, x; | 260 | int i, x; |
188 | u8 lcr[24]; | 261 | u8 lcr[24]; |
@@ -211,7 +284,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | |||
211 | cx25840_vbi_setup(client); | 284 | cx25840_vbi_setup(client); |
212 | 285 | ||
213 | /* Sliced VBI */ | 286 | /* Sliced VBI */ |
214 | cx25840_write(client, 0x404, 0x36); /* Ancillery data */ | 287 | cx25840_write(client, 0x404, 0x32); /* Ancillary data */ |
215 | cx25840_write(client, 0x406, 0x13); | 288 | cx25840_write(client, 0x406, 0x13); |
216 | cx25840_write(client, 0x47f, vbi_offset); | 289 | cx25840_write(client, 0x47f, vbi_offset); |
217 | 290 | ||
@@ -248,8 +321,18 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | |||
248 | } | 321 | } |
249 | } | 322 | } |
250 | 323 | ||
251 | for (x = 1, i = 0x424; i <= 0x434; i++, x++) { | 324 | if (is_pal) { |
252 | cx25840_write(client, i, lcr[6 + x]); | 325 | for (x = 1, i = 0x424; i <= 0x434; i++, x++) { |
326 | cx25840_write(client, i, lcr[6 + x]); | ||
327 | } | ||
328 | } | ||
329 | else { | ||
330 | for (x = 1, i = 0x424; i <= 0x430; i++, x++) { | ||
331 | cx25840_write(client, i, lcr[9 + x]); | ||
332 | } | ||
333 | for (i = 0x431; i <= 0x434; i++) { | ||
334 | cx25840_write(client, i, 0); | ||
335 | } | ||
253 | } | 336 | } |
254 | 337 | ||
255 | cx25840_write(client, 0x43c, 0x16); | 338 | cx25840_write(client, 0x43c, 0x16); |
@@ -257,7 +340,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | |||
257 | if (is_pal) { | 340 | if (is_pal) { |
258 | cx25840_write(client, 0x474, 0x2a); | 341 | cx25840_write(client, 0x474, 0x2a); |
259 | } else { | 342 | } else { |
260 | cx25840_write(client, 0x474, 0x1a + 6); | 343 | cx25840_write(client, 0x474, 0x22); |
261 | } | 344 | } |
262 | break; | 345 | break; |
263 | } | 346 | } |
@@ -278,7 +361,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | |||
278 | id1 = p[-1]; | 361 | id1 = p[-1]; |
279 | id2 = p[0] & 0xf; | 362 | id2 = p[0] & 0xf; |
280 | l = p[2] & 0x3f; | 363 | l = p[2] & 0x3f; |
281 | l += 5; | 364 | l += state->vbi_line_offset; |
282 | p += 4; | 365 | p += 4; |
283 | 366 | ||
284 | switch (id2) { | 367 | switch (id2) { |
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 630273992a41..91e1c481a164 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -11,6 +11,7 @@ config VIDEO_CX88 | |||
11 | select VIDEO_BUF | 11 | select VIDEO_BUF |
12 | select VIDEO_TUNER | 12 | select VIDEO_TUNER |
13 | select VIDEO_TVEEPROM | 13 | select VIDEO_TVEEPROM |
14 | select VIDEO_CX2341X | ||
14 | select VIDEO_IR | 15 | select VIDEO_IR |
15 | ---help--- | 16 | ---help--- |
16 | This is a video4linux driver for Conexant 2388x based | 17 | This is a video4linux driver for Conexant 2388x based |
@@ -61,6 +62,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS | |||
61 | select DVB_LGDT330X | 62 | select DVB_LGDT330X |
62 | select DVB_NXT200X | 63 | select DVB_NXT200X |
63 | select DVB_CX24123 | 64 | select DVB_CX24123 |
65 | select DVB_ISL6421 | ||
64 | ---help--- | 66 | ---help--- |
65 | This builds cx88-dvb with all currently supported frontend | 67 | This builds cx88-dvb with all currently supported frontend |
66 | demodulators. If you wish to tweak your configuration, and | 68 | demodulators. If you wish to tweak your configuration, and |
@@ -139,6 +141,7 @@ config VIDEO_CX88_DVB_CX24123 | |||
139 | default y | 141 | default y |
140 | depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS | 142 | depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS |
141 | select DVB_CX24123 | 143 | select DVB_CX24123 |
144 | select DVB_ISL6421 | ||
142 | ---help--- | 145 | ---help--- |
143 | This adds DVB-S support for cards based on the | 146 | This adds DVB-S support for cards based on the |
144 | Connexant 2388x chip and the CX24123 demodulator. | 147 | Connexant 2388x chip and the CX24123 demodulator. |
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 320b3d9384ba..2194cbeca33b 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * PCI function #1 of the cx2388x. | 4 | * PCI function #1 of the cx2388x. |
5 | * | 5 | * |
6 | * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org> | 6 | * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org> |
7 | * (c) 2005 Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 7 | * (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org> |
8 | * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org> | 8 | * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org> |
9 | * Based on dummy.c by Jaroslav Kysela <perex@suse.cz> | 9 | * Based on dummy.c by Jaroslav Kysela <perex@suse.cz> |
10 | * | 10 | * |
@@ -111,7 +111,7 @@ MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s)."); | |||
111 | 111 | ||
112 | MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards"); | 112 | MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards"); |
113 | MODULE_AUTHOR("Ricardo Cerqueira"); | 113 | MODULE_AUTHOR("Ricardo Cerqueira"); |
114 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@brturbo.com.br>"); | 114 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); |
115 | MODULE_LICENSE("GPL"); | 115 | MODULE_LICENSE("GPL"); |
116 | MODULE_SUPPORTED_DEVICE("{{Conexant,23881}," | 116 | MODULE_SUPPORTED_DEVICE("{{Conexant,23881}," |
117 | "{{Conexant,23882}," | 117 | "{{Conexant,23882}," |
@@ -696,7 +696,6 @@ static int __devinit snd_cx88_create(struct snd_card *card, | |||
696 | chip->irq = -1; | 696 | chip->irq = -1; |
697 | spin_lock_init(&chip->reg_lock); | 697 | spin_lock_init(&chip->reg_lock); |
698 | 698 | ||
699 | cx88_reset(core); | ||
700 | chip->core = core; | 699 | chip->core = core; |
701 | 700 | ||
702 | /* get irq */ | 701 | /* get irq */ |
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index e100d8ef369a..67fd3302e8f2 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
@@ -30,9 +30,10 @@ | |||
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include <linux/device.h> | 31 | #include <linux/device.h> |
32 | #include <linux/firmware.h> | 32 | #include <linux/firmware.h> |
33 | #include <media/v4l2-common.h> | ||
34 | #include <media/cx2341x.h> | ||
33 | 35 | ||
34 | #include "cx88.h" | 36 | #include "cx88.h" |
35 | #include <media/v4l2-common.h> | ||
36 | 37 | ||
37 | MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards"); | 38 | MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards"); |
38 | MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | 39 | MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); |
@@ -53,7 +54,6 @@ static LIST_HEAD(cx8802_devlist); | |||
53 | 54 | ||
54 | /* ------------------------------------------------------------------ */ | 55 | /* ------------------------------------------------------------------ */ |
55 | 56 | ||
56 | #define BLACKBIRD_FIRM_ENC_FILENAME "blackbird-fw-enc.bin" | ||
57 | #define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024 | 57 | #define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024 |
58 | 58 | ||
59 | /* defines below are from ivtv-driver.h */ | 59 | /* defines below are from ivtv-driver.h */ |
@@ -63,8 +63,6 @@ static LIST_HEAD(cx8802_devlist); | |||
63 | /* Firmware API commands */ | 63 | /* Firmware API commands */ |
64 | #define IVTV_API_STD_TIMEOUT 500 | 64 | #define IVTV_API_STD_TIMEOUT 500 |
65 | 65 | ||
66 | #define BLACKBIRD_API_PING 0x80 | ||
67 | #define BLACKBIRD_API_BEGIN_CAPTURE 0x81 | ||
68 | enum blackbird_capture_type { | 66 | enum blackbird_capture_type { |
69 | BLACKBIRD_MPEG_CAPTURE, | 67 | BLACKBIRD_MPEG_CAPTURE, |
70 | BLACKBIRD_RAW_CAPTURE, | 68 | BLACKBIRD_RAW_CAPTURE, |
@@ -78,205 +76,29 @@ enum blackbird_capture_bits { | |||
78 | BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08, | 76 | BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08, |
79 | BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE = 0x10 | 77 | BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE = 0x10 |
80 | }; | 78 | }; |
81 | #define BLACKBIRD_API_END_CAPTURE 0x82 | ||
82 | enum blackbird_capture_end { | 79 | enum blackbird_capture_end { |
83 | BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */ | 80 | BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */ |
84 | BLACKBIRD_END_NOW, /* stop immediately, no irq */ | 81 | BLACKBIRD_END_NOW, /* stop immediately, no irq */ |
85 | }; | 82 | }; |
86 | #define BLACKBIRD_API_SET_AUDIO_ID 0x89 | ||
87 | #define BLACKBIRD_API_SET_VIDEO_ID 0x8B | ||
88 | #define BLACKBIRD_API_SET_PCR_ID 0x8D | ||
89 | #define BLACKBIRD_API_SET_FRAMERATE 0x8F | ||
90 | enum blackbird_framerate { | 83 | enum blackbird_framerate { |
91 | BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */ | 84 | BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */ |
92 | BLACKBIRD_FRAMERATE_PAL_25 /* PAL: 25fps */ | 85 | BLACKBIRD_FRAMERATE_PAL_25 /* PAL: 25fps */ |
93 | }; | 86 | }; |
94 | #define BLACKBIRD_API_SET_RESOLUTION 0x91 | ||
95 | #define BLACKBIRD_API_SET_VIDEO_BITRATE 0x95 | ||
96 | enum blackbird_video_bitrate_type { | ||
97 | BLACKBIRD_VIDEO_VBR, | ||
98 | BLACKBIRD_VIDEO_CBR | ||
99 | }; | ||
100 | #define BLACKBIRD_PEAK_RATE_DIVISOR 400 | ||
101 | enum blackbird_mux_rate { | ||
102 | BLACKBIRD_MUX_RATE_DEFAULT, | ||
103 | /* dvd mux rate: multiply by 400 to get the actual rate */ | ||
104 | BLACKBIRD_MUX_RATE_DVD = 25200 | ||
105 | }; | ||
106 | #define BLACKBIRD_API_SET_GOP_STRUCTURE 0x97 | ||
107 | #define BLACKBIRD_API_SET_ASPECT_RATIO 0x99 | ||
108 | enum blackbird_aspect_ratio { | ||
109 | BLACKBIRD_ASPECT_RATIO_FORBIDDEN, | ||
110 | BLACKBIRD_ASPECT_RATIO_1_1_SQUARE, | ||
111 | BLACKBIRD_ASPECT_RATIO_4_3, | ||
112 | BLACKBIRD_ASPECT_RATIO_16_9, | ||
113 | BLACKBIRD_ASPECT_RATIO_221_100, | ||
114 | BLACKBIRD_ASPECT_RATIO_RESERVED | ||
115 | }; | ||
116 | #define BLACKBIRD_API_SET_DNR_MODE 0x9B | ||
117 | enum blackbird_dnr_bits { | ||
118 | BLACKBIRD_DNR_BITS_MANUAL, | ||
119 | BLACKBIRD_DNR_BITS_AUTO_SPATIAL, | ||
120 | BLACKBIRD_DNR_BITS_AUTO_TEMPORAL, | ||
121 | BLACKBIRD_DNR_BITS_AUTO | ||
122 | }; | ||
123 | enum blackbird_median_filter { | ||
124 | BLACKBIRD_MEDIAN_FILTER_DISABLED, | ||
125 | BLACKBIRD_MEDIAN_FILTER_HORIZONTAL, | ||
126 | BLACKBIRD_MEDIAN_FILTER_VERTICAL, | ||
127 | BLACKBIRD_MEDIAN_FILTER_HV, | ||
128 | BLACKBIRD_MEDIAN_FILTER_DIAGONAL | ||
129 | }; | ||
130 | #define BLACKBIRD_API_SET_MANUAL_DNR 0x9D | ||
131 | #define BLACKBIRD_API_SET_DNR_MEDIAN 0x9F | ||
132 | #define BLACKBIRD_API_SET_SPATIAL_FILTER 0xA1 | ||
133 | enum blackbird_spatial_filter_luma { | ||
134 | BLACKBIRD_SPATIAL_FILTER_LUMA_DISABLED, | ||
135 | BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ, | ||
136 | BLACKBIRD_SPATIAL_FILTER_LUMA_1D_VERT, | ||
137 | BLACKBIRD_SPATIAL_FILTER_LUMA_2D_HV, /* separable, default */ | ||
138 | BLACKBIRD_SPATIAL_FILTER_LUMA_2D_SYMM /* symmetric non-separable */ | ||
139 | }; | ||
140 | enum blackbird_spatial_filter_chroma { | ||
141 | BLACKBIRD_SPATIAL_FILTER_CHROMA_DISABLED, | ||
142 | BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ /* default */ | ||
143 | }; | ||
144 | #define BLACKBIRD_API_SET_3_2_PULLDOWN 0xB1 | ||
145 | enum blackbird_pulldown { | ||
146 | BLACKBIRD_3_2_PULLDOWN_DISABLED, | ||
147 | BLACKBIRD_3_2_PULLDOWN_ENABLED | ||
148 | }; | ||
149 | #define BLACKBIRD_API_SET_VBI_LINE_NO 0xB7 | ||
150 | enum blackbird_vbi_line_bits { | ||
151 | BLACKBIRD_VBI_LINE_BITS_TOP_FIELD, | ||
152 | BLACKBIRD_VBI_LINE_BITS_BOT_FIELD = (1 << 31), | ||
153 | BLACKBIRD_VBI_LINE_BITS_ALL_LINES = 0xFFFFFFFF | ||
154 | }; | ||
155 | enum blackbird_vbi_line { | ||
156 | BLACKBIRD_VBI_LINE_DISABLED, | ||
157 | BLACKBIRD_VBI_LINE_ENABLED | ||
158 | }; | ||
159 | enum blackbird_vbi_slicing { | ||
160 | BLACKBIRD_VBI_SLICING_NONE, | ||
161 | BLACKBIRD_VBI_SLICING_CLOSED_CAPTION | ||
162 | }; | ||
163 | #define BLACKBIRD_API_SET_STREAM_TYPE 0xB9 | ||
164 | enum blackbird_stream_type { | ||
165 | BLACKBIRD_STREAM_PROGRAM, | ||
166 | BLACKBIRD_STREAM_TRANSPORT, | ||
167 | BLACKBIRD_STREAM_MPEG1, | ||
168 | BLACKBIRD_STREAM_PES_AV, | ||
169 | BLACKBIRD_STREAM_UNKNOWN4, | ||
170 | BLACKBIRD_STREAM_PES_VIDEO, | ||
171 | BLACKBIRD_STREAM_UNKNOWN6, | ||
172 | BLACKBIRD_STREAM_PES_AUDIO, | ||
173 | BLACKBIRD_STREAM_UNKNOWN8, | ||
174 | BLACKBIRD_STREAM_UNKNOWN9, /* audio/pcm ? */ | ||
175 | BLACKBIRD_STREAM_DVD, | ||
176 | BLACKBIRD_STREAM_VCD, | ||
177 | BLACKBIRD_STREAM_UNKNOWN12 /* svcd/xvcd ? */ | ||
178 | }; | ||
179 | #define BLACKBIRD_API_SET_OUTPUT_PORT 0xBB | ||
180 | enum blackbird_stream_port { | 87 | enum blackbird_stream_port { |
181 | BLACKBIRD_OUTPUT_PORT_MEMORY, | 88 | BLACKBIRD_OUTPUT_PORT_MEMORY, |
182 | BLACKBIRD_OUTPUT_PORT_STREAMING, | 89 | BLACKBIRD_OUTPUT_PORT_STREAMING, |
183 | BLACKBIRD_OUTPUT_PORT_SERIAL | 90 | BLACKBIRD_OUTPUT_PORT_SERIAL |
184 | }; | 91 | }; |
185 | #define BLACKBIRD_API_SET_AUDIO_PARAMS 0xBD | ||
186 | enum blackbird_audio_bits_sample_rate { | ||
187 | BLACKBIRD_AUDIO_BITS_44100HZ, | ||
188 | BLACKBIRD_AUDIO_BITS_48000HZ, | ||
189 | BLACKBIRD_AUDIO_BITS_32000HZ, | ||
190 | BLACKBIRD_AUDIO_BITS_RESERVED_HZ, | ||
191 | }; | ||
192 | enum blackbird_audio_bits_encoding { | ||
193 | BLACKBIRD_AUDIO_BITS_LAYER_1 = 0x1 << 2, | ||
194 | BLACKBIRD_AUDIO_BITS_LAYER_2 = 0x2 << 2, | ||
195 | }; | ||
196 | enum blackbird_audio_bits_bitrate_layer_1 { | ||
197 | BLACKBIRD_AUDIO_BITS_LAYER_1_FREE_FORMAT, | ||
198 | BLACKBIRD_AUDIO_BITS_LAYER_1_32 = 0x01 << 4, | ||
199 | BLACKBIRD_AUDIO_BITS_LAYER_1_64 = 0x02 << 4, | ||
200 | BLACKBIRD_AUDIO_BITS_LAYER_1_96 = 0x03 << 4, | ||
201 | BLACKBIRD_AUDIO_BITS_LAYER_1_128 = 0x04 << 4, | ||
202 | BLACKBIRD_AUDIO_BITS_LAYER_1_160 = 0x05 << 4, | ||
203 | BLACKBIRD_AUDIO_BITS_LAYER_1_192 = 0x06 << 4, | ||
204 | BLACKBIRD_AUDIO_BITS_LAYER_1_224 = 0x07 << 4, | ||
205 | BLACKBIRD_AUDIO_BITS_LAYER_1_256 = 0x08 << 4, | ||
206 | BLACKBIRD_AUDIO_BITS_LAYER_1_288 = 0x09 << 4, | ||
207 | BLACKBIRD_AUDIO_BITS_LAYER_1_320 = 0x0A << 4, | ||
208 | BLACKBIRD_AUDIO_BITS_LAYER_1_352 = 0x0B << 4, | ||
209 | BLACKBIRD_AUDIO_BITS_LAYER_1_384 = 0x0C << 4, | ||
210 | BLACKBIRD_AUDIO_BITS_LAYER_1_416 = 0x0D << 4, | ||
211 | BLACKBIRD_AUDIO_BITS_LAYER_1_448 = 0x0E << 4, | ||
212 | }; | ||
213 | enum blackbird_audio_bits_bitrate_layer_2 { | ||
214 | BLACKBIRD_AUDIO_BITS_LAYER_2_FREE_FORMAT, | ||
215 | BLACKBIRD_AUDIO_BITS_LAYER_2_32 = 0x01 << 4, | ||
216 | BLACKBIRD_AUDIO_BITS_LAYER_2_48 = 0x02 << 4, | ||
217 | BLACKBIRD_AUDIO_BITS_LAYER_2_56 = 0x03 << 4, | ||
218 | BLACKBIRD_AUDIO_BITS_LAYER_2_64 = 0x04 << 4, | ||
219 | BLACKBIRD_AUDIO_BITS_LAYER_2_80 = 0x05 << 4, | ||
220 | BLACKBIRD_AUDIO_BITS_LAYER_2_96 = 0x06 << 4, | ||
221 | BLACKBIRD_AUDIO_BITS_LAYER_2_112 = 0x07 << 4, | ||
222 | BLACKBIRD_AUDIO_BITS_LAYER_2_128 = 0x08 << 4, | ||
223 | BLACKBIRD_AUDIO_BITS_LAYER_2_160 = 0x09 << 4, | ||
224 | BLACKBIRD_AUDIO_BITS_LAYER_2_192 = 0x0A << 4, | ||
225 | BLACKBIRD_AUDIO_BITS_LAYER_2_224 = 0x0B << 4, | ||
226 | BLACKBIRD_AUDIO_BITS_LAYER_2_256 = 0x0C << 4, | ||
227 | BLACKBIRD_AUDIO_BITS_LAYER_2_320 = 0x0D << 4, | ||
228 | BLACKBIRD_AUDIO_BITS_LAYER_2_384 = 0x0E << 4, | ||
229 | }; | ||
230 | enum blackbird_audio_bits_mode { | ||
231 | BLACKBIRD_AUDIO_BITS_STEREO, | ||
232 | BLACKBIRD_AUDIO_BITS_JOINT_STEREO = 0x1 << 8, | ||
233 | BLACKBIRD_AUDIO_BITS_DUAL = 0x2 << 8, | ||
234 | BLACKBIRD_AUDIO_BITS_MONO = 0x3 << 8, | ||
235 | }; | ||
236 | enum blackbird_audio_bits_mode_extension { | ||
237 | BLACKBIRD_AUDIO_BITS_BOUND_4, | ||
238 | BLACKBIRD_AUDIO_BITS_BOUND_8 = 0x1 << 10, | ||
239 | BLACKBIRD_AUDIO_BITS_BOUND_12 = 0x2 << 10, | ||
240 | BLACKBIRD_AUDIO_BITS_BOUND_16 = 0x3 << 10, | ||
241 | }; | ||
242 | enum blackbird_audio_bits_emphasis { | ||
243 | BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE, | ||
244 | BLACKBIRD_AUDIO_BITS_EMPHASIS_50_15 = 0x1 << 12, | ||
245 | BLACKBIRD_AUDIO_BITS_EMPHASIS_RESERVED = 0x2 << 12, | ||
246 | BLACKBIRD_AUDIO_BITS_EMPHASIS_CCITT_J17 = 0x3 << 12, | ||
247 | }; | ||
248 | enum blackbird_audio_bits_crc { | ||
249 | BLACKBIRD_AUDIO_BITS_CRC_OFF, | ||
250 | BLACKBIRD_AUDIO_BITS_CRC_ON = 0x1 << 14, | ||
251 | }; | ||
252 | enum blackbird_audio_bits_copyright { | ||
253 | BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF, | ||
254 | BLACKBIRD_AUDIO_BITS_COPYRIGHT_ON = 0x1 << 15, | ||
255 | }; | ||
256 | enum blackbird_audio_bits_original { | ||
257 | BLACKBIRD_AUDIO_BITS_COPY, | ||
258 | BLACKBIRD_AUDIO_BITS_ORIGINAL = 0x1 << 16, | ||
259 | }; | ||
260 | #define BLACKBIRD_API_HALT 0xC3 | ||
261 | #define BLACKBIRD_API_GET_VERSION 0xC4 | ||
262 | #define BLACKBIRD_API_SET_GOP_CLOSURE 0xC5 | ||
263 | enum blackbird_gop_closure { | ||
264 | BLACKBIRD_GOP_CLOSURE_OFF, | ||
265 | BLACKBIRD_GOP_CLOSURE_ON, | ||
266 | }; | ||
267 | #define BLACKBIRD_API_DATA_XFER_STATUS 0xC6 | ||
268 | enum blackbird_data_xfer_status { | 92 | enum blackbird_data_xfer_status { |
269 | BLACKBIRD_MORE_BUFFERS_FOLLOW, | 93 | BLACKBIRD_MORE_BUFFERS_FOLLOW, |
270 | BLACKBIRD_LAST_BUFFER, | 94 | BLACKBIRD_LAST_BUFFER, |
271 | }; | 95 | }; |
272 | #define BLACKBIRD_API_PROGRAM_INDEX_INFO 0xC7 | ||
273 | enum blackbird_picture_mask { | 96 | enum blackbird_picture_mask { |
274 | BLACKBIRD_PICTURE_MASK_NONE, | 97 | BLACKBIRD_PICTURE_MASK_NONE, |
275 | BLACKBIRD_PICTURE_MASK_I_FRAMES, | 98 | BLACKBIRD_PICTURE_MASK_I_FRAMES, |
276 | BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3, | 99 | BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3, |
277 | BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7, | 100 | BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7, |
278 | }; | 101 | }; |
279 | #define BLACKBIRD_API_SET_VBI_PARAMS 0xC8 | ||
280 | enum blackbird_vbi_mode_bits { | 102 | enum blackbird_vbi_mode_bits { |
281 | BLACKBIRD_VBI_BITS_SLICED, | 103 | BLACKBIRD_VBI_BITS_SLICED, |
282 | BLACKBIRD_VBI_BITS_RAW, | 104 | BLACKBIRD_VBI_BITS_RAW, |
@@ -288,33 +110,23 @@ enum blackbird_vbi_insertion_bits { | |||
288 | BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1, | 110 | BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1, |
289 | BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1, | 111 | BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1, |
290 | }; | 112 | }; |
291 | #define BLACKBIRD_API_SET_DMA_BLOCK_SIZE 0xC9 | ||
292 | enum blackbird_dma_unit { | 113 | enum blackbird_dma_unit { |
293 | BLACKBIRD_DMA_BYTES, | 114 | BLACKBIRD_DMA_BYTES, |
294 | BLACKBIRD_DMA_FRAMES, | 115 | BLACKBIRD_DMA_FRAMES, |
295 | }; | 116 | }; |
296 | #define BLACKBIRD_API_DMA_TRANSFER_INFO 0xCA | ||
297 | #define BLACKBIRD_API_DMA_TRANSFER_STAT 0xCB | ||
298 | enum blackbird_dma_transfer_status_bits { | 117 | enum blackbird_dma_transfer_status_bits { |
299 | BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01, | 118 | BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01, |
300 | BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04, | 119 | BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04, |
301 | BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10, | 120 | BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10, |
302 | }; | 121 | }; |
303 | #define BLACKBIRD_API_SET_DMA2HOST_ADDR 0xCC | ||
304 | #define BLACKBIRD_API_INIT_VIDEO_INPUT 0xCD | ||
305 | #define BLACKBIRD_API_SET_FRAMESKIP 0xD0 | ||
306 | #define BLACKBIRD_API_PAUSE 0xD2 | ||
307 | enum blackbird_pause { | 122 | enum blackbird_pause { |
308 | BLACKBIRD_PAUSE_ENCODING, | 123 | BLACKBIRD_PAUSE_ENCODING, |
309 | BLACKBIRD_RESUME_ENCODING, | 124 | BLACKBIRD_RESUME_ENCODING, |
310 | }; | 125 | }; |
311 | #define BLACKBIRD_API_REFRESH_INPUT 0xD3 | ||
312 | #define BLACKBIRD_API_SET_COPYRIGHT 0xD4 | ||
313 | enum blackbird_copyright { | 126 | enum blackbird_copyright { |
314 | BLACKBIRD_COPYRIGHT_OFF, | 127 | BLACKBIRD_COPYRIGHT_OFF, |
315 | BLACKBIRD_COPYRIGHT_ON, | 128 | BLACKBIRD_COPYRIGHT_ON, |
316 | }; | 129 | }; |
317 | #define BLACKBIRD_API_SET_NOTIFICATION 0xD5 | ||
318 | enum blackbird_notification_type { | 130 | enum blackbird_notification_type { |
319 | BLACKBIRD_NOTIFICATION_REFRESH, | 131 | BLACKBIRD_NOTIFICATION_REFRESH, |
320 | }; | 132 | }; |
@@ -325,7 +137,6 @@ enum blackbird_notification_status { | |||
325 | enum blackbird_notification_mailbox { | 137 | enum blackbird_notification_mailbox { |
326 | BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1, | 138 | BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1, |
327 | }; | 139 | }; |
328 | #define BLACKBIRD_API_SET_CAPTURE_LINES 0xD6 | ||
329 | enum blackbird_field1_lines { | 140 | enum blackbird_field1_lines { |
330 | BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */ | 141 | BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */ |
331 | BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */ | 142 | BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */ |
@@ -336,12 +147,10 @@ enum blackbird_field2_lines { | |||
336 | BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */ | 147 | BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */ |
337 | BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */ | 148 | BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */ |
338 | }; | 149 | }; |
339 | #define BLACKBIRD_API_SET_CUSTOM_DATA 0xD7 | ||
340 | enum blackbird_custom_data_type { | 150 | enum blackbird_custom_data_type { |
341 | BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, | 151 | BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, |
342 | BLACKBIRD_CUSTOM_PRIVATE_PACKET, | 152 | BLACKBIRD_CUSTOM_PRIVATE_PACKET, |
343 | }; | 153 | }; |
344 | #define BLACKBIRD_API_MUTE_VIDEO 0xD9 | ||
345 | enum blackbird_mute { | 154 | enum blackbird_mute { |
346 | BLACKBIRD_UNMUTE, | 155 | BLACKBIRD_UNMUTE, |
347 | BLACKBIRD_MUTE, | 156 | BLACKBIRD_MUTE, |
@@ -356,7 +165,6 @@ enum blackbird_mute_video_shift { | |||
356 | BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16, | 165 | BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16, |
357 | BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24, | 166 | BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24, |
358 | }; | 167 | }; |
359 | #define BLACKBIRD_API_MUTE_AUDIO 0xDA | ||
360 | 168 | ||
361 | /* Registers */ | 169 | /* Registers */ |
362 | #define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/) | 170 | #define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/) |
@@ -498,15 +306,12 @@ static int register_read(struct cx88_core *core, u32 address, u32 *value) | |||
498 | 306 | ||
499 | /* ------------------------------------------------------------------ */ | 307 | /* ------------------------------------------------------------------ */ |
500 | 308 | ||
501 | /* We don't need to call the API often, so using just one mailbox will probably suffice */ | 309 | static int blackbird_mbox_func(void *priv, int command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]) |
502 | static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command, | ||
503 | u32 inputcnt, u32 outputcnt, ...) | ||
504 | { | 310 | { |
311 | struct cx8802_dev *dev = priv; | ||
505 | unsigned long timeout; | 312 | unsigned long timeout; |
506 | u32 value, flag, retval; | 313 | u32 value, flag, retval; |
507 | int i; | 314 | int i; |
508 | va_list args; | ||
509 | va_start(args, outputcnt); | ||
510 | 315 | ||
511 | dprintk(1,"%s: 0x%X\n", __FUNCTION__, command); | 316 | dprintk(1,"%s: 0x%X\n", __FUNCTION__, command); |
512 | 317 | ||
@@ -530,12 +335,11 @@ static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command, | |||
530 | /* write command + args + fill remaining with zeros */ | 335 | /* write command + args + fill remaining with zeros */ |
531 | memory_write(dev->core, dev->mailbox + 1, command); /* command code */ | 336 | memory_write(dev->core, dev->mailbox + 1, command); /* command code */ |
532 | memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */ | 337 | memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */ |
533 | for (i = 0; i < inputcnt ; i++) { | 338 | for (i = 0; i < in; i++) { |
534 | value = va_arg(args, int); | 339 | memory_write(dev->core, dev->mailbox + 4 + i, data[i]); |
535 | memory_write(dev->core, dev->mailbox + 4 + i, value); | 340 | dprintk(1, "API Input %d = %d\n", i, data[i]); |
536 | dprintk(1, "API Input %d = %d\n", i, value); | ||
537 | } | 341 | } |
538 | for (; i < 16 ; i++) | 342 | for (; i < CX2341X_MBOX_MAX_DATA; i++) |
539 | memory_write(dev->core, dev->mailbox + 4 + i, 0); | 343 | memory_write(dev->core, dev->mailbox + 4 + i, 0); |
540 | 344 | ||
541 | flag |= 3; /* tell 'em we're done writing */ | 345 | flag |= 3; /* tell 'em we're done writing */ |
@@ -555,12 +359,10 @@ static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command, | |||
555 | } | 359 | } |
556 | 360 | ||
557 | /* read output values */ | 361 | /* read output values */ |
558 | for (i = 0; i < outputcnt ; i++) { | 362 | for (i = 0; i < out; i++) { |
559 | int *vptr = va_arg(args, int *); | 363 | memory_read(dev->core, dev->mailbox + 4 + i, data + i); |
560 | memory_read(dev->core, dev->mailbox + 4 + i, vptr); | 364 | dprintk(1, "API Output %d = %d\n", i, data[i]); |
561 | dprintk(1, "API Output %d = %d\n", i, *vptr); | ||
562 | } | 365 | } |
563 | va_end(args); | ||
564 | 366 | ||
565 | memory_read(dev->core, dev->mailbox + 2, &retval); | 367 | memory_read(dev->core, dev->mailbox + 2, &retval); |
566 | dprintk(1, "API result = %d\n",retval); | 368 | dprintk(1, "API result = %d\n",retval); |
@@ -569,7 +371,29 @@ static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command, | |||
569 | memory_write(dev->core, dev->mailbox, flag); | 371 | memory_write(dev->core, dev->mailbox, flag); |
570 | return retval; | 372 | return retval; |
571 | } | 373 | } |
374 | /* ------------------------------------------------------------------ */ | ||
572 | 375 | ||
376 | /* We don't need to call the API often, so using just one mailbox will probably suffice */ | ||
377 | static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command, | ||
378 | u32 inputcnt, u32 outputcnt, ...) | ||
379 | { | ||
380 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
381 | va_list vargs; | ||
382 | int i, err; | ||
383 | |||
384 | va_start(vargs, outputcnt); | ||
385 | |||
386 | for (i = 0; i < inputcnt; i++) { | ||
387 | data[i] = va_arg(vargs, int); | ||
388 | } | ||
389 | err = blackbird_mbox_func(dev, command, inputcnt, outputcnt, data); | ||
390 | for (i = 0; i < outputcnt; i++) { | ||
391 | int *vptr = va_arg(vargs, int *); | ||
392 | *vptr = data[i]; | ||
393 | } | ||
394 | va_end(vargs); | ||
395 | return err; | ||
396 | } | ||
573 | 397 | ||
574 | static int blackbird_find_mailbox(struct cx8802_dev *dev) | 398 | static int blackbird_find_mailbox(struct cx8802_dev *dev) |
575 | { | 399 | { |
@@ -614,13 +438,13 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) | |||
614 | if (retval < 0) | 438 | if (retval < 0) |
615 | dprintk(0, "Error with register_write\n"); | 439 | dprintk(0, "Error with register_write\n"); |
616 | 440 | ||
617 | retval = request_firmware(&firmware, BLACKBIRD_FIRM_ENC_FILENAME, | 441 | retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME, |
618 | &dev->pci->dev); | 442 | &dev->pci->dev); |
619 | 443 | ||
620 | 444 | ||
621 | if (retval != 0) { | 445 | if (retval != 0) { |
622 | dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n", | 446 | dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n", |
623 | BLACKBIRD_FIRM_ENC_FILENAME); | 447 | CX2341X_FIRM_ENC_FILENAME); |
624 | dprintk(0, "Please fix your hotplug setup, the board will " | 448 | dprintk(0, "Please fix your hotplug setup, the board will " |
625 | "not work without firmware loaded!\n"); | 449 | "not work without firmware loaded!\n"); |
626 | return -1; | 450 | return -1; |
@@ -686,12 +510,19 @@ DB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | M | |||
686 | *DB: "DirectBurn" | 510 | *DB: "DirectBurn" |
687 | */ | 511 | */ |
688 | 512 | ||
689 | static struct blackbird_dnr default_dnr_params = { | 513 | static void blackbird_codec_settings(struct cx8802_dev *dev) |
690 | .mode = BLACKBIRD_DNR_BITS_MANUAL, | 514 | { |
691 | .type = BLACKBIRD_MEDIAN_FILTER_DISABLED, | 515 | /* assign frame size */ |
692 | .spatial = 0, | 516 | blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, |
693 | .temporal = 0 | 517 | dev->height, dev->width); |
694 | }; | 518 | |
519 | dev->params.width = dev->width; | ||
520 | dev->params.height = dev->height; | ||
521 | dev->params.is_50hz = (dev->core->tvnorm->id & V4L2_STD_625_50) != 0; | ||
522 | |||
523 | cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params); | ||
524 | } | ||
525 | |||
695 | static struct v4l2_mpeg_compression default_mpeg_params = { | 526 | static struct v4l2_mpeg_compression default_mpeg_params = { |
696 | .st_type = V4L2_MPEG_PS_2, | 527 | .st_type = V4L2_MPEG_PS_2, |
697 | .st_bitrate = { | 528 | .st_bitrate = { |
@@ -712,7 +543,7 @@ static struct v4l2_mpeg_compression default_mpeg_params = { | |||
712 | .target = 224, | 543 | .target = 224, |
713 | .max = 224 | 544 | .max = 224 |
714 | }, | 545 | }, |
715 | .au_sample_rate = 44100, | 546 | .au_sample_rate = 48000, |
716 | .au_pesid = 0, | 547 | .au_pesid = 0, |
717 | .vi_type = V4L2_MPEG_VI_2, | 548 | .vi_type = V4L2_MPEG_VI_2, |
718 | .vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3, | 549 | .vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3, |
@@ -723,524 +554,13 @@ static struct v4l2_mpeg_compression default_mpeg_params = { | |||
723 | .max = 6000 | 554 | .max = 6000 |
724 | }, | 555 | }, |
725 | .vi_frame_rate = 25, | 556 | .vi_frame_rate = 25, |
726 | .vi_frames_per_gop = 15, | 557 | .vi_frames_per_gop = 12, |
727 | .vi_bframes_count = 2, | 558 | .vi_bframes_count = 2, |
728 | .vi_pesid = 0, | 559 | .vi_pesid = 0, |
729 | .closed_gops = 0, | 560 | .closed_gops = 1, |
730 | .pulldown = 0 | 561 | .pulldown = 0 |
731 | }; | 562 | }; |
732 | 563 | ||
733 | static enum blackbird_stream_type mpeg_stream_types[] = { | ||
734 | [V4L2_MPEG_SS_1] = BLACKBIRD_STREAM_MPEG1, | ||
735 | [V4L2_MPEG_PS_2] = BLACKBIRD_STREAM_PROGRAM, | ||
736 | [V4L2_MPEG_TS_2] = BLACKBIRD_STREAM_TRANSPORT, | ||
737 | [V4L2_MPEG_PS_DVD] = BLACKBIRD_STREAM_DVD, | ||
738 | }; | ||
739 | static enum blackbird_aspect_ratio mpeg_stream_ratios[] = { | ||
740 | [V4L2_MPEG_ASPECT_SQUARE] = BLACKBIRD_ASPECT_RATIO_1_1_SQUARE, | ||
741 | [V4L2_MPEG_ASPECT_4_3] = BLACKBIRD_ASPECT_RATIO_4_3, | ||
742 | [V4L2_MPEG_ASPECT_16_9] = BLACKBIRD_ASPECT_RATIO_16_9, | ||
743 | [V4L2_MPEG_ASPECT_1_221] = BLACKBIRD_ASPECT_RATIO_221_100, | ||
744 | }; | ||
745 | static enum blackbird_video_bitrate_type mpeg_video_bitrates[] = { | ||
746 | [V4L2_BITRATE_NONE] = BLACKBIRD_VIDEO_CBR, | ||
747 | [V4L2_BITRATE_CBR] = BLACKBIRD_VIDEO_CBR, | ||
748 | [V4L2_BITRATE_VBR] = BLACKBIRD_VIDEO_VBR, | ||
749 | }; | ||
750 | /* find the best layer I/II bitrate to fit a given numeric value */ | ||
751 | struct bitrate_bits { | ||
752 | u32 bits; /* layer bits for the best fit */ | ||
753 | u32 rate; /* actual numeric value for the layer best fit */ | ||
754 | }; | ||
755 | struct bitrate_approximation { | ||
756 | u32 target; /* numeric value of the rate we want */ | ||
757 | struct bitrate_bits layer[2]; | ||
758 | }; | ||
759 | static struct bitrate_approximation mpeg_audio_bitrates[] = { | ||
760 | /* target layer[0].bits layer[0].rate layer[1].bits layer[1].rate */ | ||
761 | { 0, { { 0, 0, }, { 0, 0, }, }, }, | ||
762 | { 32, { { BLACKBIRD_AUDIO_BITS_LAYER_1_32 , 32, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_32 , 32, }, }, }, | ||
763 | { 48, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 , 64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_48 , 48, }, }, }, | ||
764 | { 56, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 , 64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_56 , 56, }, }, }, | ||
765 | { 64, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 , 64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_64 , 64, }, }, }, | ||
766 | { 80, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 , 96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_80 , 80, }, }, }, | ||
767 | { 96, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 , 96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_96 , 96, }, }, }, | ||
768 | { 112, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_112, 112, }, }, }, | ||
769 | { 128, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_128, 128, }, }, }, | ||
770 | { 160, { { BLACKBIRD_AUDIO_BITS_LAYER_1_160, 160, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_160, 160, }, }, }, | ||
771 | { 192, { { BLACKBIRD_AUDIO_BITS_LAYER_1_192, 192, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_192, 192, }, }, }, | ||
772 | { 224, { { BLACKBIRD_AUDIO_BITS_LAYER_1_224, 224, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_224, 224, }, }, }, | ||
773 | { 256, { { BLACKBIRD_AUDIO_BITS_LAYER_1_256, 256, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_256, 256, }, }, }, | ||
774 | { 288, { { BLACKBIRD_AUDIO_BITS_LAYER_1_288, 288, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, }, | ||
775 | { 320, { { BLACKBIRD_AUDIO_BITS_LAYER_1_320, 320, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, }, | ||
776 | { 352, { { BLACKBIRD_AUDIO_BITS_LAYER_1_352, 352, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, | ||
777 | { 384, { { BLACKBIRD_AUDIO_BITS_LAYER_1_384, 384, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, | ||
778 | { 416, { { BLACKBIRD_AUDIO_BITS_LAYER_1_416, 416, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, | ||
779 | { 448, { { BLACKBIRD_AUDIO_BITS_LAYER_1_448, 448, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, | ||
780 | }; | ||
781 | static const int BITRATES_SIZE = ARRAY_SIZE(mpeg_audio_bitrates); | ||
782 | |||
783 | static void blackbird_set_default_params(struct cx8802_dev *dev) | ||
784 | { | ||
785 | struct v4l2_mpeg_compression *params = &dev->params; | ||
786 | u32 au_params; | ||
787 | |||
788 | /* assign stream type */ | ||
789 | if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) ) | ||
790 | params->st_type = V4L2_MPEG_PS_2; | ||
791 | if( params->st_type == V4L2_MPEG_SS_1 ) | ||
792 | params->vi_type = V4L2_MPEG_VI_1; | ||
793 | else | ||
794 | params->vi_type = V4L2_MPEG_VI_2; | ||
795 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]); | ||
796 | |||
797 | /* assign framerate */ | ||
798 | if( params->vi_frame_rate <= 25 ) | ||
799 | { | ||
800 | params->vi_frame_rate = 25; | ||
801 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25); | ||
802 | } | ||
803 | else | ||
804 | { | ||
805 | params->vi_frame_rate = 30; | ||
806 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30); | ||
807 | } | ||
808 | |||
809 | /* assign aspect ratio */ | ||
810 | if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) ) | ||
811 | params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3; | ||
812 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]); | ||
813 | |||
814 | /* assign gop properties */ | ||
815 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1); | ||
816 | |||
817 | /* assign gop closure */ | ||
818 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, params->closed_gops); | ||
819 | |||
820 | /* assign 3 2 pulldown */ | ||
821 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, params->pulldown); | ||
822 | |||
823 | /* make sure the params are within bounds */ | ||
824 | if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) | ||
825 | params->vi_bitrate.mode = V4L2_BITRATE_NONE; | ||
826 | if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) | ||
827 | params->vi_bitrate.mode = V4L2_BITRATE_NONE; | ||
828 | if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) | ||
829 | params->au_bitrate.mode = V4L2_BITRATE_NONE; | ||
830 | |||
831 | /* assign audio properties */ | ||
832 | /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ | ||
833 | au_params = BLACKBIRD_AUDIO_BITS_STEREO | | ||
834 | /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */ | ||
835 | BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE | | ||
836 | BLACKBIRD_AUDIO_BITS_CRC_OFF | | ||
837 | BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF | | ||
838 | BLACKBIRD_AUDIO_BITS_COPY | | ||
839 | 0; | ||
840 | if( params->au_sample_rate <= 32000 ) | ||
841 | { | ||
842 | params->au_sample_rate = 32000; | ||
843 | au_params |= BLACKBIRD_AUDIO_BITS_32000HZ; | ||
844 | } | ||
845 | else if( params->au_sample_rate <= 44100 ) | ||
846 | { | ||
847 | params->au_sample_rate = 44100; | ||
848 | au_params |= BLACKBIRD_AUDIO_BITS_44100HZ; | ||
849 | } | ||
850 | else | ||
851 | { | ||
852 | params->au_sample_rate = 48000; | ||
853 | au_params |= BLACKBIRD_AUDIO_BITS_48000HZ; | ||
854 | } | ||
855 | if( params->au_type == V4L2_MPEG_AU_2_I ) | ||
856 | { | ||
857 | au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1; | ||
858 | } | ||
859 | else | ||
860 | { | ||
861 | /* TODO: try to handle the other formats more gracefully */ | ||
862 | params->au_type = V4L2_MPEG_AU_2_II; | ||
863 | au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2; | ||
864 | } | ||
865 | if( params->au_bitrate.mode ) | ||
866 | { | ||
867 | int layer; | ||
868 | |||
869 | if( params->au_bitrate.mode == V4L2_BITRATE_CBR ) | ||
870 | params->au_bitrate.max = params->vi_bitrate.target; | ||
871 | else | ||
872 | params->au_bitrate.target = params->vi_bitrate.max; | ||
873 | |||
874 | layer = params->au_type; | ||
875 | if( params->au_bitrate.target == 0 ) | ||
876 | { | ||
877 | /* TODO: use the minimum possible bitrate instead of 0 ? */ | ||
878 | au_params |= 0; | ||
879 | } | ||
880 | else if( params->au_bitrate.target >= | ||
881 | mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) | ||
882 | { | ||
883 | /* clamp the bitrate to the max supported by the standard */ | ||
884 | params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; | ||
885 | params->au_bitrate.max = params->au_bitrate.target; | ||
886 | au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits; | ||
887 | } | ||
888 | else | ||
889 | { | ||
890 | /* round up to the nearest supported bitrate */ | ||
891 | int i; | ||
892 | for(i = 1; i < BITRATES_SIZE; i++) | ||
893 | { | ||
894 | if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate && | ||
895 | params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate ) | ||
896 | { | ||
897 | params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate; | ||
898 | params->au_bitrate.max = params->au_bitrate.target; | ||
899 | au_params |= mpeg_audio_bitrates[i].layer[layer].bits; | ||
900 | break; | ||
901 | } | ||
902 | } | ||
903 | } | ||
904 | } | ||
905 | else | ||
906 | { | ||
907 | /* TODO: ??? */ | ||
908 | params->au_bitrate.target = params->au_bitrate.max = 0; | ||
909 | au_params |= 0; | ||
910 | } | ||
911 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, au_params ); | ||
912 | |||
913 | /* assign bitrates */ | ||
914 | if( params->vi_bitrate.mode ) | ||
915 | { | ||
916 | /* bitrate is set, let's figure out the cbr/vbr mess */ | ||
917 | if( params->vi_bitrate.max < params->vi_bitrate.target ) | ||
918 | { | ||
919 | if( params->vi_bitrate.mode == V4L2_BITRATE_CBR ) | ||
920 | params->vi_bitrate.max = params->vi_bitrate.target; | ||
921 | else | ||
922 | params->vi_bitrate.target = params->vi_bitrate.max; | ||
923 | } | ||
924 | } | ||
925 | else | ||
926 | { | ||
927 | if( params->st_bitrate.max < params->st_bitrate.target ) | ||
928 | { | ||
929 | if( params->st_bitrate.mode == V4L2_BITRATE_VBR ) | ||
930 | params->st_bitrate.target = params->st_bitrate.max; | ||
931 | else | ||
932 | params->st_bitrate.max = params->st_bitrate.target; | ||
933 | } | ||
934 | /* calculate vi_bitrate = st_bitrate - au_bitrate */ | ||
935 | params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max; | ||
936 | params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target; | ||
937 | } | ||
938 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 4, 0, | ||
939 | mpeg_video_bitrates[params->vi_bitrate.mode], | ||
940 | params->vi_bitrate.target * 1000, /* kbps -> bps */ | ||
941 | params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */ | ||
942 | BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */ | ||
943 | |||
944 | /* TODO: implement the stream ID stuff: | ||
945 | ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, | ||
946 | ps_size, au_pesid, vi_pesid | ||
947 | */ | ||
948 | } | ||
949 | #define CHECK_PARAM( name ) ( dev->params.name != params->name ) | ||
950 | #define IF_PARAM( name ) if( CHECK_PARAM( name ) ) | ||
951 | #define UPDATE_PARAM( name ) dev->params.name = params->name | ||
952 | void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression *params) | ||
953 | { | ||
954 | u32 au_params; | ||
955 | |||
956 | /* assign stream type */ | ||
957 | if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) ) | ||
958 | params->st_type = V4L2_MPEG_PS_2; | ||
959 | if( params->st_type == V4L2_MPEG_SS_1 ) | ||
960 | params->vi_type = V4L2_MPEG_VI_1; | ||
961 | else | ||
962 | params->vi_type = V4L2_MPEG_VI_2; | ||
963 | if( CHECK_PARAM( st_type ) || CHECK_PARAM( vi_type ) ) | ||
964 | { | ||
965 | UPDATE_PARAM( st_type ); | ||
966 | UPDATE_PARAM( vi_type ); | ||
967 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]); | ||
968 | } | ||
969 | |||
970 | /* assign framerate */ | ||
971 | if( params->vi_frame_rate <= 25 ) | ||
972 | params->vi_frame_rate = 25; | ||
973 | else | ||
974 | params->vi_frame_rate = 30; | ||
975 | IF_PARAM( vi_frame_rate ) | ||
976 | { | ||
977 | UPDATE_PARAM( vi_frame_rate ); | ||
978 | if( params->vi_frame_rate == 25 ) | ||
979 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25); | ||
980 | else | ||
981 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30); | ||
982 | } | ||
983 | |||
984 | /* assign aspect ratio */ | ||
985 | if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) ) | ||
986 | params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3; | ||
987 | IF_PARAM( vi_aspect_ratio ) | ||
988 | { | ||
989 | UPDATE_PARAM( vi_aspect_ratio ); | ||
990 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]); | ||
991 | } | ||
992 | |||
993 | /* assign gop properties */ | ||
994 | if( CHECK_PARAM( vi_frames_per_gop ) || CHECK_PARAM( vi_bframes_count ) ) | ||
995 | { | ||
996 | UPDATE_PARAM( vi_frames_per_gop ); | ||
997 | UPDATE_PARAM( vi_bframes_count ); | ||
998 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1); | ||
999 | } | ||
1000 | |||
1001 | /* assign gop closure */ | ||
1002 | IF_PARAM( closed_gops ) | ||
1003 | { | ||
1004 | UPDATE_PARAM( closed_gops ); | ||
1005 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, params->closed_gops); | ||
1006 | } | ||
1007 | |||
1008 | /* assign 3 2 pulldown */ | ||
1009 | IF_PARAM( pulldown ) | ||
1010 | { | ||
1011 | UPDATE_PARAM( pulldown ); | ||
1012 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, params->pulldown); | ||
1013 | } | ||
1014 | |||
1015 | /* make sure the params are within bounds */ | ||
1016 | if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) | ||
1017 | params->vi_bitrate.mode = V4L2_BITRATE_NONE; | ||
1018 | if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) | ||
1019 | params->vi_bitrate.mode = V4L2_BITRATE_NONE; | ||
1020 | if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) | ||
1021 | params->au_bitrate.mode = V4L2_BITRATE_NONE; | ||
1022 | |||
1023 | /* assign audio properties */ | ||
1024 | /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ | ||
1025 | au_params = BLACKBIRD_AUDIO_BITS_STEREO | | ||
1026 | /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */ | ||
1027 | BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE | | ||
1028 | BLACKBIRD_AUDIO_BITS_CRC_OFF | | ||
1029 | BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF | | ||
1030 | BLACKBIRD_AUDIO_BITS_COPY | | ||
1031 | 0; | ||
1032 | if( params->au_sample_rate < 32000 ) | ||
1033 | { | ||
1034 | params->au_sample_rate = 32000; | ||
1035 | au_params |= BLACKBIRD_AUDIO_BITS_32000HZ; | ||
1036 | } | ||
1037 | else if( params->au_sample_rate < 44100 ) | ||
1038 | { | ||
1039 | params->au_sample_rate = 44100; | ||
1040 | au_params |= BLACKBIRD_AUDIO_BITS_44100HZ; | ||
1041 | } | ||
1042 | else | ||
1043 | { | ||
1044 | params->au_sample_rate = 48000; | ||
1045 | au_params |= BLACKBIRD_AUDIO_BITS_48000HZ; | ||
1046 | } | ||
1047 | if( params->au_type == V4L2_MPEG_AU_2_I ) | ||
1048 | { | ||
1049 | au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1; | ||
1050 | } | ||
1051 | else | ||
1052 | { | ||
1053 | /* TODO: try to handle the other formats more gracefully */ | ||
1054 | params->au_type = V4L2_MPEG_AU_2_II; | ||
1055 | au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2; | ||
1056 | } | ||
1057 | if( params->au_bitrate.mode ) | ||
1058 | { | ||
1059 | int layer; | ||
1060 | |||
1061 | if( params->au_bitrate.mode == V4L2_BITRATE_CBR ) | ||
1062 | params->au_bitrate.max = params->vi_bitrate.target; | ||
1063 | else | ||
1064 | params->au_bitrate.target = params->vi_bitrate.max; | ||
1065 | |||
1066 | layer = params->au_type; | ||
1067 | if( params->au_bitrate.target == 0 ) | ||
1068 | { | ||
1069 | /* TODO: use the minimum possible bitrate instead of 0 ? */ | ||
1070 | au_params |= 0; | ||
1071 | } | ||
1072 | else if( params->au_bitrate.target >= | ||
1073 | mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) | ||
1074 | { | ||
1075 | /* clamp the bitrate to the max supported by the standard */ | ||
1076 | params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; | ||
1077 | params->au_bitrate.max = params->au_bitrate.target; | ||
1078 | au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits; | ||
1079 | } | ||
1080 | else | ||
1081 | { | ||
1082 | /* round up to the nearest supported bitrate */ | ||
1083 | int i; | ||
1084 | for(i = 1; i < BITRATES_SIZE; i++) | ||
1085 | { | ||
1086 | if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate && | ||
1087 | params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate ) | ||
1088 | { | ||
1089 | params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate; | ||
1090 | params->au_bitrate.max = params->au_bitrate.target; | ||
1091 | au_params |= mpeg_audio_bitrates[i].layer[layer].bits; | ||
1092 | break; | ||
1093 | } | ||
1094 | } | ||
1095 | } | ||
1096 | } | ||
1097 | else | ||
1098 | { | ||
1099 | /* TODO: ??? */ | ||
1100 | params->au_bitrate.target = params->au_bitrate.max = 0; | ||
1101 | au_params |= 0; | ||
1102 | } | ||
1103 | if( CHECK_PARAM( au_type ) || CHECK_PARAM( au_sample_rate ) | ||
1104 | || CHECK_PARAM( au_bitrate.mode ) || CHECK_PARAM( au_bitrate.max ) | ||
1105 | || CHECK_PARAM( au_bitrate.target ) | ||
1106 | ) | ||
1107 | { | ||
1108 | UPDATE_PARAM( au_type ); | ||
1109 | UPDATE_PARAM( au_sample_rate ); | ||
1110 | UPDATE_PARAM( au_bitrate ); | ||
1111 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, au_params ); | ||
1112 | } | ||
1113 | |||
1114 | /* assign bitrates */ | ||
1115 | if( params->vi_bitrate.mode ) | ||
1116 | { | ||
1117 | /* bitrate is set, let's figure out the cbr/vbr mess */ | ||
1118 | if( params->vi_bitrate.max < params->vi_bitrate.target ) | ||
1119 | { | ||
1120 | if( params->vi_bitrate.mode == V4L2_BITRATE_CBR ) | ||
1121 | params->vi_bitrate.max = params->vi_bitrate.target; | ||
1122 | else | ||
1123 | params->vi_bitrate.target = params->vi_bitrate.max; | ||
1124 | } | ||
1125 | } | ||
1126 | else | ||
1127 | { | ||
1128 | if( params->st_bitrate.max < params->st_bitrate.target ) | ||
1129 | { | ||
1130 | if( params->st_bitrate.mode == V4L2_BITRATE_VBR ) | ||
1131 | params->st_bitrate.target = params->st_bitrate.max; | ||
1132 | else | ||
1133 | params->st_bitrate.max = params->st_bitrate.target; | ||
1134 | } | ||
1135 | /* calculate vi_bitrate = st_bitrate - au_bitrate */ | ||
1136 | params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max; | ||
1137 | params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target; | ||
1138 | } | ||
1139 | UPDATE_PARAM( st_bitrate ); | ||
1140 | if( CHECK_PARAM( vi_bitrate.mode ) || CHECK_PARAM( vi_bitrate.max ) | ||
1141 | || CHECK_PARAM( vi_bitrate.target ) | ||
1142 | ) | ||
1143 | { | ||
1144 | UPDATE_PARAM( vi_bitrate ); | ||
1145 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 4, 0, | ||
1146 | mpeg_video_bitrates[params->vi_bitrate.mode], | ||
1147 | params->vi_bitrate.target * 1000, /* kbps -> bps */ | ||
1148 | params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */ | ||
1149 | BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */ | ||
1150 | } | ||
1151 | |||
1152 | /* TODO: implement the stream ID stuff: | ||
1153 | ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, | ||
1154 | ps_size, au_pesid, vi_pesid | ||
1155 | */ | ||
1156 | UPDATE_PARAM( ts_pid_pmt ); | ||
1157 | UPDATE_PARAM( ts_pid_audio ); | ||
1158 | UPDATE_PARAM( ts_pid_video ); | ||
1159 | UPDATE_PARAM( ts_pid_pcr ); | ||
1160 | UPDATE_PARAM( ps_size ); | ||
1161 | UPDATE_PARAM( au_pesid ); | ||
1162 | UPDATE_PARAM( vi_pesid ); | ||
1163 | } | ||
1164 | |||
1165 | static void blackbird_set_default_dnr_params(struct cx8802_dev *dev) | ||
1166 | { | ||
1167 | /* assign dnr filter mode */ | ||
1168 | if( dev->dnr_params.mode > BLACKBIRD_DNR_BITS_AUTO ) | ||
1169 | dev->dnr_params.mode = BLACKBIRD_DNR_BITS_MANUAL; | ||
1170 | if( dev->dnr_params.type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL ) | ||
1171 | dev->dnr_params.type = BLACKBIRD_MEDIAN_FILTER_DISABLED; | ||
1172 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0, | ||
1173 | dev->dnr_params.mode, | ||
1174 | dev->dnr_params.type | ||
1175 | ); | ||
1176 | |||
1177 | /* assign dnr filter props*/ | ||
1178 | if( dev->dnr_params.spatial > 15 ) | ||
1179 | dev->dnr_params.spatial = 15; | ||
1180 | if( dev->dnr_params.temporal > 31 ) | ||
1181 | dev->dnr_params.temporal = 31; | ||
1182 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, | ||
1183 | dev->dnr_params.spatial, | ||
1184 | dev->dnr_params.temporal | ||
1185 | ); | ||
1186 | } | ||
1187 | #define CHECK_DNR_PARAM( name ) ( dev->dnr_params.name != dnr_params->name ) | ||
1188 | #define UPDATE_DNR_PARAM( name ) dev->dnr_params.name = dnr_params->name | ||
1189 | void blackbird_set_dnr_params(struct cx8802_dev *dev, struct blackbird_dnr* dnr_params) | ||
1190 | { | ||
1191 | /* assign dnr filter mode */ | ||
1192 | /* clamp values */ | ||
1193 | if( dnr_params->mode > BLACKBIRD_DNR_BITS_AUTO ) | ||
1194 | dnr_params->mode = BLACKBIRD_DNR_BITS_MANUAL; | ||
1195 | if( dnr_params->type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL ) | ||
1196 | dnr_params->type = BLACKBIRD_MEDIAN_FILTER_DISABLED; | ||
1197 | /* check if the params actually changed */ | ||
1198 | if( CHECK_DNR_PARAM( mode ) || CHECK_DNR_PARAM( type ) ) | ||
1199 | { | ||
1200 | UPDATE_DNR_PARAM( mode ); | ||
1201 | UPDATE_DNR_PARAM( type ); | ||
1202 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0, dnr_params->mode, dnr_params->type); | ||
1203 | } | ||
1204 | |||
1205 | /* assign dnr filter props*/ | ||
1206 | if( dnr_params->spatial > 15 ) | ||
1207 | dnr_params->spatial = 15; | ||
1208 | if( dnr_params->temporal > 31 ) | ||
1209 | dnr_params->temporal = 31; | ||
1210 | if( CHECK_DNR_PARAM( spatial ) || CHECK_DNR_PARAM( temporal ) ) | ||
1211 | { | ||
1212 | UPDATE_DNR_PARAM( spatial ); | ||
1213 | UPDATE_DNR_PARAM( temporal ); | ||
1214 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, dnr_params->spatial, dnr_params->temporal); | ||
1215 | } | ||
1216 | } | ||
1217 | |||
1218 | static void blackbird_codec_settings(struct cx8802_dev *dev) | ||
1219 | { | ||
1220 | |||
1221 | /* assign output port */ | ||
1222 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */ | ||
1223 | |||
1224 | /* assign frame size */ | ||
1225 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_RESOLUTION, 2, 0, | ||
1226 | dev->height, dev->width); | ||
1227 | |||
1228 | /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */ | ||
1229 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MEDIAN, 4, 0, 0, 255, 0, 255); | ||
1230 | |||
1231 | /* assign spatial filter type: luma_t: horiz_only, chroma_t: horiz_only */ | ||
1232 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_SPATIAL_FILTER, 2, 0, | ||
1233 | BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ, | ||
1234 | BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ | ||
1235 | ); | ||
1236 | |||
1237 | /* assign frame drop rate */ | ||
1238 | /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); */ | ||
1239 | |||
1240 | blackbird_set_default_params(dev); | ||
1241 | blackbird_set_default_dnr_params(dev); | ||
1242 | } | ||
1243 | |||
1244 | static int blackbird_initialize_codec(struct cx8802_dev *dev) | 564 | static int blackbird_initialize_codec(struct cx8802_dev *dev) |
1245 | { | 565 | { |
1246 | struct cx88_core *core = dev->core; | 566 | struct cx88_core *core = dev->core; |
@@ -1248,7 +568,7 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) | |||
1248 | int retval; | 568 | int retval; |
1249 | 569 | ||
1250 | dprintk(1,"Initialize codec\n"); | 570 | dprintk(1,"Initialize codec\n"); |
1251 | retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */ | 571 | retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ |
1252 | if (retval < 0) { | 572 | if (retval < 0) { |
1253 | /* ping was not successful, reset and upload firmware */ | 573 | /* ping was not successful, reset and upload firmware */ |
1254 | cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ | 574 | cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ |
@@ -1263,13 +583,13 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) | |||
1263 | if (dev->mailbox < 0) | 583 | if (dev->mailbox < 0) |
1264 | return -1; | 584 | return -1; |
1265 | 585 | ||
1266 | retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */ | 586 | retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ |
1267 | if (retval < 0) { | 587 | if (retval < 0) { |
1268 | dprintk(0, "ERROR: Firmware ping failed!\n"); | 588 | dprintk(0, "ERROR: Firmware ping failed!\n"); |
1269 | return -1; | 589 | return -1; |
1270 | } | 590 | } |
1271 | 591 | ||
1272 | retval = blackbird_api_cmd(dev, BLACKBIRD_API_GET_VERSION, 0, 1, &version); | 592 | retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version); |
1273 | if (retval < 0) { | 593 | if (retval < 0) { |
1274 | dprintk(0, "ERROR: Firmware get encoder version failed!\n"); | 594 | dprintk(0, "ERROR: Firmware get encoder version failed!\n"); |
1275 | return -1; | 595 | return -1; |
@@ -1289,35 +609,35 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) | |||
1289 | /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef); | 609 | /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef); |
1290 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0); | 610 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0); |
1291 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */ | 611 | blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */ |
1292 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_CAPTURE_LINES, 2, 0, | 612 | blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, |
1293 | BLACKBIRD_FIELD1_SAA7115, | 613 | BLACKBIRD_FIELD1_SAA7115, |
1294 | BLACKBIRD_FIELD1_SAA7115 | 614 | BLACKBIRD_FIELD2_SAA7115 |
1295 | ); | 615 | ); |
1296 | 616 | ||
1297 | /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */ | 617 | /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */ |
1298 | blackbird_api_cmd(dev, BLACKBIRD_API_SET_CUSTOM_DATA, 12, 0, | 618 | blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0, |
1299 | BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, | 619 | BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, |
1300 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | 620 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); |
1301 | 621 | ||
1302 | /* initialize the video input */ | 622 | /* initialize the video input */ |
1303 | blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0); | 623 | blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); |
1304 | 624 | ||
1305 | msleep(1); | 625 | msleep(1); |
1306 | 626 | ||
1307 | blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE); | 627 | blackbird_api_cmd(dev, CX2341X_ENC_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE); |
1308 | msleep(1); | 628 | msleep(1); |
1309 | blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE); | 629 | blackbird_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE); |
1310 | msleep(1); | 630 | msleep(1); |
1311 | 631 | ||
1312 | /* start capturing to the host interface */ | 632 | /* start capturing to the host interface */ |
1313 | /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); */ | 633 | /* blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, 0, 0x13); */ |
1314 | blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, | 634 | blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, |
1315 | BLACKBIRD_MPEG_CAPTURE, | 635 | BLACKBIRD_MPEG_CAPTURE, |
1316 | BLACKBIRD_RAW_BITS_NONE | 636 | BLACKBIRD_RAW_BITS_NONE |
1317 | ); | 637 | ); |
1318 | msleep(10); | 638 | msleep(10); |
1319 | 639 | ||
1320 | blackbird_api_cmd(dev, BLACKBIRD_API_REFRESH_INPUT, 0,0); | 640 | blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0,0); |
1321 | return 0; | 641 | return 0; |
1322 | } | 642 | } |
1323 | 643 | ||
@@ -1485,14 +805,52 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, | |||
1485 | { | 805 | { |
1486 | struct v4l2_mpeg_compression *f = arg; | 806 | struct v4l2_mpeg_compression *f = arg; |
1487 | 807 | ||
1488 | memcpy(f,&dev->params,sizeof(*f)); | 808 | printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. " |
809 | "Replace with VIDIOC_G_EXT_CTRLS!"); | ||
810 | memcpy(f,&default_mpeg_params,sizeof(*f)); | ||
1489 | return 0; | 811 | return 0; |
1490 | } | 812 | } |
1491 | case VIDIOC_S_MPEGCOMP: | 813 | case VIDIOC_S_MPEGCOMP: |
814 | printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. " | ||
815 | "Replace with VIDIOC_S_EXT_CTRLS!"); | ||
816 | return 0; | ||
817 | case VIDIOC_G_EXT_CTRLS: | ||
1492 | { | 818 | { |
1493 | struct v4l2_mpeg_compression *f = arg; | 819 | struct v4l2_ext_controls *f = arg; |
1494 | 820 | ||
1495 | blackbird_set_params(dev, f); | 821 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
822 | return -EINVAL; | ||
823 | return cx2341x_ext_ctrls(&dev->params, f, cmd); | ||
824 | } | ||
825 | case VIDIOC_S_EXT_CTRLS: | ||
826 | case VIDIOC_TRY_EXT_CTRLS: | ||
827 | { | ||
828 | struct v4l2_ext_controls *f = arg; | ||
829 | struct cx2341x_mpeg_params p; | ||
830 | int err; | ||
831 | |||
832 | if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) | ||
833 | return -EINVAL; | ||
834 | p = dev->params; | ||
835 | err = cx2341x_ext_ctrls(&p, f, cmd); | ||
836 | if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) { | ||
837 | err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p); | ||
838 | dev->params = p; | ||
839 | } | ||
840 | return err; | ||
841 | } | ||
842 | case VIDIOC_S_FREQUENCY: | ||
843 | { | ||
844 | blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, | ||
845 | BLACKBIRD_END_NOW, | ||
846 | BLACKBIRD_MPEG_CAPTURE, | ||
847 | BLACKBIRD_RAW_BITS_NONE); | ||
848 | |||
849 | cx88_do_ioctl( inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook ); | ||
850 | |||
851 | blackbird_initialize_codec(dev); | ||
852 | cx88_set_scale(dev->core, dev->width, dev->height, | ||
853 | fh->mpegq.field); | ||
1496 | return 0; | 854 | return 0; |
1497 | } | 855 | } |
1498 | 856 | ||
@@ -1562,13 +920,14 @@ static int mpeg_release(struct inode *inode, struct file *file) | |||
1562 | { | 920 | { |
1563 | struct cx8802_fh *fh = file->private_data; | 921 | struct cx8802_fh *fh = file->private_data; |
1564 | 922 | ||
1565 | /* blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ | 923 | /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ |
1566 | blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0, | 924 | blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, |
1567 | BLACKBIRD_END_NOW, | 925 | BLACKBIRD_END_NOW, |
1568 | BLACKBIRD_MPEG_CAPTURE, | 926 | BLACKBIRD_MPEG_CAPTURE, |
1569 | BLACKBIRD_RAW_BITS_NONE | 927 | BLACKBIRD_RAW_BITS_NONE |
1570 | ); | 928 | ); |
1571 | 929 | ||
930 | cx8802_cancel_buffers(fh->dev); | ||
1572 | /* stop mpeg capture */ | 931 | /* stop mpeg capture */ |
1573 | if (fh->mpegq.streaming) | 932 | if (fh->mpegq.streaming) |
1574 | videobuf_streamoff(&fh->mpegq); | 933 | videobuf_streamoff(&fh->mpegq); |
@@ -1683,19 +1042,13 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev, | |||
1683 | dev->core = core; | 1042 | dev->core = core; |
1684 | dev->width = 720; | 1043 | dev->width = 720; |
1685 | dev->height = 576; | 1044 | dev->height = 576; |
1686 | memcpy(&dev->params,&default_mpeg_params,sizeof(default_mpeg_params)); | 1045 | cx2341x_fill_defaults(&dev->params); |
1687 | memcpy(&dev->dnr_params,&default_dnr_params,sizeof(default_dnr_params)); | 1046 | dev->params.port = CX2341X_PORT_STREAMING; |
1688 | |||
1689 | if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN) { | ||
1690 | |||
1691 | if (core->tuner_formats & V4L2_STD_525_60) { | ||
1692 | dev->height = 480; | ||
1693 | dev->params.vi_frame_rate = 30; | ||
1694 | } else { | ||
1695 | dev->height = 576; | ||
1696 | dev->params.vi_frame_rate = 25; | ||
1697 | } | ||
1698 | 1047 | ||
1048 | if (core->tvnorm->id & V4L2_STD_525_60) { | ||
1049 | dev->height = 480; | ||
1050 | } else { | ||
1051 | dev->height = 576; | ||
1699 | } | 1052 | } |
1700 | 1053 | ||
1701 | err = cx8802_init_common(dev); | 1054 | err = cx8802_init_common(dev); |
@@ -1781,8 +1134,6 @@ module_exit(blackbird_fini); | |||
1781 | 1134 | ||
1782 | EXPORT_SYMBOL(cx88_ioctl_hook); | 1135 | EXPORT_SYMBOL(cx88_ioctl_hook); |
1783 | EXPORT_SYMBOL(cx88_ioctl_translator); | 1136 | EXPORT_SYMBOL(cx88_ioctl_translator); |
1784 | EXPORT_SYMBOL(blackbird_set_params); | ||
1785 | EXPORT_SYMBOL(blackbird_set_dnr_params); | ||
1786 | 1137 | ||
1787 | /* ----------------------------------------------------------- */ | 1138 | /* ----------------------------------------------------------- */ |
1788 | /* | 1139 | /* |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index f80154b87d22..67cdd8270863 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -114,7 +114,7 @@ struct cx88_board cx88_boards[] = { | |||
114 | .radio = { | 114 | .radio = { |
115 | .type = CX88_RADIO, | 115 | .type = CX88_RADIO, |
116 | .gpio0 = 0xff10, | 116 | .gpio0 = 0xff10, |
117 | }, | 117 | }, |
118 | }, | 118 | }, |
119 | [CX88_BOARD_ATI_WONDER_PRO] = { | 119 | [CX88_BOARD_ATI_WONDER_PRO] = { |
120 | .name = "ATI TV Wonder Pro", | 120 | .name = "ATI TV Wonder Pro", |
@@ -267,7 +267,7 @@ struct cx88_board cx88_boards[] = { | |||
267 | .gpio1 = 0x00007004, | 267 | .gpio1 = 0x00007004, |
268 | .gpio2 = 0x0035d700, | 268 | .gpio2 = 0x0035d700, |
269 | .gpio3 = 0x02000000, | 269 | .gpio3 = 0x02000000, |
270 | }, | 270 | }, |
271 | }, | 271 | }, |
272 | [CX88_BOARD_LEADTEK_PVR2000] = { | 272 | [CX88_BOARD_LEADTEK_PVR2000] = { |
273 | // gpio values for PAL version from regspy by DScaler | 273 | // gpio values for PAL version from regspy by DScaler |
@@ -413,7 +413,7 @@ struct cx88_board cx88_boards[] = { | |||
413 | .type = CX88_VMUX_COMPOSITE1, | 413 | .type = CX88_VMUX_COMPOSITE1, |
414 | .vmux = 1, | 414 | .vmux = 1, |
415 | .gpio0 = 0x000027df, | 415 | .gpio0 = 0x000027df, |
416 | },{ | 416 | },{ |
417 | .type = CX88_VMUX_SVIDEO, | 417 | .type = CX88_VMUX_SVIDEO, |
418 | .vmux = 2, | 418 | .vmux = 2, |
419 | .gpio0 = 0x000027df, | 419 | .gpio0 = 0x000027df, |
@@ -536,7 +536,7 @@ struct cx88_board cx88_boards[] = { | |||
536 | .type = CX88_VMUX_COMPOSITE1, | 536 | .type = CX88_VMUX_COMPOSITE1, |
537 | .vmux = 1, | 537 | .vmux = 1, |
538 | .gpio0 = 0x000027df, | 538 | .gpio0 = 0x000027df, |
539 | },{ | 539 | },{ |
540 | .type = CX88_VMUX_SVIDEO, | 540 | .type = CX88_VMUX_SVIDEO, |
541 | .vmux = 2, | 541 | .vmux = 2, |
542 | .gpio0 = 0x000027df, | 542 | .gpio0 = 0x000027df, |
@@ -759,7 +759,7 @@ struct cx88_board cx88_boards[] = { | |||
759 | }, | 759 | }, |
760 | [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = { | 760 | [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = { |
761 | .name = "DViCO FusionHDTV 5 Gold", | 761 | .name = "DViCO FusionHDTV 5 Gold", |
762 | .tuner_type = TUNER_LG_TDVS_H062F, | 762 | .tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H062F */ |
763 | .radio_type = UNSET, | 763 | .radio_type = UNSET, |
764 | .tuner_addr = ADDR_UNSET, | 764 | .tuner_addr = ADDR_UNSET, |
765 | .radio_addr = ADDR_UNSET, | 765 | .radio_addr = ADDR_UNSET, |
@@ -1050,11 +1050,7 @@ struct cx88_board cx88_boards[] = { | |||
1050 | .dvb = 1, | 1050 | .dvb = 1, |
1051 | }, | 1051 | }, |
1052 | [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { | 1052 | [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { |
1053 | /* FIXME: Standard video using the cx88 broadcast decoder is | 1053 | /* FIXME: Audio not working for s-video / composite inputs. */ |
1054 | * working, but blackbird isn't working yet, audio is only | ||
1055 | * working correctly for television mode. S-Video and Composite | ||
1056 | * are working for video-only, so I have them disabled for now. | ||
1057 | */ | ||
1058 | .name = "KWorld HardwareMpegTV XPert", | 1054 | .name = "KWorld HardwareMpegTV XPert", |
1059 | .tuner_type = TUNER_PHILIPS_TDA8290, | 1055 | .tuner_type = TUNER_PHILIPS_TDA8290, |
1060 | .radio_type = UNSET, | 1056 | .radio_type = UNSET, |
@@ -1065,12 +1061,21 @@ struct cx88_board cx88_boards[] = { | |||
1065 | .vmux = 0, | 1061 | .vmux = 0, |
1066 | .gpio0 = 0x3de2, | 1062 | .gpio0 = 0x3de2, |
1067 | .gpio2 = 0x00ff, | 1063 | .gpio2 = 0x00ff, |
1064 | },{ | ||
1065 | .type = CX88_VMUX_COMPOSITE1, | ||
1066 | .vmux = 1, | ||
1067 | .gpio0 = 0x3de6, | ||
1068 | },{ | ||
1069 | .type = CX88_VMUX_SVIDEO, | ||
1070 | .vmux = 2, | ||
1071 | .gpio0 = 0x3de6, | ||
1068 | }}, | 1072 | }}, |
1069 | .radio = { | 1073 | .radio = { |
1070 | .type = CX88_RADIO, | 1074 | .type = CX88_RADIO, |
1071 | .gpio0 = 0x3de6, | 1075 | .gpio0 = 0x3de6, |
1072 | .gpio2 = 0x00ff, | 1076 | .gpio2 = 0x00ff, |
1073 | }, | 1077 | }, |
1078 | .blackbird = 1, | ||
1074 | }, | 1079 | }, |
1075 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = { | 1080 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = { |
1076 | .name = "DViCO FusionHDTV DVB-T Hybrid", | 1081 | .name = "DViCO FusionHDTV DVB-T Hybrid", |
@@ -1093,7 +1098,102 @@ struct cx88_board cx88_boards[] = { | |||
1093 | }}, | 1098 | }}, |
1094 | .dvb = 1, | 1099 | .dvb = 1, |
1095 | }, | 1100 | }, |
1096 | 1101 | [CX88_BOARD_PCHDTV_HD5500] = { | |
1102 | .name = "pcHDTV HD5500 HDTV", | ||
1103 | .tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */ | ||
1104 | .radio_type = UNSET, | ||
1105 | .tuner_addr = ADDR_UNSET, | ||
1106 | .radio_addr = ADDR_UNSET, | ||
1107 | .tda9887_conf = TDA9887_PRESENT, | ||
1108 | .input = {{ | ||
1109 | .type = CX88_VMUX_TELEVISION, | ||
1110 | .vmux = 0, | ||
1111 | .gpio0 = 0x87fd, | ||
1112 | },{ | ||
1113 | .type = CX88_VMUX_COMPOSITE1, | ||
1114 | .vmux = 1, | ||
1115 | .gpio0 = 0x87f9, | ||
1116 | },{ | ||
1117 | .type = CX88_VMUX_SVIDEO, | ||
1118 | .vmux = 2, | ||
1119 | .gpio0 = 0x87f9, | ||
1120 | }}, | ||
1121 | .dvb = 1, | ||
1122 | }, | ||
1123 | [CX88_BOARD_KWORLD_MCE200_DELUXE] = { | ||
1124 | /* FIXME: tested TV input only, disabled composite, | ||
1125 | svideo and radio until they can be tested also. */ | ||
1126 | .name = "Kworld MCE 200 Deluxe", | ||
1127 | .tuner_type = TUNER_TENA_9533_DI, | ||
1128 | .radio_type = UNSET, | ||
1129 | .tda9887_conf = TDA9887_PRESENT, | ||
1130 | .tuner_addr = ADDR_UNSET, | ||
1131 | .radio_addr = ADDR_UNSET, | ||
1132 | .input = {{ | ||
1133 | .type = CX88_VMUX_TELEVISION, | ||
1134 | .vmux = 0, | ||
1135 | .gpio0 = 0x0000BDE6 | ||
1136 | }}, | ||
1137 | .blackbird = 1, | ||
1138 | }, | ||
1139 | [CX88_BOARD_PIXELVIEW_PLAYTV_P7000] = { | ||
1140 | /* FIXME: SVideo, Composite and FM inputs are untested */ | ||
1141 | .name = "PixelView PlayTV P7000", | ||
1142 | .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, | ||
1143 | .radio_type = UNSET, | ||
1144 | .tuner_addr = ADDR_UNSET, | ||
1145 | .radio_addr = ADDR_UNSET, | ||
1146 | .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE | | ||
1147 | TDA9887_PORT2_ACTIVE, | ||
1148 | .input = {{ | ||
1149 | .type = CX88_VMUX_TELEVISION, | ||
1150 | .vmux = 0, | ||
1151 | .gpio0 = 0x5da6, | ||
1152 | }}, | ||
1153 | .blackbird = 1, | ||
1154 | }, | ||
1155 | [CX88_BOARD_NPGTECH_REALTV_TOP10FM] = { | ||
1156 | .name = "NPG Tech Real TV FM Top 10", | ||
1157 | .tuner_type = TUNER_TNF_5335MF, /* Actually a TNF9535 */ | ||
1158 | .radio_type = UNSET, | ||
1159 | .tuner_addr = ADDR_UNSET, | ||
1160 | .radio_addr = ADDR_UNSET, | ||
1161 | .input = {{ | ||
1162 | .type = CX88_VMUX_TELEVISION, | ||
1163 | .vmux = 0, | ||
1164 | .gpio0 = 0x0788, | ||
1165 | },{ | ||
1166 | .type = CX88_VMUX_COMPOSITE1, | ||
1167 | .vmux = 1, | ||
1168 | .gpio0 = 0x078b, | ||
1169 | },{ | ||
1170 | .type = CX88_VMUX_SVIDEO, | ||
1171 | .vmux = 2, | ||
1172 | .gpio0 = 0x078b, | ||
1173 | }}, | ||
1174 | .radio = { | ||
1175 | .type = CX88_RADIO, | ||
1176 | .gpio0 = 0x074a, | ||
1177 | }, | ||
1178 | }, | ||
1179 | [CX88_BOARD_WINFAST_DTV2000H] = { | ||
1180 | /* video inputs and radio still in testing */ | ||
1181 | .name = "WinFast DTV2000 H", | ||
1182 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, | ||
1183 | .radio_type = UNSET, | ||
1184 | .tuner_addr = ADDR_UNSET, | ||
1185 | .radio_addr = ADDR_UNSET, | ||
1186 | .tda9887_conf = TDA9887_PRESENT, | ||
1187 | .input = {{ | ||
1188 | .type = CX88_VMUX_TELEVISION, | ||
1189 | .vmux = 0, | ||
1190 | .gpio0 = 0x00017304, | ||
1191 | .gpio1 = 0x00008203, | ||
1192 | .gpio2 = 0x00017304, | ||
1193 | .gpio3 = 0x02000000, | ||
1194 | }}, | ||
1195 | .dvb = 1, | ||
1196 | }, | ||
1097 | }; | 1197 | }; |
1098 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); | 1198 | const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); |
1099 | 1199 | ||
@@ -1311,6 +1411,34 @@ struct cx88_subid cx88_subids[] = { | |||
1311 | .subvendor = 0x18ac, | 1411 | .subvendor = 0x18ac, |
1312 | .subdevice = 0xdb44, | 1412 | .subdevice = 0xdb44, |
1313 | .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID, | 1413 | .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID, |
1414 | },{ | ||
1415 | .subvendor = 0x7063, | ||
1416 | .subdevice = 0x5500, | ||
1417 | .card = CX88_BOARD_PCHDTV_HD5500, | ||
1418 | },{ | ||
1419 | .subvendor = 0x17de, | ||
1420 | .subdevice = 0x0841, | ||
1421 | .card = CX88_BOARD_KWORLD_MCE200_DELUXE, | ||
1422 | },{ | ||
1423 | .subvendor = 0x1822, | ||
1424 | .subdevice = 0x0019, | ||
1425 | .card = CX88_BOARD_DNTV_LIVE_DVB_T_PRO, | ||
1426 | },{ | ||
1427 | .subvendor = 0x1554, | ||
1428 | .subdevice = 0x4813, | ||
1429 | .card = CX88_BOARD_PIXELVIEW_PLAYTV_P7000, | ||
1430 | },{ | ||
1431 | .subvendor = 0x14f1, | ||
1432 | .subdevice = 0x0842, | ||
1433 | .card = CX88_BOARD_NPGTECH_REALTV_TOP10FM, | ||
1434 | },{ | ||
1435 | .subvendor = 0x107d, | ||
1436 | .subdevice = 0x665e, | ||
1437 | .card = CX88_BOARD_WINFAST_DTV2000H, | ||
1438 | },{ | ||
1439 | .subvendor = 0x18ac, | ||
1440 | .subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */ | ||
1441 | .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q, | ||
1314 | }, | 1442 | }, |
1315 | }; | 1443 | }; |
1316 | const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); | 1444 | const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); |
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index e1092d5d4628..c56292d8d93b 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c | |||
@@ -677,7 +677,7 @@ static unsigned int inline norm_htotal(struct cx88_tvnorm *norm) | |||
677 | 677 | ||
678 | static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm) | 678 | static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm) |
679 | { | 679 | { |
680 | return (norm->id & V4L2_STD_625_50) ? 511 : 288; | 680 | return (norm->id & V4L2_STD_625_50) ? 511 : 400; |
681 | } | 681 | } |
682 | 682 | ||
683 | int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height, | 683 | int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height, |
@@ -932,9 +932,9 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm) | |||
932 | htotal, cx_read(MO_HTOTAL), (u32)tmp64); | 932 | htotal, cx_read(MO_HTOTAL), (u32)tmp64); |
933 | cx_write(MO_HTOTAL, htotal); | 933 | cx_write(MO_HTOTAL, htotal); |
934 | 934 | ||
935 | // vbi stuff | 935 | // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes |
936 | cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */ | 936 | // the effective vbi offset ~244 samples, the same as the Bt8x8 |
937 | norm_vbipack(norm))); | 937 | cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm)); |
938 | 938 | ||
939 | // this is needed as well to set all tvnorm parameter | 939 | // this is needed as well to set all tvnorm parameter |
940 | cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED); | 940 | cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED); |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 3619a449aefd..dce1feddd55d 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #endif | 51 | #endif |
52 | #ifdef HAVE_LGDT330X | 52 | #ifdef HAVE_LGDT330X |
53 | # include "lgdt330x.h" | 53 | # include "lgdt330x.h" |
54 | # include "lg_h06xf.h" | ||
54 | #endif | 55 | #endif |
55 | #ifdef HAVE_NXT200X | 56 | #ifdef HAVE_NXT200X |
56 | # include "nxt200x.h" | 57 | # include "nxt200x.h" |
@@ -58,6 +59,7 @@ | |||
58 | #ifdef HAVE_CX24123 | 59 | #ifdef HAVE_CX24123 |
59 | # include "cx24123.h" | 60 | # include "cx24123.h" |
60 | #endif | 61 | #endif |
62 | #include "isl6421.h" | ||
61 | 63 | ||
62 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); | 64 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); |
63 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); | 65 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); |
@@ -113,21 +115,6 @@ static struct videobuf_queue_ops dvb_qops = { | |||
113 | 115 | ||
114 | /* ------------------------------------------------------------------ */ | 116 | /* ------------------------------------------------------------------ */ |
115 | 117 | ||
116 | #if defined(HAVE_MT352) || defined(HAVE_ZL10353) | ||
117 | static int zarlink_pll_set(struct dvb_frontend *fe, | ||
118 | struct dvb_frontend_parameters *params, | ||
119 | u8 *pllbuf) | ||
120 | { | ||
121 | struct cx8802_dev *dev = fe->dvb->priv; | ||
122 | |||
123 | pllbuf[0] = dev->core->pll_addr << 1; | ||
124 | dvb_pll_configure(dev->core->pll_desc, pllbuf + 1, | ||
125 | params->frequency, | ||
126 | params->u.ofdm.bandwidth); | ||
127 | return 0; | ||
128 | } | ||
129 | #endif | ||
130 | |||
131 | #ifdef HAVE_MT352 | 118 | #ifdef HAVE_MT352 |
132 | static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) | 119 | static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) |
133 | { | 120 | { |
@@ -196,19 +183,16 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) | |||
196 | static struct mt352_config dvico_fusionhdtv = { | 183 | static struct mt352_config dvico_fusionhdtv = { |
197 | .demod_address = 0x0F, | 184 | .demod_address = 0x0F, |
198 | .demod_init = dvico_fusionhdtv_demod_init, | 185 | .demod_init = dvico_fusionhdtv_demod_init, |
199 | .pll_set = zarlink_pll_set, | ||
200 | }; | 186 | }; |
201 | 187 | ||
202 | static struct mt352_config dntv_live_dvbt_config = { | 188 | static struct mt352_config dntv_live_dvbt_config = { |
203 | .demod_address = 0x0f, | 189 | .demod_address = 0x0f, |
204 | .demod_init = dntv_live_dvbt_demod_init, | 190 | .demod_init = dntv_live_dvbt_demod_init, |
205 | .pll_set = zarlink_pll_set, | ||
206 | }; | 191 | }; |
207 | 192 | ||
208 | static struct mt352_config dvico_fusionhdtv_dual = { | 193 | static struct mt352_config dvico_fusionhdtv_dual = { |
209 | .demod_address = 0x0F, | 194 | .demod_address = 0x0F, |
210 | .demod_init = dvico_dual_demod_init, | 195 | .demod_init = dvico_dual_demod_init, |
211 | .pll_set = zarlink_pll_set, | ||
212 | }; | 196 | }; |
213 | 197 | ||
214 | #ifdef HAVE_VP3054_I2C | 198 | #ifdef HAVE_VP3054_I2C |
@@ -246,6 +230,8 @@ static int philips_fmd1216_pll_init(struct dvb_frontend *fe) | |||
246 | .buf = fmd1216_init, .len = sizeof(fmd1216_init) }; | 230 | .buf = fmd1216_init, .len = sizeof(fmd1216_init) }; |
247 | int err; | 231 | int err; |
248 | 232 | ||
233 | if (fe->ops.i2c_gate_ctrl) | ||
234 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
249 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { | 235 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { |
250 | if (err < 0) | 236 | if (err < 0) |
251 | return err; | 237 | return err; |
@@ -256,14 +242,14 @@ static int philips_fmd1216_pll_init(struct dvb_frontend *fe) | |||
256 | return 0; | 242 | return 0; |
257 | } | 243 | } |
258 | 244 | ||
259 | static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe, | 245 | static int dntv_live_dvbt_pro_tuner_set_params(struct dvb_frontend* fe, |
260 | struct dvb_frontend_parameters* params, | 246 | struct dvb_frontend_parameters* params) |
261 | u8* pllbuf) | ||
262 | { | 247 | { |
263 | struct cx8802_dev *dev= fe->dvb->priv; | 248 | struct cx8802_dev *dev= fe->dvb->priv; |
249 | u8 buf[4]; | ||
264 | struct i2c_msg msg = | 250 | struct i2c_msg msg = |
265 | { .addr = dev->core->pll_addr, .flags = 0, | 251 | { .addr = dev->core->pll_addr, .flags = 0, |
266 | .buf = pllbuf+1, .len = 4 }; | 252 | .buf = buf, .len = 4 }; |
267 | int err; | 253 | int err; |
268 | 254 | ||
269 | /* Switch PLL to DVB mode */ | 255 | /* Switch PLL to DVB mode */ |
@@ -272,14 +258,16 @@ static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe, | |||
272 | return err; | 258 | return err; |
273 | 259 | ||
274 | /* Tune PLL */ | 260 | /* Tune PLL */ |
275 | pllbuf[0] = dev->core->pll_addr << 1; | 261 | dvb_pll_configure(dev->core->pll_desc, buf, |
276 | dvb_pll_configure(dev->core->pll_desc, pllbuf+1, | ||
277 | params->frequency, | 262 | params->frequency, |
278 | params->u.ofdm.bandwidth); | 263 | params->u.ofdm.bandwidth); |
264 | if (fe->ops.i2c_gate_ctrl) | ||
265 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
279 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { | 266 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { |
267 | |||
280 | printk(KERN_WARNING "cx88-dvb: %s error " | 268 | printk(KERN_WARNING "cx88-dvb: %s error " |
281 | "(addr %02x <- %02x, err = %i)\n", | 269 | "(addr %02x <- %02x, err = %i)\n", |
282 | __FUNCTION__, pllbuf[0], pllbuf[1], err); | 270 | __FUNCTION__, dev->core->pll_addr, buf[0], err); |
283 | if (err < 0) | 271 | if (err < 0) |
284 | return err; | 272 | return err; |
285 | else | 273 | else |
@@ -293,27 +281,27 @@ static struct mt352_config dntv_live_dvbt_pro_config = { | |||
293 | .demod_address = 0x0f, | 281 | .demod_address = 0x0f, |
294 | .no_tuner = 1, | 282 | .no_tuner = 1, |
295 | .demod_init = dntv_live_dvbt_pro_demod_init, | 283 | .demod_init = dntv_live_dvbt_pro_demod_init, |
296 | .pll_set = dntv_live_dvbt_pro_pll_set, | ||
297 | }; | 284 | }; |
298 | #endif | 285 | #endif |
299 | #endif | 286 | #endif |
300 | 287 | ||
301 | #ifdef HAVE_ZL10353 | 288 | #ifdef HAVE_ZL10353 |
302 | static int dvico_hybrid_tune_pll(struct dvb_frontend *fe, | 289 | static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe, |
303 | struct dvb_frontend_parameters *params, | 290 | struct dvb_frontend_parameters *params) |
304 | u8 *pllbuf) | ||
305 | { | 291 | { |
292 | u8 pllbuf[4]; | ||
306 | struct cx8802_dev *dev= fe->dvb->priv; | 293 | struct cx8802_dev *dev= fe->dvb->priv; |
307 | struct i2c_msg msg = | 294 | struct i2c_msg msg = |
308 | { .addr = dev->core->pll_addr, .flags = 0, | 295 | { .addr = dev->core->pll_addr, .flags = 0, |
309 | .buf = pllbuf + 1, .len = 4 }; | 296 | .buf = pllbuf, .len = 4 }; |
310 | int err; | 297 | int err; |
311 | 298 | ||
312 | pllbuf[0] = dev->core->pll_addr << 1; | 299 | dvb_pll_configure(dev->core->pll_desc, pllbuf, |
313 | dvb_pll_configure(dev->core->pll_desc, pllbuf + 1, | ||
314 | params->frequency, | 300 | params->frequency, |
315 | params->u.ofdm.bandwidth); | 301 | params->u.ofdm.bandwidth); |
316 | 302 | ||
303 | if (fe->ops.i2c_gate_ctrl) | ||
304 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
317 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { | 305 | if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { |
318 | printk(KERN_WARNING "cx88-dvb: %s error " | 306 | printk(KERN_WARNING "cx88-dvb: %s error " |
319 | "(addr %02x <- %02x, err = %i)\n", | 307 | "(addr %02x <- %02x, err = %i)\n", |
@@ -329,12 +317,11 @@ static int dvico_hybrid_tune_pll(struct dvb_frontend *fe, | |||
329 | 317 | ||
330 | static struct zl10353_config dvico_fusionhdtv_hybrid = { | 318 | static struct zl10353_config dvico_fusionhdtv_hybrid = { |
331 | .demod_address = 0x0F, | 319 | .demod_address = 0x0F, |
332 | .pll_set = dvico_hybrid_tune_pll, | 320 | .no_tuner = 1, |
333 | }; | 321 | }; |
334 | 322 | ||
335 | static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { | 323 | static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { |
336 | .demod_address = 0x0F, | 324 | .demod_address = 0x0F, |
337 | .pll_set = zarlink_pll_set, | ||
338 | }; | 325 | }; |
339 | #endif | 326 | #endif |
340 | 327 | ||
@@ -342,21 +329,15 @@ static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { | |||
342 | static struct cx22702_config connexant_refboard_config = { | 329 | static struct cx22702_config connexant_refboard_config = { |
343 | .demod_address = 0x43, | 330 | .demod_address = 0x43, |
344 | .output_mode = CX22702_SERIAL_OUTPUT, | 331 | .output_mode = CX22702_SERIAL_OUTPUT, |
345 | .pll_address = 0x60, | ||
346 | .pll_desc = &dvb_pll_thomson_dtt7579, | ||
347 | }; | 332 | }; |
348 | 333 | ||
349 | static struct cx22702_config hauppauge_novat_config = { | 334 | static struct cx22702_config hauppauge_novat_config = { |
350 | .demod_address = 0x43, | 335 | .demod_address = 0x43, |
351 | .output_mode = CX22702_SERIAL_OUTPUT, | 336 | .output_mode = CX22702_SERIAL_OUTPUT, |
352 | .pll_address = 0x61, | ||
353 | .pll_desc = &dvb_pll_thomson_dtt759x, | ||
354 | }; | 337 | }; |
355 | static struct cx22702_config hauppauge_hvr1100_config = { | 338 | static struct cx22702_config hauppauge_hvr1100_config = { |
356 | .demod_address = 0x63, | 339 | .demod_address = 0x63, |
357 | .output_mode = CX22702_SERIAL_OUTPUT, | 340 | .output_mode = CX22702_SERIAL_OUTPUT, |
358 | .pll_address = 0x61, | ||
359 | .pll_desc = &dvb_pll_fmd1216me, | ||
360 | }; | 341 | }; |
361 | #endif | 342 | #endif |
362 | 343 | ||
@@ -371,15 +352,13 @@ static int or51132_set_ts_param(struct dvb_frontend* fe, | |||
371 | 352 | ||
372 | static struct or51132_config pchdtv_hd3000 = { | 353 | static struct or51132_config pchdtv_hd3000 = { |
373 | .demod_address = 0x15, | 354 | .demod_address = 0x15, |
374 | .pll_address = 0x61, | ||
375 | .pll_desc = &dvb_pll_thomson_dtt761x, | ||
376 | .set_ts_params = or51132_set_ts_param, | 355 | .set_ts_params = or51132_set_ts_param, |
377 | }; | 356 | }; |
378 | #endif | 357 | #endif |
379 | 358 | ||
380 | #ifdef HAVE_LGDT330X | 359 | #ifdef HAVE_LGDT330X |
381 | static int lgdt330x_pll_set(struct dvb_frontend* fe, | 360 | static int lgdt3302_tuner_set_params(struct dvb_frontend* fe, |
382 | struct dvb_frontend_parameters* params) | 361 | struct dvb_frontend_parameters* params) |
383 | { | 362 | { |
384 | /* FIXME make this routine use the tuner-simple code. | 363 | /* FIXME make this routine use the tuner-simple code. |
385 | * It could probably be shared with a number of ATSC | 364 | * It could probably be shared with a number of ATSC |
@@ -392,12 +371,12 @@ static int lgdt330x_pll_set(struct dvb_frontend* fe, | |||
392 | { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; | 371 | { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; |
393 | int err; | 372 | int err; |
394 | 373 | ||
395 | /* Put the analog decoder in standby to keep it quiet */ | ||
396 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
397 | |||
398 | dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); | 374 | dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); |
399 | dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", | 375 | dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", |
400 | __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); | 376 | __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); |
377 | |||
378 | if (fe->ops.i2c_gate_ctrl) | ||
379 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
401 | if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) { | 380 | if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) { |
402 | printk(KERN_WARNING "cx88-dvb: %s error " | 381 | printk(KERN_WARNING "cx88-dvb: %s error " |
403 | "(addr %02x <- %02x, err = %i)\n", | 382 | "(addr %02x <- %02x, err = %i)\n", |
@@ -407,16 +386,21 @@ static int lgdt330x_pll_set(struct dvb_frontend* fe, | |||
407 | else | 386 | else |
408 | return -EREMOTEIO; | 387 | return -EREMOTEIO; |
409 | } | 388 | } |
410 | if (core->tuner_type == TUNER_LG_TDVS_H062F) { | ||
411 | /* Set the Auxiliary Byte. */ | ||
412 | buf[2] &= ~0x20; | ||
413 | buf[2] |= 0x18; | ||
414 | buf[3] = 0x50; | ||
415 | i2c_transfer(&core->i2c_adap, &msg, 1); | ||
416 | } | ||
417 | return 0; | 389 | return 0; |
418 | } | 390 | } |
419 | 391 | ||
392 | static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, | ||
393 | struct dvb_frontend_parameters* params) | ||
394 | { | ||
395 | struct cx8802_dev *dev= fe->dvb->priv; | ||
396 | struct cx88_core *core = dev->core; | ||
397 | |||
398 | /* Put the analog decoder in standby to keep it quiet */ | ||
399 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
400 | |||
401 | return lg_h06xf_pll_set(fe, &core->i2c_adap, params); | ||
402 | } | ||
403 | |||
420 | static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) | 404 | static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) |
421 | { | 405 | { |
422 | struct cx8802_dev *dev= fe->dvb->priv; | 406 | struct cx8802_dev *dev= fe->dvb->priv; |
@@ -444,7 +428,6 @@ static struct lgdt330x_config fusionhdtv_3_gold = { | |||
444 | .demod_address = 0x0e, | 428 | .demod_address = 0x0e, |
445 | .demod_chip = LGDT3302, | 429 | .demod_chip = LGDT3302, |
446 | .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ | 430 | .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ |
447 | .pll_set = lgdt330x_pll_set, | ||
448 | .set_ts_params = lgdt330x_set_ts_param, | 431 | .set_ts_params = lgdt330x_set_ts_param, |
449 | }; | 432 | }; |
450 | 433 | ||
@@ -452,7 +435,13 @@ static struct lgdt330x_config fusionhdtv_5_gold = { | |||
452 | .demod_address = 0x0e, | 435 | .demod_address = 0x0e, |
453 | .demod_chip = LGDT3303, | 436 | .demod_chip = LGDT3303, |
454 | .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ | 437 | .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ |
455 | .pll_set = lgdt330x_pll_set, | 438 | .set_ts_params = lgdt330x_set_ts_param, |
439 | }; | ||
440 | |||
441 | static struct lgdt330x_config pchdtv_hd5500 = { | ||
442 | .demod_address = 0x59, | ||
443 | .demod_chip = LGDT3303, | ||
444 | .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ | ||
456 | .set_ts_params = lgdt330x_set_ts_param, | 445 | .set_ts_params = lgdt330x_set_ts_param, |
457 | }; | 446 | }; |
458 | #endif | 447 | #endif |
@@ -477,8 +466,6 @@ static int nxt200x_set_pll_input(u8* buf, int input) | |||
477 | 466 | ||
478 | static struct nxt200x_config ati_hdtvwonder = { | 467 | static struct nxt200x_config ati_hdtvwonder = { |
479 | .demod_address = 0x0a, | 468 | .demod_address = 0x0a, |
480 | .pll_address = 0x61, | ||
481 | .pll_desc = &dvb_pll_tuv1236d, | ||
482 | .set_pll_input = nxt200x_set_pll_input, | 469 | .set_pll_input = nxt200x_set_pll_input, |
483 | .set_ts_params = nxt200x_set_ts_param, | 470 | .set_ts_params = nxt200x_set_ts_param, |
484 | }; | 471 | }; |
@@ -493,28 +480,30 @@ static int cx24123_set_ts_param(struct dvb_frontend* fe, | |||
493 | return 0; | 480 | return 0; |
494 | } | 481 | } |
495 | 482 | ||
496 | static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on) | 483 | static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) |
497 | { | 484 | { |
498 | struct cx8802_dev *dev= fe->dvb->priv; | 485 | struct cx8802_dev *dev= fe->dvb->priv; |
499 | struct cx88_core *core = dev->core; | 486 | struct cx88_core *core = dev->core; |
500 | 487 | ||
501 | if (on) | 488 | if (voltage == SEC_VOLTAGE_OFF) { |
502 | cx_write(MO_GP0_IO, 0x000006f9); | ||
503 | else | ||
504 | cx_write(MO_GP0_IO, 0x000006fB); | 489 | cx_write(MO_GP0_IO, 0x000006fB); |
490 | } else { | ||
491 | cx_write(MO_GP0_IO, 0x000006f9); | ||
492 | } | ||
493 | |||
494 | if (core->prev_set_voltage) | ||
495 | return core->prev_set_voltage(fe, voltage); | ||
496 | return 0; | ||
505 | } | 497 | } |
506 | 498 | ||
507 | static struct cx24123_config hauppauge_novas_config = { | 499 | static struct cx24123_config hauppauge_novas_config = { |
508 | .demod_address = 0x55, | 500 | .demod_address = 0x55, |
509 | .use_isl6421 = 1, | ||
510 | .set_ts_params = cx24123_set_ts_param, | 501 | .set_ts_params = cx24123_set_ts_param, |
511 | }; | 502 | }; |
512 | 503 | ||
513 | static struct cx24123_config kworld_dvbs_100_config = { | 504 | static struct cx24123_config kworld_dvbs_100_config = { |
514 | .demod_address = 0x15, | 505 | .demod_address = 0x15, |
515 | .use_isl6421 = 0, | ||
516 | .set_ts_params = cx24123_set_ts_param, | 506 | .set_ts_params = cx24123_set_ts_param, |
517 | .enable_lnb_voltage = cx24123_enable_lnb_voltage, | ||
518 | }; | 507 | }; |
519 | #endif | 508 | #endif |
520 | 509 | ||
@@ -530,6 +519,11 @@ static int dvb_register(struct cx8802_dev *dev) | |||
530 | case CX88_BOARD_HAUPPAUGE_DVB_T1: | 519 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
531 | dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config, | 520 | dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config, |
532 | &dev->core->i2c_adap); | 521 | &dev->core->i2c_adap); |
522 | if (dev->dvb.frontend != NULL) { | ||
523 | dvb_pll_attach(dev->dvb.frontend, 0x61, | ||
524 | &dev->core->i2c_adap, | ||
525 | &dvb_pll_thomson_dtt759x); | ||
526 | } | ||
533 | break; | 527 | break; |
534 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: | 528 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: |
535 | case CX88_BOARD_CONEXANT_DVB_T1: | 529 | case CX88_BOARD_CONEXANT_DVB_T1: |
@@ -537,44 +531,92 @@ static int dvb_register(struct cx8802_dev *dev) | |||
537 | case CX88_BOARD_WINFAST_DTV1000: | 531 | case CX88_BOARD_WINFAST_DTV1000: |
538 | dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, | 532 | dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, |
539 | &dev->core->i2c_adap); | 533 | &dev->core->i2c_adap); |
534 | if (dev->dvb.frontend != NULL) { | ||
535 | dvb_pll_attach(dev->dvb.frontend, 0x60, | ||
536 | &dev->core->i2c_adap, | ||
537 | &dvb_pll_thomson_dtt7579); | ||
538 | } | ||
540 | break; | 539 | break; |
540 | case CX88_BOARD_WINFAST_DTV2000H: | ||
541 | case CX88_BOARD_HAUPPAUGE_HVR1100: | 541 | case CX88_BOARD_HAUPPAUGE_HVR1100: |
542 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | 542 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: |
543 | dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config, | 543 | dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config, |
544 | &dev->core->i2c_adap); | 544 | &dev->core->i2c_adap); |
545 | if (dev->dvb.frontend != NULL) { | ||
546 | dvb_pll_attach(dev->dvb.frontend, 0x61, | ||
547 | &dev->core->i2c_adap, | ||
548 | &dvb_pll_fmd1216me); | ||
549 | } | ||
545 | break; | 550 | break; |
546 | #endif | 551 | #endif |
547 | #if defined(HAVE_MT352) || defined(HAVE_ZL10353) | 552 | #if defined(HAVE_MT352) || defined(HAVE_ZL10353) |
548 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: | 553 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: |
549 | dev->core->pll_addr = 0x60; | ||
550 | dev->core->pll_desc = &dvb_pll_thomson_dtt7579; | ||
551 | #ifdef HAVE_MT352 | 554 | #ifdef HAVE_MT352 |
552 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, | 555 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, |
553 | &dev->core->i2c_adap); | 556 | &dev->core->i2c_adap); |
554 | if (dev->dvb.frontend != NULL) | 557 | if (dev->dvb.frontend != NULL) { |
558 | dvb_pll_attach(dev->dvb.frontend, 0x60, | ||
559 | &dev->core->i2c_adap, | ||
560 | &dvb_pll_thomson_dtt7579); | ||
555 | break; | 561 | break; |
562 | } | ||
556 | #endif | 563 | #endif |
557 | #ifdef HAVE_ZL10353 | 564 | #ifdef HAVE_ZL10353 |
558 | /* ZL10353 replaces MT352 on later cards */ | 565 | /* ZL10353 replaces MT352 on later cards */ |
559 | dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1, | 566 | dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1, |
560 | &dev->core->i2c_adap); | 567 | &dev->core->i2c_adap); |
568 | if (dev->dvb.frontend != NULL) { | ||
569 | dvb_pll_attach(dev->dvb.frontend, 0x60, | ||
570 | &dev->core->i2c_adap, | ||
571 | &dvb_pll_thomson_dtt7579); | ||
572 | } | ||
573 | #endif | ||
574 | break; | ||
575 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: | ||
576 | #ifdef HAVE_MT352 | ||
577 | /* The tin box says DEE1601, but it seems to be DTT7579 | ||
578 | * compatible, with a slightly different MT352 AGC gain. */ | ||
579 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual, | ||
580 | &dev->core->i2c_adap); | ||
581 | if (dev->dvb.frontend != NULL) { | ||
582 | dvb_pll_attach(dev->dvb.frontend, 0x61, | ||
583 | &dev->core->i2c_adap, | ||
584 | &dvb_pll_thomson_dtt7579); | ||
585 | break; | ||
586 | } | ||
587 | #endif | ||
588 | #ifdef HAVE_ZL10353 | ||
589 | /* ZL10353 replaces MT352 on later cards */ | ||
590 | dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1, | ||
591 | &dev->core->i2c_adap); | ||
592 | if (dev->dvb.frontend != NULL) { | ||
593 | dvb_pll_attach(dev->dvb.frontend, 0x61, | ||
594 | &dev->core->i2c_adap, | ||
595 | &dvb_pll_thomson_dtt7579); | ||
596 | } | ||
561 | #endif | 597 | #endif |
562 | break; | 598 | break; |
563 | #endif /* HAVE_MT352 || HAVE_ZL10353 */ | 599 | #endif /* HAVE_MT352 || HAVE_ZL10353 */ |
564 | #ifdef HAVE_MT352 | 600 | #ifdef HAVE_MT352 |
565 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: | 601 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: |
566 | dev->core->pll_addr = 0x61; | ||
567 | dev->core->pll_desc = &dvb_pll_lg_z201; | ||
568 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, | 602 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, |
569 | &dev->core->i2c_adap); | 603 | &dev->core->i2c_adap); |
604 | if (dev->dvb.frontend != NULL) { | ||
605 | dvb_pll_attach(dev->dvb.frontend, 0x61, | ||
606 | &dev->core->i2c_adap, | ||
607 | &dvb_pll_lg_z201); | ||
608 | } | ||
570 | break; | 609 | break; |
571 | case CX88_BOARD_KWORLD_DVB_T: | 610 | case CX88_BOARD_KWORLD_DVB_T: |
572 | case CX88_BOARD_DNTV_LIVE_DVB_T: | 611 | case CX88_BOARD_DNTV_LIVE_DVB_T: |
573 | case CX88_BOARD_ADSTECH_DVB_T_PCI: | 612 | case CX88_BOARD_ADSTECH_DVB_T_PCI: |
574 | dev->core->pll_addr = 0x61; | ||
575 | dev->core->pll_desc = &dvb_pll_unknown_1; | ||
576 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config, | 613 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config, |
577 | &dev->core->i2c_adap); | 614 | &dev->core->i2c_adap); |
615 | if (dev->dvb.frontend != NULL) { | ||
616 | dvb_pll_attach(dev->dvb.frontend, 0x61, | ||
617 | &dev->core->i2c_adap, | ||
618 | &dvb_pll_unknown_1); | ||
619 | } | ||
578 | break; | 620 | break; |
579 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: | 621 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: |
580 | #ifdef HAVE_VP3054_I2C | 622 | #ifdef HAVE_VP3054_I2C |
@@ -582,18 +624,13 @@ static int dvb_register(struct cx8802_dev *dev) | |||
582 | dev->core->pll_desc = &dvb_pll_fmd1216me; | 624 | dev->core->pll_desc = &dvb_pll_fmd1216me; |
583 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config, | 625 | dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config, |
584 | &((struct vp3054_i2c_state *)dev->card_priv)->adap); | 626 | &((struct vp3054_i2c_state *)dev->card_priv)->adap); |
627 | if (dev->dvb.frontend != NULL) { | ||
628 | dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params; | ||
629 | } | ||
585 | #else | 630 | #else |
586 | printk("%s: built without vp3054 support\n", dev->core->name); | 631 | printk("%s: built without vp3054 support\n", dev->core->name); |
587 | #endif | 632 | #endif |
588 | break; | 633 | break; |
589 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: | ||
590 | /* The tin box says DEE1601, but it seems to be DTT7579 | ||
591 | * compatible, with a slightly different MT352 AGC gain. */ | ||
592 | dev->core->pll_addr = 0x61; | ||
593 | dev->core->pll_desc = &dvb_pll_thomson_dtt7579; | ||
594 | dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual, | ||
595 | &dev->core->i2c_adap); | ||
596 | break; | ||
597 | #endif | 634 | #endif |
598 | #ifdef HAVE_ZL10353 | 635 | #ifdef HAVE_ZL10353 |
599 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: | 636 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: |
@@ -601,12 +638,20 @@ static int dvb_register(struct cx8802_dev *dev) | |||
601 | dev->core->pll_desc = &dvb_pll_thomson_fe6600; | 638 | dev->core->pll_desc = &dvb_pll_thomson_fe6600; |
602 | dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid, | 639 | dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid, |
603 | &dev->core->i2c_adap); | 640 | &dev->core->i2c_adap); |
641 | if (dev->dvb.frontend != NULL) { | ||
642 | dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params; | ||
643 | } | ||
604 | break; | 644 | break; |
605 | #endif | 645 | #endif |
606 | #ifdef HAVE_OR51132 | 646 | #ifdef HAVE_OR51132 |
607 | case CX88_BOARD_PCHDTV_HD3000: | 647 | case CX88_BOARD_PCHDTV_HD3000: |
608 | dev->dvb.frontend = or51132_attach(&pchdtv_hd3000, | 648 | dev->dvb.frontend = or51132_attach(&pchdtv_hd3000, |
609 | &dev->core->i2c_adap); | 649 | &dev->core->i2c_adap); |
650 | if (dev->dvb.frontend != NULL) { | ||
651 | dvb_pll_attach(dev->dvb.frontend, 0x61, | ||
652 | &dev->core->i2c_adap, | ||
653 | &dvb_pll_thomson_dtt761x); | ||
654 | } | ||
610 | break; | 655 | break; |
611 | #endif | 656 | #endif |
612 | #ifdef HAVE_LGDT330X | 657 | #ifdef HAVE_LGDT330X |
@@ -627,6 +672,9 @@ static int dvb_register(struct cx8802_dev *dev) | |||
627 | dev->core->pll_desc = &dvb_pll_microtune_4042; | 672 | dev->core->pll_desc = &dvb_pll_microtune_4042; |
628 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, | 673 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, |
629 | &dev->core->i2c_adap); | 674 | &dev->core->i2c_adap); |
675 | if (dev->dvb.frontend != NULL) { | ||
676 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; | ||
677 | } | ||
630 | } | 678 | } |
631 | break; | 679 | break; |
632 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: | 680 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: |
@@ -643,6 +691,9 @@ static int dvb_register(struct cx8802_dev *dev) | |||
643 | dev->core->pll_desc = &dvb_pll_thomson_dtt761x; | 691 | dev->core->pll_desc = &dvb_pll_thomson_dtt761x; |
644 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, | 692 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, |
645 | &dev->core->i2c_adap); | 693 | &dev->core->i2c_adap); |
694 | if (dev->dvb.frontend != NULL) { | ||
695 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; | ||
696 | } | ||
646 | } | 697 | } |
647 | break; | 698 | break; |
648 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: | 699 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: |
@@ -655,10 +706,28 @@ static int dvb_register(struct cx8802_dev *dev) | |||
655 | mdelay(100); | 706 | mdelay(100); |
656 | cx_set(MO_GP0_IO, 1); | 707 | cx_set(MO_GP0_IO, 1); |
657 | mdelay(200); | 708 | mdelay(200); |
658 | dev->core->pll_addr = 0x61; | ||
659 | dev->core->pll_desc = &dvb_pll_tdvs_tua6034; | ||
660 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold, | 709 | dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold, |
661 | &dev->core->i2c_adap); | 710 | &dev->core->i2c_adap); |
711 | if (dev->dvb.frontend != NULL) { | ||
712 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; | ||
713 | } | ||
714 | } | ||
715 | break; | ||
716 | case CX88_BOARD_PCHDTV_HD5500: | ||
717 | dev->ts_gen_cntrl = 0x08; | ||
718 | { | ||
719 | /* Do a hardware reset of chip before using it. */ | ||
720 | struct cx88_core *core = dev->core; | ||
721 | |||
722 | cx_clear(MO_GP0_IO, 1); | ||
723 | mdelay(100); | ||
724 | cx_set(MO_GP0_IO, 1); | ||
725 | mdelay(200); | ||
726 | dev->dvb.frontend = lgdt330x_attach(&pchdtv_hd5500, | ||
727 | &dev->core->i2c_adap); | ||
728 | if (dev->dvb.frontend != NULL) { | ||
729 | dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; | ||
730 | } | ||
662 | } | 731 | } |
663 | break; | 732 | break; |
664 | #endif | 733 | #endif |
@@ -666,6 +735,11 @@ static int dvb_register(struct cx8802_dev *dev) | |||
666 | case CX88_BOARD_ATI_HDTVWONDER: | 735 | case CX88_BOARD_ATI_HDTVWONDER: |
667 | dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder, | 736 | dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder, |
668 | &dev->core->i2c_adap); | 737 | &dev->core->i2c_adap); |
738 | if (dev->dvb.frontend != NULL) { | ||
739 | dvb_pll_attach(dev->dvb.frontend, 0x61, | ||
740 | &dev->core->i2c_adap, | ||
741 | &dvb_pll_tuv1236d); | ||
742 | } | ||
669 | break; | 743 | break; |
670 | #endif | 744 | #endif |
671 | #ifdef HAVE_CX24123 | 745 | #ifdef HAVE_CX24123 |
@@ -673,10 +747,18 @@ static int dvb_register(struct cx8802_dev *dev) | |||
673 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | 747 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: |
674 | dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config, | 748 | dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config, |
675 | &dev->core->i2c_adap); | 749 | &dev->core->i2c_adap); |
750 | if (dev->dvb.frontend) { | ||
751 | isl6421_attach(dev->dvb.frontend, &dev->core->i2c_adap, | ||
752 | 0x08, 0x00, 0x00); | ||
753 | } | ||
676 | break; | 754 | break; |
677 | case CX88_BOARD_KWORLD_DVBS_100: | 755 | case CX88_BOARD_KWORLD_DVBS_100: |
678 | dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config, | 756 | dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config, |
679 | &dev->core->i2c_adap); | 757 | &dev->core->i2c_adap); |
758 | if (dev->dvb.frontend) { | ||
759 | dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; | ||
760 | dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; | ||
761 | } | ||
680 | break; | 762 | break; |
681 | #endif | 763 | #endif |
682 | default: | 764 | default: |
@@ -690,15 +772,15 @@ static int dvb_register(struct cx8802_dev *dev) | |||
690 | } | 772 | } |
691 | 773 | ||
692 | if (dev->core->pll_desc) { | 774 | if (dev->core->pll_desc) { |
693 | dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min; | 775 | dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; |
694 | dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max; | 776 | dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; |
695 | } | 777 | } |
696 | 778 | ||
697 | /* Put the analog decoder in standby to keep it quiet */ | 779 | /* Put the analog decoder in standby to keep it quiet */ |
698 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | 780 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); |
699 | 781 | ||
700 | /* register everything */ | 782 | /* register everything */ |
701 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); | 783 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev); |
702 | } | 784 | } |
703 | 785 | ||
704 | /* ----------------------------------------------------------- */ | 786 | /* ----------------------------------------------------------- */ |
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index f720901e9638..7efa6def0bde 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c | |||
@@ -138,13 +138,13 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) | |||
138 | return; | 138 | return; |
139 | 139 | ||
140 | if (core->dvbdev) { | 140 | if (core->dvbdev) { |
141 | if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl) | 141 | if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) |
142 | core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); | 142 | core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); |
143 | 143 | ||
144 | i2c_clients_command(&core->i2c_adap, cmd, arg); | 144 | i2c_clients_command(&core->i2c_adap, cmd, arg); |
145 | 145 | ||
146 | if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl) | 146 | if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) |
147 | core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0); | 147 | core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0); |
148 | } else | 148 | } else |
149 | i2c_clients_command(&core->i2c_adap, cmd, arg); | 149 | i2c_clients_command(&core->i2c_adap, cmd, arg); |
150 | } | 150 | } |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 78a63b7dd380..72b630a91f41 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -70,14 +70,33 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); | |||
70 | static void cx88_ir_handle_key(struct cx88_IR *ir) | 70 | static void cx88_ir_handle_key(struct cx88_IR *ir) |
71 | { | 71 | { |
72 | struct cx88_core *core = ir->core; | 72 | struct cx88_core *core = ir->core; |
73 | u32 gpio, data; | 73 | u32 gpio, data, auxgpio; |
74 | 74 | ||
75 | /* read gpio value */ | 75 | /* read gpio value */ |
76 | gpio = cx_read(ir->gpio_addr); | 76 | gpio = cx_read(ir->gpio_addr); |
77 | if (core->board == CX88_BOARD_NPGTECH_REALTV_TOP10FM) { | ||
78 | /* This board apparently uses a combination of 2 GPIO | ||
79 | to represent the keys. Additionally, the second GPIO | ||
80 | can be used for parity. | ||
81 | |||
82 | Example: | ||
83 | |||
84 | for key "5" | ||
85 | gpio = 0x758, auxgpio = 0xe5 or 0xf5 | ||
86 | for key "Power" | ||
87 | gpio = 0x758, auxgpio = 0xed or 0xfd | ||
88 | */ | ||
89 | |||
90 | auxgpio = cx_read(MO_GP1_IO); | ||
91 | /* Take out the parity part */ | ||
92 | gpio+=(gpio & 0x7fd) + (auxgpio & 0xef); | ||
93 | } else | ||
94 | auxgpio = gpio; | ||
95 | |||
77 | if (ir->polling) { | 96 | if (ir->polling) { |
78 | if (ir->last_gpio == gpio) | 97 | if (ir->last_gpio == auxgpio) |
79 | return; | 98 | return; |
80 | ir->last_gpio = gpio; | 99 | ir->last_gpio = auxgpio; |
81 | } | 100 | } |
82 | 101 | ||
83 | /* extract data */ | 102 | /* extract data */ |
@@ -172,12 +191,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
172 | ir_type = IR_TYPE_RC5; | 191 | ir_type = IR_TYPE_RC5; |
173 | ir->sampling = 1; | 192 | ir->sampling = 1; |
174 | break; | 193 | break; |
194 | case CX88_BOARD_WINFAST_DTV2000H: | ||
175 | case CX88_BOARD_WINFAST2000XP_EXPERT: | 195 | case CX88_BOARD_WINFAST2000XP_EXPERT: |
176 | ir_codes = ir_codes_winfast; | 196 | ir_codes = ir_codes_winfast; |
177 | ir->gpio_addr = MO_GP0_IO; | 197 | ir->gpio_addr = MO_GP0_IO; |
178 | ir->mask_keycode = 0x8f8; | 198 | ir->mask_keycode = 0x8f8; |
179 | ir->mask_keyup = 0x100; | 199 | ir->mask_keyup = 0x100; |
180 | ir->polling = 1; /* ms */ | 200 | ir->polling = 50; /* ms */ |
181 | break; | 201 | break; |
182 | case CX88_BOARD_IODATA_GVBCTV7E: | 202 | case CX88_BOARD_IODATA_GVBCTV7E: |
183 | ir_codes = ir_codes_iodata_bctv7e; | 203 | ir_codes = ir_codes_iodata_bctv7e; |
@@ -228,6 +248,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
228 | ir_type = IR_TYPE_PD; | 248 | ir_type = IR_TYPE_PD; |
229 | ir->sampling = 0xff00; /* address */ | 249 | ir->sampling = 0xff00; /* address */ |
230 | break; | 250 | break; |
251 | case CX88_BOARD_NPGTECH_REALTV_TOP10FM: | ||
252 | ir_codes = ir_codes_npgtech; | ||
253 | ir->gpio_addr = MO_GP0_IO; | ||
254 | ir->mask_keycode = 0xfa; | ||
255 | ir->polling = 50; /* ms */ | ||
256 | break; | ||
231 | } | 257 | } |
232 | 258 | ||
233 | if (NULL == ir_codes) { | 259 | if (NULL == ir_codes) { |
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 7d16888b4a86..a9d7795a8e14 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -54,7 +54,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
54 | { | 54 | { |
55 | struct cx88_core *core = dev->core; | 55 | struct cx88_core *core = dev->core; |
56 | 56 | ||
57 | dprintk(0, "cx8802_start_dma w: %d, h: %d, f: %d\n", dev->width, dev->height, buf->vb.field); | 57 | dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", dev->width, dev->height, buf->vb.field); |
58 | 58 | ||
59 | /* setup fifo + format */ | 59 | /* setup fifo + format */ |
60 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], | 60 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], |
@@ -76,6 +76,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
76 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: | 76 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: |
77 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: | 77 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: |
78 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: | 78 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: |
79 | case CX88_BOARD_PCHDTV_HD5500: | ||
79 | cx_write(TS_SOP_STAT, 1<<13); | 80 | cx_write(TS_SOP_STAT, 1<<13); |
80 | break; | 81 | break; |
81 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | 82 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: |
@@ -109,7 +110,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
109 | q->count = 1; | 110 | q->count = 1; |
110 | 111 | ||
111 | /* enable irqs */ | 112 | /* enable irqs */ |
112 | dprintk( 0, "setting the interrupt mask\n" ); | 113 | dprintk( 1, "setting the interrupt mask\n" ); |
113 | cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04); | 114 | cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04); |
114 | cx_set(MO_TS_INTMSK, 0x1f0011); | 115 | cx_set(MO_TS_INTMSK, 0x1f0011); |
115 | 116 | ||
@@ -122,7 +123,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
122 | static int cx8802_stop_dma(struct cx8802_dev *dev) | 123 | static int cx8802_stop_dma(struct cx8802_dev *dev) |
123 | { | 124 | { |
124 | struct cx88_core *core = dev->core; | 125 | struct cx88_core *core = dev->core; |
125 | dprintk( 0, "cx8802_stop_dma\n" ); | 126 | dprintk( 1, "cx8802_stop_dma\n" ); |
126 | 127 | ||
127 | /* stop dma */ | 128 | /* stop dma */ |
128 | cx_clear(MO_TS_DMACNTRL, 0x11); | 129 | cx_clear(MO_TS_DMACNTRL, 0x11); |
@@ -142,10 +143,43 @@ static int cx8802_restart_queue(struct cx8802_dev *dev, | |||
142 | struct cx88_buffer *buf; | 143 | struct cx88_buffer *buf; |
143 | struct list_head *item; | 144 | struct list_head *item; |
144 | 145 | ||
145 | dprintk( 0, "cx8802_restart_queue\n" ); | 146 | dprintk( 1, "cx8802_restart_queue\n" ); |
146 | if (list_empty(&q->active)) | 147 | if (list_empty(&q->active)) |
147 | { | 148 | { |
148 | dprintk( 0, "cx8802_restart_queue: queue is empty\n" ); | 149 | struct cx88_buffer *prev; |
150 | prev = NULL; | ||
151 | |||
152 | dprintk(1, "cx8802_restart_queue: queue is empty\n" ); | ||
153 | |||
154 | for (;;) { | ||
155 | if (list_empty(&q->queued)) | ||
156 | return 0; | ||
157 | buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); | ||
158 | if (NULL == prev) { | ||
159 | list_del(&buf->vb.queue); | ||
160 | list_add_tail(&buf->vb.queue,&q->active); | ||
161 | cx8802_start_dma(dev, q, buf); | ||
162 | buf->vb.state = STATE_ACTIVE; | ||
163 | buf->count = q->count++; | ||
164 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
165 | dprintk(1,"[%p/%d] restart_queue - first active\n", | ||
166 | buf,buf->vb.i); | ||
167 | |||
168 | } else if (prev->vb.width == buf->vb.width && | ||
169 | prev->vb.height == buf->vb.height && | ||
170 | prev->fmt == buf->fmt) { | ||
171 | list_del(&buf->vb.queue); | ||
172 | list_add_tail(&buf->vb.queue,&q->active); | ||
173 | buf->vb.state = STATE_ACTIVE; | ||
174 | buf->count = q->count++; | ||
175 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
176 | dprintk(1,"[%p/%d] restart_queue - move to active\n", | ||
177 | buf,buf->vb.i); | ||
178 | } else { | ||
179 | return 0; | ||
180 | } | ||
181 | prev = buf; | ||
182 | } | ||
149 | return 0; | 183 | return 0; |
150 | } | 184 | } |
151 | 185 | ||
@@ -204,13 +238,13 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) | |||
204 | buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma); | 238 | buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma); |
205 | 239 | ||
206 | if (list_empty(&cx88q->active)) { | 240 | if (list_empty(&cx88q->active)) { |
207 | dprintk( 0, "queue is empty - first active\n" ); | 241 | dprintk( 1, "queue is empty - first active\n" ); |
208 | list_add_tail(&buf->vb.queue,&cx88q->active); | 242 | list_add_tail(&buf->vb.queue,&cx88q->active); |
209 | cx8802_start_dma(dev, cx88q, buf); | 243 | cx8802_start_dma(dev, cx88q, buf); |
210 | buf->vb.state = STATE_ACTIVE; | 244 | buf->vb.state = STATE_ACTIVE; |
211 | buf->count = cx88q->count++; | 245 | buf->count = cx88q->count++; |
212 | mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT); | 246 | mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT); |
213 | dprintk(0,"[%p/%d] %s - first active\n", | 247 | dprintk(1,"[%p/%d] %s - first active\n", |
214 | buf, buf->vb.i, __FUNCTION__); | 248 | buf, buf->vb.i, __FUNCTION__); |
215 | 249 | ||
216 | } else { | 250 | } else { |
@@ -244,7 +278,7 @@ static void do_cancel_buffers(struct cx8802_dev *dev, char *reason, int restart) | |||
244 | } | 278 | } |
245 | if (restart) | 279 | if (restart) |
246 | { | 280 | { |
247 | dprintk(0, "restarting queue\n" ); | 281 | dprintk(1, "restarting queue\n" ); |
248 | cx8802_restart_queue(dev,q); | 282 | cx8802_restart_queue(dev,q); |
249 | } | 283 | } |
250 | spin_unlock_irqrestore(&dev->slock,flags); | 284 | spin_unlock_irqrestore(&dev->slock,flags); |
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 641a0c5a6490..1e4278b588d8 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <linux/init.h> | 52 | #include <linux/init.h> |
53 | #include <linux/smp_lock.h> | 53 | #include <linux/smp_lock.h> |
54 | #include <linux/delay.h> | 54 | #include <linux/delay.h> |
55 | #include <linux/config.h> | ||
55 | #include <linux/kthread.h> | 56 | #include <linux/kthread.h> |
56 | 57 | ||
57 | #include "cx88.h" | 58 | #include "cx88.h" |
@@ -137,21 +138,28 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) | |||
137 | { | 138 | { |
138 | u32 volume; | 139 | u32 volume; |
139 | 140 | ||
140 | #ifndef USING_CX88_ALSA | 141 | #ifndef CONFIG_VIDEO_CX88_ALSA |
141 | /* restart dma; This avoids buzz in NICAM and is good in others */ | 142 | /* restart dma; This avoids buzz in NICAM and is good in others */ |
142 | cx88_stop_audio_dma(core); | 143 | cx88_stop_audio_dma(core); |
143 | #endif | 144 | #endif |
144 | cx_write(AUD_RATE_THRES_DMD, 0x000000C0); | 145 | cx_write(AUD_RATE_THRES_DMD, 0x000000C0); |
145 | #ifndef USING_CX88_ALSA | 146 | #ifndef CONFIG_VIDEO_CX88_ALSA |
146 | cx88_start_audio_dma(core); | 147 | cx88_start_audio_dma(core); |
147 | #endif | 148 | #endif |
148 | 149 | ||
149 | if (cx88_boards[core->board].blackbird) { | 150 | if (cx88_boards[core->board].blackbird) { |
150 | /* sets sound input from external adc */ | 151 | /* sets sound input from external adc */ |
151 | if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN) | 152 | switch (core->board) { |
153 | case CX88_BOARD_HAUPPAUGE_ROSLYN: | ||
154 | case CX88_BOARD_KWORLD_MCE200_DELUXE: | ||
155 | case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT: | ||
156 | case CX88_BOARD_PIXELVIEW_PLAYTV_P7000: | ||
157 | case CX88_BOARD_ASUS_PVR_416: | ||
152 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); | 158 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); |
153 | else | 159 | break; |
160 | default: | ||
154 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); | 161 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); |
162 | } | ||
155 | 163 | ||
156 | cx_write(AUD_I2SINPUTCNTL, 4); | 164 | cx_write(AUD_I2SINPUTCNTL, 4); |
157 | cx_write(AUD_BAUDRATE, 1); | 165 | cx_write(AUD_BAUDRATE, 1); |
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index 846faadc9f1c..aa2a69770098 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c | |||
@@ -34,8 +34,8 @@ void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f) | |||
34 | if (dev->core->tvnorm->id & V4L2_STD_525_60) { | 34 | if (dev->core->tvnorm->id & V4L2_STD_525_60) { |
35 | /* ntsc */ | 35 | /* ntsc */ |
36 | f->fmt.vbi.sampling_rate = 28636363; | 36 | f->fmt.vbi.sampling_rate = 28636363; |
37 | f->fmt.vbi.start[0] = 10 -1; | 37 | f->fmt.vbi.start[0] = 10; |
38 | f->fmt.vbi.start[1] = 273 -1; | 38 | f->fmt.vbi.start[1] = 273; |
39 | 39 | ||
40 | } else if (dev->core->tvnorm->id & V4L2_STD_625_50) { | 40 | } else if (dev->core->tvnorm->id & V4L2_STD_625_50) { |
41 | /* pal */ | 41 | /* pal */ |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 326a25f147f6..dc7bc35f18f4 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -25,9 +25,11 @@ | |||
25 | #include <linux/videodev2.h> | 25 | #include <linux/videodev2.h> |
26 | #include <linux/kdev_t.h> | 26 | #include <linux/kdev_t.h> |
27 | 27 | ||
28 | #include <media/v4l2-common.h> | ||
28 | #include <media/tuner.h> | 29 | #include <media/tuner.h> |
29 | #include <media/tveeprom.h> | 30 | #include <media/tveeprom.h> |
30 | #include <media/video-buf.h> | 31 | #include <media/video-buf.h> |
32 | #include <media/cx2341x.h> | ||
31 | #include <media/video-buf-dvb.h> | 33 | #include <media/video-buf-dvb.h> |
32 | 34 | ||
33 | #include "btcx-risc.h" | 35 | #include "btcx-risc.h" |
@@ -35,7 +37,7 @@ | |||
35 | 37 | ||
36 | #include <linux/version.h> | 38 | #include <linux/version.h> |
37 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
38 | #define CX88_VERSION_CODE KERNEL_VERSION(0,0,5) | 40 | #define CX88_VERSION_CODE KERNEL_VERSION(0,0,6) |
39 | 41 | ||
40 | #ifndef TRUE | 42 | #ifndef TRUE |
41 | # define TRUE (1==1) | 43 | # define TRUE (1==1) |
@@ -189,6 +191,11 @@ extern struct sram_channel cx88_sram_channels[]; | |||
189 | #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44 | 191 | #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44 |
190 | #define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45 | 192 | #define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45 |
191 | #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46 | 193 | #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46 |
194 | #define CX88_BOARD_PCHDTV_HD5500 47 | ||
195 | #define CX88_BOARD_KWORLD_MCE200_DELUXE 48 | ||
196 | #define CX88_BOARD_PIXELVIEW_PLAYTV_P7000 49 | ||
197 | #define CX88_BOARD_NPGTECH_REALTV_TOP10FM 50 | ||
198 | #define CX88_BOARD_WINFAST_DTV2000H 51 | ||
192 | 199 | ||
193 | enum cx88_itype { | 200 | enum cx88_itype { |
194 | CX88_VMUX_COMPOSITE1 = 1, | 201 | CX88_VMUX_COMPOSITE1 = 1, |
@@ -296,6 +303,7 @@ struct cx88_core { | |||
296 | /* config info -- dvb */ | 303 | /* config info -- dvb */ |
297 | struct dvb_pll_desc *pll_desc; | 304 | struct dvb_pll_desc *pll_desc; |
298 | unsigned int pll_addr; | 305 | unsigned int pll_addr; |
306 | int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); | ||
299 | 307 | ||
300 | /* state info */ | 308 | /* state info */ |
301 | struct task_struct *kthread; | 309 | struct task_struct *kthread; |
@@ -391,14 +399,6 @@ struct cx8802_suspend_state { | |||
391 | int disabled; | 399 | int disabled; |
392 | }; | 400 | }; |
393 | 401 | ||
394 | /* TODO: move this to struct v4l2_mpeg_compression ? */ | ||
395 | struct blackbird_dnr { | ||
396 | u32 mode; | ||
397 | u32 type; | ||
398 | u32 spatial; | ||
399 | u32 temporal; | ||
400 | }; | ||
401 | |||
402 | struct cx8802_dev { | 402 | struct cx8802_dev { |
403 | struct cx88_core *core; | 403 | struct cx88_core *core; |
404 | spinlock_t slock; | 404 | spinlock_t slock; |
@@ -432,8 +432,7 @@ struct cx8802_dev { | |||
432 | unsigned char ts_gen_cntrl; | 432 | unsigned char ts_gen_cntrl; |
433 | 433 | ||
434 | /* mpeg params */ | 434 | /* mpeg params */ |
435 | struct v4l2_mpeg_compression params; | 435 | struct cx2341x_mpeg_params params; |
436 | struct blackbird_dnr dnr_params; | ||
437 | }; | 436 | }; |
438 | 437 | ||
439 | /* ----------------------------------------------------------- */ | 438 | /* ----------------------------------------------------------- */ |
@@ -598,10 +597,6 @@ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, | |||
598 | extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, | 597 | extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, |
599 | unsigned int cmd, void *arg); | 598 | unsigned int cmd, void *arg); |
600 | extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd); | 599 | extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd); |
601 | void blackbird_set_params(struct cx8802_dev *dev, | ||
602 | struct v4l2_mpeg_compression *params); | ||
603 | void blackbird_set_dnr_params(struct cx8802_dev *dev, | ||
604 | struct blackbird_dnr* dnr_params); | ||
605 | 600 | ||
606 | /* | 601 | /* |
607 | * Local variables: | 602 | * Local variables: |
diff --git a/drivers/media/video/dsbr100.c b/drivers/media/video/dsbr100.c index 3b4e9985c3d7..f7e33f9ee8e9 100644 --- a/drivers/media/video/dsbr100.c +++ b/drivers/media/video/dsbr100.c | |||
@@ -72,6 +72,7 @@ | |||
72 | #include <linux/slab.h> | 72 | #include <linux/slab.h> |
73 | #include <linux/input.h> | 73 | #include <linux/input.h> |
74 | #include <linux/videodev.h> | 74 | #include <linux/videodev.h> |
75 | #include <media/v4l2-common.h> | ||
75 | #include <linux/usb.h> | 76 | #include <linux/usb.h> |
76 | #include <linux/smp_lock.h> | 77 | #include <linux/smp_lock.h> |
77 | 78 | ||
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 3ba3439db580..ed882ebc7b95 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> | 4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> |
5 | Markus Rechberger <mrechberger@gmail.com> | 5 | Markus Rechberger <mrechberger@gmail.com> |
6 | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 6 | Mauro Carvalho Chehab <mchehab@infradead.org> |
7 | Sascha Sommer <saschasommer@freenet.de> | 7 | Sascha Sommer <saschasommer@freenet.de> |
8 | 8 | ||
9 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify |
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/usb.h> | 29 | #include <linux/usb.h> |
30 | #include <media/tuner.h> | 30 | #include <media/tuner.h> |
31 | #include <media/msp3400.h> | 31 | #include <media/msp3400.h> |
32 | #include <media/saa7115.h> | ||
33 | #include <media/tvp5150.h> | ||
32 | #include <media/tveeprom.h> | 34 | #include <media/tveeprom.h> |
33 | #include <media/audiochip.h> | 35 | #include <media/audiochip.h> |
34 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
@@ -46,11 +48,11 @@ struct em28xx_board em28xx_boards[] = { | |||
46 | .decoder = EM28XX_SAA7113, | 48 | .decoder = EM28XX_SAA7113, |
47 | .input = {{ | 49 | .input = {{ |
48 | .type = EM28XX_VMUX_COMPOSITE1, | 50 | .type = EM28XX_VMUX_COMPOSITE1, |
49 | .vmux = 0, | 51 | .vmux = SAA7115_COMPOSITE0, |
50 | .amux = 1, | 52 | .amux = 1, |
51 | },{ | 53 | },{ |
52 | .type = EM28XX_VMUX_SVIDEO, | 54 | .type = EM28XX_VMUX_SVIDEO, |
53 | .vmux = 9, | 55 | .vmux = SAA7115_SVIDEO3, |
54 | .amux = 1, | 56 | .amux = 1, |
55 | }}, | 57 | }}, |
56 | }, | 58 | }, |
@@ -64,11 +66,11 @@ struct em28xx_board em28xx_boards[] = { | |||
64 | .decoder = EM28XX_SAA7113, | 66 | .decoder = EM28XX_SAA7113, |
65 | .input = {{ | 67 | .input = {{ |
66 | .type = EM28XX_VMUX_COMPOSITE1, | 68 | .type = EM28XX_VMUX_COMPOSITE1, |
67 | .vmux = 0, | 69 | .vmux = SAA7115_COMPOSITE0, |
68 | .amux = 1, | 70 | .amux = 1, |
69 | },{ | 71 | },{ |
70 | .type = EM28XX_VMUX_SVIDEO, | 72 | .type = EM28XX_VMUX_SVIDEO, |
71 | .vmux = 9, | 73 | .vmux = SAA7115_SVIDEO3, |
72 | .amux = 1, | 74 | .amux = 1, |
73 | }}, | 75 | }}, |
74 | }, | 76 | }, |
@@ -82,11 +84,11 @@ struct em28xx_board em28xx_boards[] = { | |||
82 | .decoder = EM28XX_SAA7113, | 84 | .decoder = EM28XX_SAA7113, |
83 | .input = {{ | 85 | .input = {{ |
84 | .type = EM28XX_VMUX_COMPOSITE1, | 86 | .type = EM28XX_VMUX_COMPOSITE1, |
85 | .vmux = 0, | 87 | .vmux = SAA7115_COMPOSITE0, |
86 | .amux = 1, | 88 | .amux = 1, |
87 | },{ | 89 | },{ |
88 | .type = EM28XX_VMUX_SVIDEO, | 90 | .type = EM28XX_VMUX_SVIDEO, |
89 | .vmux = 9, | 91 | .vmux = SAA7115_SVIDEO3, |
90 | .amux = 1, | 92 | .amux = 1, |
91 | }}, | 93 | }}, |
92 | }, | 94 | }, |
@@ -100,15 +102,15 @@ struct em28xx_board em28xx_boards[] = { | |||
100 | .decoder = EM28XX_SAA7113, | 102 | .decoder = EM28XX_SAA7113, |
101 | .input = {{ | 103 | .input = {{ |
102 | .type = EM28XX_VMUX_TELEVISION, | 104 | .type = EM28XX_VMUX_TELEVISION, |
103 | .vmux = 2, | 105 | .vmux = SAA7115_COMPOSITE2, |
104 | .amux = 1, | 106 | .amux = 1, |
105 | },{ | 107 | },{ |
106 | .type = EM28XX_VMUX_COMPOSITE1, | 108 | .type = EM28XX_VMUX_COMPOSITE1, |
107 | .vmux = 0, | 109 | .vmux = SAA7115_COMPOSITE0, |
108 | .amux = 1, | 110 | .amux = 1, |
109 | },{ | 111 | },{ |
110 | .type = EM28XX_VMUX_SVIDEO, | 112 | .type = EM28XX_VMUX_SVIDEO, |
111 | .vmux = 9, | 113 | .vmux = SAA7115_SVIDEO3, |
112 | .amux = 1, | 114 | .amux = 1, |
113 | }}, | 115 | }}, |
114 | }, | 116 | }, |
@@ -122,15 +124,15 @@ struct em28xx_board em28xx_boards[] = { | |||
122 | .decoder = EM28XX_SAA7113, | 124 | .decoder = EM28XX_SAA7113, |
123 | .input = {{ | 125 | .input = {{ |
124 | .type = EM28XX_VMUX_TELEVISION, | 126 | .type = EM28XX_VMUX_TELEVISION, |
125 | .vmux = 2, | 127 | .vmux = SAA7115_COMPOSITE2, |
126 | .amux = 0, | 128 | .amux = 0, |
127 | },{ | 129 | },{ |
128 | .type = EM28XX_VMUX_COMPOSITE1, | 130 | .type = EM28XX_VMUX_COMPOSITE1, |
129 | .vmux = 0, | 131 | .vmux = SAA7115_COMPOSITE0, |
130 | .amux = 1, | 132 | .amux = 1, |
131 | },{ | 133 | },{ |
132 | .type = EM28XX_VMUX_SVIDEO, | 134 | .type = EM28XX_VMUX_SVIDEO, |
133 | .vmux = 9, | 135 | .vmux = SAA7115_SVIDEO3, |
134 | .amux = 1, | 136 | .amux = 1, |
135 | }}, | 137 | }}, |
136 | }, | 138 | }, |
@@ -146,11 +148,11 @@ struct em28xx_board em28xx_boards[] = { | |||
146 | /*FIXME: S-Video not tested */ | 148 | /*FIXME: S-Video not tested */ |
147 | .input = {{ | 149 | .input = {{ |
148 | .type = EM28XX_VMUX_TELEVISION, | 150 | .type = EM28XX_VMUX_TELEVISION, |
149 | .vmux = 0, | 151 | .vmux = TVP5150_COMPOSITE0, |
150 | .amux = MSP_INPUT_DEFAULT, | 152 | .amux = MSP_INPUT_DEFAULT, |
151 | },{ | 153 | },{ |
152 | .type = EM28XX_VMUX_SVIDEO, | 154 | .type = EM28XX_VMUX_SVIDEO, |
153 | .vmux = 2, | 155 | .vmux = TVP5150_SVIDEO, |
154 | .amux = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, | 156 | .amux = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, |
155 | MSP_DSP_IN_SCART, MSP_DSP_IN_SCART), | 157 | MSP_DSP_IN_SCART, MSP_DSP_IN_SCART), |
156 | }}, | 158 | }}, |
@@ -165,15 +167,15 @@ struct em28xx_board em28xx_boards[] = { | |||
165 | .decoder = EM28XX_SAA7114, | 167 | .decoder = EM28XX_SAA7114, |
166 | .input = {{ | 168 | .input = {{ |
167 | .type = EM28XX_VMUX_TELEVISION, | 169 | .type = EM28XX_VMUX_TELEVISION, |
168 | .vmux = 4, | 170 | .vmux = SAA7115_COMPOSITE4, |
169 | .amux = 0, | 171 | .amux = 0, |
170 | },{ | 172 | },{ |
171 | .type = EM28XX_VMUX_COMPOSITE1, | 173 | .type = EM28XX_VMUX_COMPOSITE1, |
172 | .vmux = 0, | 174 | .vmux = SAA7115_COMPOSITE0, |
173 | .amux = 1, | 175 | .amux = 1, |
174 | },{ | 176 | },{ |
175 | .type = EM28XX_VMUX_SVIDEO, | 177 | .type = EM28XX_VMUX_SVIDEO, |
176 | .vmux = 9, | 178 | .vmux = SAA7115_SVIDEO3, |
177 | .amux = 1, | 179 | .amux = 1, |
178 | }}, | 180 | }}, |
179 | }, | 181 | }, |
@@ -188,15 +190,15 @@ struct em28xx_board em28xx_boards[] = { | |||
188 | .decoder = EM28XX_SAA7113, | 190 | .decoder = EM28XX_SAA7113, |
189 | .input = {{ | 191 | .input = {{ |
190 | .type = EM28XX_VMUX_TELEVISION, | 192 | .type = EM28XX_VMUX_TELEVISION, |
191 | .vmux = 2, | 193 | .vmux = SAA7115_COMPOSITE2, |
192 | .amux = 0, | 194 | .amux = 0, |
193 | },{ | 195 | },{ |
194 | .type = EM28XX_VMUX_COMPOSITE1, | 196 | .type = EM28XX_VMUX_COMPOSITE1, |
195 | .vmux = 0, | 197 | .vmux = SAA7115_COMPOSITE0, |
196 | .amux = 1, | 198 | .amux = 1, |
197 | },{ | 199 | },{ |
198 | .type = EM28XX_VMUX_SVIDEO, | 200 | .type = EM28XX_VMUX_SVIDEO, |
199 | .vmux = 9, | 201 | .vmux = SAA7115_SVIDEO3, |
200 | .amux = 1, | 202 | .amux = 1, |
201 | }}, | 203 | }}, |
202 | }, | 204 | }, |
@@ -211,15 +213,15 @@ struct em28xx_board em28xx_boards[] = { | |||
211 | .decoder = EM28XX_SAA7113, | 213 | .decoder = EM28XX_SAA7113, |
212 | .input = {{ | 214 | .input = {{ |
213 | .type = EM28XX_VMUX_TELEVISION, | 215 | .type = EM28XX_VMUX_TELEVISION, |
214 | .vmux = 2, | 216 | .vmux = SAA7115_COMPOSITE2, |
215 | .amux = 0, | 217 | .amux = 0, |
216 | },{ | 218 | },{ |
217 | .type = EM28XX_VMUX_COMPOSITE1, | 219 | .type = EM28XX_VMUX_COMPOSITE1, |
218 | .vmux = 0, | 220 | .vmux = SAA7115_COMPOSITE0, |
219 | .amux = 1, | 221 | .amux = 1, |
220 | },{ | 222 | },{ |
221 | .type = EM28XX_VMUX_SVIDEO, | 223 | .type = EM28XX_VMUX_SVIDEO, |
222 | .vmux = 9, | 224 | .vmux = SAA7115_SVIDEO3, |
223 | .amux = 1, | 225 | .amux = 1, |
224 | }}, | 226 | }}, |
225 | }, | 227 | }, |
@@ -234,15 +236,15 @@ struct em28xx_board em28xx_boards[] = { | |||
234 | .decoder = EM28XX_SAA7113, | 236 | .decoder = EM28XX_SAA7113, |
235 | .input = {{ | 237 | .input = {{ |
236 | .type = EM28XX_VMUX_TELEVISION, | 238 | .type = EM28XX_VMUX_TELEVISION, |
237 | .vmux = 2, | 239 | .vmux = SAA7115_COMPOSITE2, |
238 | .amux = 0, | 240 | .amux = 0, |
239 | },{ | 241 | },{ |
240 | .type = EM28XX_VMUX_COMPOSITE1, | 242 | .type = EM28XX_VMUX_COMPOSITE1, |
241 | .vmux = 0, | 243 | .vmux = SAA7115_COMPOSITE0, |
242 | .amux = 1, | 244 | .amux = 1, |
243 | },{ | 245 | },{ |
244 | .type = EM28XX_VMUX_SVIDEO, | 246 | .type = EM28XX_VMUX_SVIDEO, |
245 | .vmux = 9, | 247 | .vmux = SAA7115_SVIDEO3, |
246 | .amux = 1, | 248 | .amux = 1, |
247 | }}, | 249 | }}, |
248 | }, | 250 | }, |
@@ -254,11 +256,11 @@ struct em28xx_board em28xx_boards[] = { | |||
254 | .decoder = EM28XX_SAA7113, | 256 | .decoder = EM28XX_SAA7113, |
255 | .input = {{ | 257 | .input = {{ |
256 | .type = EM28XX_VMUX_COMPOSITE1, | 258 | .type = EM28XX_VMUX_COMPOSITE1, |
257 | .vmux = 0, | 259 | .vmux = SAA7115_COMPOSITE0, |
258 | .amux = 1, | 260 | .amux = 1, |
259 | },{ | 261 | },{ |
260 | .type = EM28XX_VMUX_SVIDEO, | 262 | .type = EM28XX_VMUX_SVIDEO, |
261 | .vmux = 9, | 263 | .vmux = SAA7115_SVIDEO3, |
262 | .amux = 1, | 264 | .amux = 1, |
263 | }}, | 265 | }}, |
264 | }, | 266 | }, |
@@ -324,8 +326,4 @@ void em28xx_card_setup(struct em28xx *dev) | |||
324 | } | 326 | } |
325 | } | 327 | } |
326 | 328 | ||
327 | EXPORT_SYMBOL(em28xx_boards); | ||
328 | EXPORT_SYMBOL(em28xx_bcount); | ||
329 | EXPORT_SYMBOL(em28xx_id_table); | ||
330 | |||
331 | MODULE_DEVICE_TABLE (usb, em28xx_id_table); | 329 | MODULE_DEVICE_TABLE (usb, em28xx_id_table); |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index e5ee8bceb210..4350cc75b025 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> | 4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> |
5 | Markus Rechberger <mrechberger@gmail.com> | 5 | Markus Rechberger <mrechberger@gmail.com> |
6 | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 6 | Mauro Carvalho Chehab <mchehab@infradead.org> |
7 | Sascha Sommer <saschasommer@freenet.de> | 7 | Sascha Sommer <saschasommer@freenet.de> |
8 | 8 | ||
9 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify |
@@ -317,8 +317,8 @@ int em28xx_outfmt_set_yuv422(struct em28xx *dev) | |||
317 | return em28xx_write_regs(dev, VINCTRL_REG, "\x11", 1); | 317 | return em28xx_write_regs(dev, VINCTRL_REG, "\x11", 1); |
318 | } | 318 | } |
319 | 319 | ||
320 | int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin, | 320 | static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, |
321 | u8 ymax) | 321 | u8 ymin, u8 ymax) |
322 | { | 322 | { |
323 | em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax); | 323 | em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax); |
324 | 324 | ||
@@ -328,7 +328,7 @@ int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin, | |||
328 | return em28xx_write_regs(dev, YMAX_REG, &ymax, 1); | 328 | return em28xx_write_regs(dev, YMAX_REG, &ymax, 1); |
329 | } | 329 | } |
330 | 330 | ||
331 | int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, | 331 | static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, |
332 | u16 width, u16 height) | 332 | u16 width, u16 height) |
333 | { | 333 | { |
334 | u8 cwidth = width; | 334 | u8 cwidth = width; |
@@ -345,7 +345,7 @@ int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, | |||
345 | return em28xx_write_regs(dev, OFLOW_REG, &overflow, 1); | 345 | return em28xx_write_regs(dev, OFLOW_REG, &overflow, 1); |
346 | } | 346 | } |
347 | 347 | ||
348 | int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) | 348 | static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) |
349 | { | 349 | { |
350 | u8 mode; | 350 | u8 mode; |
351 | /* the em2800 scaler only supports scaling down to 50% */ | 351 | /* the em2800 scaler only supports scaling down to 50% */ |
@@ -534,7 +534,7 @@ static inline void em28xx_isoc_video_copy(struct em28xx *dev, | |||
534 | * em28xx_isoIrq() | 534 | * em28xx_isoIrq() |
535 | * handles the incoming isoc urbs and fills the frames from our inqueue | 535 | * handles the incoming isoc urbs and fills the frames from our inqueue |
536 | */ | 536 | */ |
537 | void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs) | 537 | static void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs) |
538 | { | 538 | { |
539 | struct em28xx *dev = urb->context; | 539 | struct em28xx *dev = urb->context; |
540 | int i, status; | 540 | int i, status; |
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 5b6cece37aee..d829d8f8c1f6 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> | 4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> |
5 | Markus Rechberger <mrechberger@gmail.com> | 5 | Markus Rechberger <mrechberger@gmail.com> |
6 | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 6 | Mauro Carvalho Chehab <mchehab@infradead.org> |
7 | Sascha Sommer <saschasommer@freenet.de> | 7 | Sascha Sommer <saschasommer@freenet.de> |
8 | 8 | ||
9 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify |
@@ -399,17 +399,6 @@ static u32 functionality(struct i2c_adapter *adap) | |||
399 | return I2C_FUNC_SMBUS_EMUL; | 399 | return I2C_FUNC_SMBUS_EMUL; |
400 | } | 400 | } |
401 | 401 | ||
402 | #ifndef I2C_PEC | ||
403 | static void inc_use(struct i2c_adapter *adap) | ||
404 | { | ||
405 | MOD_INC_USE_COUNT; | ||
406 | } | ||
407 | |||
408 | static void dec_use(struct i2c_adapter *adap) | ||
409 | { | ||
410 | MOD_DEC_USE_COUNT; | ||
411 | } | ||
412 | #endif | ||
413 | 402 | ||
414 | static int em28xx_set_tuner(int check_eeprom, struct i2c_client *client) | 403 | static int em28xx_set_tuner(int check_eeprom, struct i2c_client *client) |
415 | { | 404 | { |
@@ -436,9 +425,19 @@ static int attach_inform(struct i2c_client *client) | |||
436 | struct em28xx *dev = client->adapter->algo_data; | 425 | struct em28xx *dev = client->adapter->algo_data; |
437 | 426 | ||
438 | switch (client->addr << 1) { | 427 | switch (client->addr << 1) { |
439 | case 0x86: | 428 | case 0x43: |
429 | case 0x4b: | ||
430 | { | ||
431 | struct tuner_setup tun_setup; | ||
432 | |||
433 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | ||
434 | tun_setup.type = TUNER_TDA9887; | ||
435 | tun_setup.addr = client->addr; | ||
436 | |||
437 | em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); | ||
440 | em28xx_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); | 438 | em28xx_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); |
441 | break; | 439 | break; |
440 | } | ||
442 | case 0x42: | 441 | case 0x42: |
443 | dprintk1(1,"attach_inform: saa7114 detected.\n"); | 442 | dprintk1(1,"attach_inform: saa7114 detected.\n"); |
444 | break; | 443 | break; |
@@ -464,6 +463,7 @@ static int attach_inform(struct i2c_client *client) | |||
464 | case 0xba: | 463 | case 0xba: |
465 | dprintk1(1,"attach_inform: tvp5150 detected.\n"); | 464 | dprintk1(1,"attach_inform: tvp5150 detected.\n"); |
466 | break; | 465 | break; |
466 | |||
467 | default: | 467 | default: |
468 | dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1); | 468 | dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1); |
469 | dev->tuner_addr = client->addr; | 469 | dev->tuner_addr = client->addr; |
@@ -480,12 +480,7 @@ static struct i2c_algorithm em28xx_algo = { | |||
480 | }; | 480 | }; |
481 | 481 | ||
482 | static struct i2c_adapter em28xx_adap_template = { | 482 | static struct i2c_adapter em28xx_adap_template = { |
483 | #ifdef I2C_PEC | ||
484 | .owner = THIS_MODULE, | 483 | .owner = THIS_MODULE, |
485 | #else | ||
486 | .inc_use = inc_use, | ||
487 | .dec_use = dec_use, | ||
488 | #endif | ||
489 | .class = I2C_CLASS_TV_ANALOG, | 484 | .class = I2C_CLASS_TV_ANALOG, |
490 | .name = "em28xx", | 485 | .name = "em28xx", |
491 | .id = I2C_HW_B_EM28XX, | 486 | .id = I2C_HW_B_EM28XX, |
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 31e89e4f18be..3ffb5684f127 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> | 4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> |
5 | Markus Rechberger <mrechberger@gmail.com> | 5 | Markus Rechberger <mrechberger@gmail.com> |
6 | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 6 | Mauro Carvalho Chehab <mchehab@infradead.org> |
7 | Sascha Sommer <saschasommer@freenet.de> | 7 | Sascha Sommer <saschasommer@freenet.de> |
8 | 8 | ||
9 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify |
@@ -105,7 +105,7 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
105 | return 1; | 105 | return 1; |
106 | } | 106 | } |
107 | 107 | ||
108 | static int get_key_pinnacle_usb(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | 108 | static int get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) |
109 | { | 109 | { |
110 | unsigned char buf[3]; | 110 | unsigned char buf[3]; |
111 | 111 | ||
@@ -148,8 +148,8 @@ void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir) | |||
148 | snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)"); | 148 | snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)"); |
149 | break; | 149 | break; |
150 | case (EM2820_BOARD_PINNACLE_USB_2): | 150 | case (EM2820_BOARD_PINNACLE_USB_2): |
151 | ir->ir_codes = ir_codes_em_pinnacle_usb; | 151 | ir->ir_codes = ir_codes_pinnacle_grey; |
152 | ir->get_key = get_key_pinnacle_usb; | 152 | ir->get_key = get_key_pinnacle_usb_grey; |
153 | snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)"); | 153 | snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)"); |
154 | break; | 154 | break; |
155 | case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): | 155 | case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index cf7cdf9ef617..9286090817cd 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> | 4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> |
5 | Markus Rechberger <mrechberger@gmail.com> | 5 | Markus Rechberger <mrechberger@gmail.com> |
6 | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 6 | Mauro Carvalho Chehab <mchehab@infradead.org> |
7 | Sascha Sommer <saschasommer@freenet.de> | 7 | Sascha Sommer <saschasommer@freenet.de> |
8 | 8 | ||
9 | Some parts based on SN9C10x PC Camera Controllers GPL driver made | 9 | Some parts based on SN9C10x PC Camera Controllers GPL driver made |
@@ -42,7 +42,7 @@ | |||
42 | 42 | ||
43 | #define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \ | 43 | #define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \ |
44 | "Markus Rechberger <mrechberger@gmail.com>, " \ | 44 | "Markus Rechberger <mrechberger@gmail.com>, " \ |
45 | "Mauro Carvalho Chehab <mchehab@brturbo.com.br>, " \ | 45 | "Mauro Carvalho Chehab <mchehab@infradead.org>, " \ |
46 | "Sascha Sommer <saschasommer@freenet.de>" | 46 | "Sascha Sommer <saschasommer@freenet.de>" |
47 | 47 | ||
48 | #define DRIVER_NAME "em28xx" | 48 | #define DRIVER_NAME "em28xx" |
@@ -170,8 +170,12 @@ static int em28xx_config(struct em28xx *dev) | |||
170 | static void em28xx_config_i2c(struct em28xx *dev) | 170 | static void em28xx_config_i2c(struct em28xx *dev) |
171 | { | 171 | { |
172 | struct v4l2_frequency f; | 172 | struct v4l2_frequency f; |
173 | struct v4l2_routing route; | ||
174 | |||
175 | route.input = INPUT(dev->ctl_input)->vmux; | ||
176 | route.output = 0; | ||
173 | em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL); | 177 | em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL); |
174 | em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &dev->ctl_input); | 178 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); |
175 | em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); | 179 | em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); |
176 | 180 | ||
177 | /* configure tuner */ | 181 | /* configure tuner */ |
@@ -206,19 +210,19 @@ static void em28xx_empty_framequeues(struct em28xx *dev) | |||
206 | 210 | ||
207 | static void video_mux(struct em28xx *dev, int index) | 211 | static void video_mux(struct em28xx *dev, int index) |
208 | { | 212 | { |
209 | int input, ainput; | 213 | int ainput; |
214 | struct v4l2_routing route; | ||
210 | 215 | ||
211 | input = INPUT(index)->vmux; | 216 | route.input = INPUT(index)->vmux; |
217 | route.output = 0; | ||
212 | dev->ctl_input = index; | 218 | dev->ctl_input = index; |
213 | dev->ctl_ainput = INPUT(index)->amux; | 219 | dev->ctl_ainput = INPUT(index)->amux; |
214 | 220 | ||
215 | em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &input); | 221 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); |
216 | 222 | ||
217 | em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput); | 223 | em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,route.input,dev->ctl_ainput); |
218 | 224 | ||
219 | if (dev->has_msp34xx) { | 225 | if (dev->has_msp34xx) { |
220 | struct v4l2_routing route; | ||
221 | |||
222 | if (dev->i2s_speed) | 226 | if (dev->i2s_speed) |
223 | em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed); | 227 | em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed); |
224 | route.input = dev->ctl_ainput; | 228 | route.input = dev->ctl_ainput; |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index e1ddc2f27a21..d8fcc9e17ac0 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> | 4 | Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> |
5 | Ludovico Cavedon <cavedon@sssup.it> | 5 | Ludovico Cavedon <cavedon@sssup.it> |
6 | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 6 | Mauro Carvalho Chehab <mchehab@infradead.org> |
7 | 7 | ||
8 | Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de> | 8 | Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de> |
9 | 9 | ||
@@ -319,13 +319,7 @@ int em28xx_audio_analog_set(struct em28xx *dev); | |||
319 | int em28xx_colorlevels_set_default(struct em28xx *dev); | 319 | int em28xx_colorlevels_set_default(struct em28xx *dev); |
320 | int em28xx_capture_start(struct em28xx *dev, int start); | 320 | int em28xx_capture_start(struct em28xx *dev, int start); |
321 | int em28xx_outfmt_set_yuv422(struct em28xx *dev); | 321 | int em28xx_outfmt_set_yuv422(struct em28xx *dev); |
322 | int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin, | ||
323 | u8 ymax); | ||
324 | int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, | ||
325 | u16 width, u16 height); | ||
326 | int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v); | ||
327 | int em28xx_resolution_set(struct em28xx *dev); | 322 | int em28xx_resolution_set(struct em28xx *dev); |
328 | void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs); | ||
329 | int em28xx_init_isoc(struct em28xx *dev); | 323 | int em28xx_init_isoc(struct em28xx *dev); |
330 | void em28xx_uninit_isoc(struct em28xx *dev); | 324 | void em28xx_uninit_isoc(struct em28xx *dev); |
331 | int em28xx_set_alternate(struct em28xx *dev); | 325 | int em28xx_set_alternate(struct em28xx *dev); |
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index dfc9dd732c9d..8992b6e62b9f 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c | |||
@@ -2341,11 +2341,9 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
2341 | case VIDIOC_G_CTRL: | 2341 | case VIDIOC_G_CTRL: |
2342 | return et61x251_vidioc_g_ctrl(cam, arg); | 2342 | return et61x251_vidioc_g_ctrl(cam, arg); |
2343 | 2343 | ||
2344 | case VIDIOC_S_CTRL_OLD: | ||
2345 | case VIDIOC_S_CTRL: | 2344 | case VIDIOC_S_CTRL: |
2346 | return et61x251_vidioc_s_ctrl(cam, arg); | 2345 | return et61x251_vidioc_s_ctrl(cam, arg); |
2347 | 2346 | ||
2348 | case VIDIOC_CROPCAP_OLD: | ||
2349 | case VIDIOC_CROPCAP: | 2347 | case VIDIOC_CROPCAP: |
2350 | return et61x251_vidioc_cropcap(cam, arg); | 2348 | return et61x251_vidioc_cropcap(cam, arg); |
2351 | 2349 | ||
@@ -2392,7 +2390,6 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
2392 | case VIDIOC_G_PARM: | 2390 | case VIDIOC_G_PARM: |
2393 | return et61x251_vidioc_g_parm(cam, arg); | 2391 | return et61x251_vidioc_g_parm(cam, arg); |
2394 | 2392 | ||
2395 | case VIDIOC_S_PARM_OLD: | ||
2396 | case VIDIOC_S_PARM: | 2393 | case VIDIOC_S_PARM: |
2397 | return et61x251_vidioc_s_parm(cam, arg); | 2394 | return et61x251_vidioc_s_parm(cam, arg); |
2398 | 2395 | ||
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 7e66d83fe0ce..fba30a40e9c6 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -150,12 +150,11 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
150 | return 1; | 150 | return 1; |
151 | } | 151 | } |
152 | 152 | ||
153 | /* The new pinnacle PCTV remote (with the colored buttons) | 153 | /* Common (grey or coloured) pinnacle PCTV remote handling |
154 | * | 154 | * |
155 | * Ricardo Cerqueira <v4l@cerqueira.org> | ||
156 | */ | 155 | */ |
157 | 156 | static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, | |
158 | int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | 157 | int parity_offset, int marker, int code_modulo) |
159 | { | 158 | { |
160 | unsigned char b[4]; | 159 | unsigned char b[4]; |
161 | unsigned int start = 0,parity = 0,code = 0; | 160 | unsigned int start = 0,parity = 0,code = 0; |
@@ -167,9 +166,9 @@ int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
167 | } | 166 | } |
168 | 167 | ||
169 | for (start = 0; start<4; start++) { | 168 | for (start = 0; start<4; start++) { |
170 | if (b[start] == 0x80) { | 169 | if (b[start] == marker) { |
171 | code=b[(start+3)%4]; | 170 | code=b[(start+parity_offset+1)%4]; |
172 | parity=b[(start+2)%4]; | 171 | parity=b[(start+parity_offset)%4]; |
173 | } | 172 | } |
174 | } | 173 | } |
175 | 174 | ||
@@ -181,16 +180,14 @@ int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
181 | if (ir->old == parity) | 180 | if (ir->old == parity) |
182 | return 0; | 181 | return 0; |
183 | 182 | ||
184 | |||
185 | ir->old = parity; | 183 | ir->old = parity; |
186 | 184 | ||
187 | /* Reduce code value to fit inside IR_KEYTAB_SIZE | 185 | /* drop special codes when a key is held down a long time for the grey controller |
188 | * | 186 | In this case, the second bit of the code is asserted */ |
189 | * this is the only value that results in 42 unique | 187 | if (marker == 0xfe && (code & 0x40)) |
190 | * codes < 128 | 188 | return 0; |
191 | */ | ||
192 | 189 | ||
193 | code %= 0x88; | 190 | code %= code_modulo; |
194 | 191 | ||
195 | *ir_raw = code; | 192 | *ir_raw = code; |
196 | *ir_key = code; | 193 | *ir_key = code; |
@@ -200,7 +197,40 @@ int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
200 | return 1; | 197 | return 1; |
201 | } | 198 | } |
202 | 199 | ||
203 | EXPORT_SYMBOL_GPL(get_key_pinnacle); | 200 | /* The grey pinnacle PCTV remote |
201 | * | ||
202 | * There are one issue with this remote: | ||
203 | * - I2c packet does not change when the same key is pressed quickly. The workaround | ||
204 | * is to hold down each key for about half a second, so that another code is generated | ||
205 | * in the i2c packet, and the function can distinguish key presses. | ||
206 | * | ||
207 | * Sylvain Pasche <sylvain.pasche@gmail.com> | ||
208 | */ | ||
209 | int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
210 | { | ||
211 | |||
212 | return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff); | ||
213 | } | ||
214 | |||
215 | EXPORT_SYMBOL_GPL(get_key_pinnacle_grey); | ||
216 | |||
217 | |||
218 | /* The new pinnacle PCTV remote (with the colored buttons) | ||
219 | * | ||
220 | * Ricardo Cerqueira <v4l@cerqueira.org> | ||
221 | */ | ||
222 | int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
223 | { | ||
224 | /* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE | ||
225 | * | ||
226 | * this is the only value that results in 42 unique | ||
227 | * codes < 128 | ||
228 | */ | ||
229 | |||
230 | return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88); | ||
231 | } | ||
232 | |||
233 | EXPORT_SYMBOL_GPL(get_key_pinnacle_color); | ||
204 | 234 | ||
205 | /* ----------------------------------------------------------------------- */ | 235 | /* ----------------------------------------------------------------------- */ |
206 | 236 | ||
diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c new file mode 100644 index 000000000000..3bf7ac4f5288 --- /dev/null +++ b/drivers/media/video/ks0127.c | |||
@@ -0,0 +1,846 @@ | |||
1 | /* | ||
2 | * Video Capture Driver (Video for Linux 1/2) | ||
3 | * for the Matrox Marvel G200,G400 and Rainbow Runner-G series | ||
4 | * | ||
5 | * This module is an interface to the KS0127 video decoder chip. | ||
6 | * | ||
7 | * Copyright (C) 1999 Ryan Drake <stiletto@mediaone.net> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version 2 | ||
12 | * of the License, or (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | * | ||
23 | ***************************************************************************** | ||
24 | * | ||
25 | * Modified and extended by | ||
26 | * Mike Bernson <mike@mlb.org> | ||
27 | * Gerard v.d. Horst | ||
28 | * Leon van Stuivenberg <l.vanstuivenberg@chello.nl> | ||
29 | * Gernot Ziegler <gz@lysator.liu.se> | ||
30 | * | ||
31 | * Version History: | ||
32 | * V1.0 Ryan Drake Initial version by Ryan Drake | ||
33 | * V1.1 Gerard v.d. Horst Added some debugoutput, reset the video-standard | ||
34 | */ | ||
35 | |||
36 | #ifndef __KERNEL__ | ||
37 | #define __KERNEL__ | ||
38 | #endif | ||
39 | |||
40 | #include <linux/init.h> | ||
41 | #include <linux/module.h> | ||
42 | #include <linux/delay.h> | ||
43 | #include <linux/errno.h> | ||
44 | #include <linux/kernel.h> | ||
45 | #include <linux/slab.h> | ||
46 | #include <linux/proc_fs.h> | ||
47 | #include "ks0127.h" | ||
48 | |||
49 | #include <linux/i2c.h> | ||
50 | #include <linux/video_decoder.h> | ||
51 | |||
52 | #define dprintk if (debug) printk | ||
53 | |||
54 | /* i2c identification */ | ||
55 | #define I2C_KS0127_ADDON 0xD8 | ||
56 | #define I2C_KS0127_ONBOARD 0xDA | ||
57 | |||
58 | #define KS_TYPE_UNKNOWN 0 | ||
59 | #define KS_TYPE_0122S 1 | ||
60 | #define KS_TYPE_0127 2 | ||
61 | #define KS_TYPE_0127B 3 | ||
62 | |||
63 | /* ks0127 control registers */ | ||
64 | #define KS_STAT 0x00 | ||
65 | #define KS_CMDA 0x01 | ||
66 | #define KS_CMDB 0x02 | ||
67 | #define KS_CMDC 0x03 | ||
68 | #define KS_CMDD 0x04 | ||
69 | #define KS_HAVB 0x05 | ||
70 | #define KS_HAVE 0x06 | ||
71 | #define KS_HS1B 0x07 | ||
72 | #define KS_HS1E 0x08 | ||
73 | #define KS_HS2B 0x09 | ||
74 | #define KS_HS2E 0x0a | ||
75 | #define KS_AGC 0x0b | ||
76 | #define KS_HXTRA 0x0c | ||
77 | #define KS_CDEM 0x0d | ||
78 | #define KS_PORTAB 0x0e | ||
79 | #define KS_LUMA 0x0f | ||
80 | #define KS_CON 0x10 | ||
81 | #define KS_BRT 0x11 | ||
82 | #define KS_CHROMA 0x12 | ||
83 | #define KS_CHROMB 0x13 | ||
84 | #define KS_DEMOD 0x14 | ||
85 | #define KS_SAT 0x15 | ||
86 | #define KS_HUE 0x16 | ||
87 | #define KS_VERTIA 0x17 | ||
88 | #define KS_VERTIB 0x18 | ||
89 | #define KS_VERTIC 0x19 | ||
90 | #define KS_HSCLL 0x1a | ||
91 | #define KS_HSCLH 0x1b | ||
92 | #define KS_VSCLL 0x1c | ||
93 | #define KS_VSCLH 0x1d | ||
94 | #define KS_OFMTA 0x1e | ||
95 | #define KS_OFMTB 0x1f | ||
96 | #define KS_VBICTL 0x20 | ||
97 | #define KS_CCDAT2 0x21 | ||
98 | #define KS_CCDAT1 0x22 | ||
99 | #define KS_VBIL30 0x23 | ||
100 | #define KS_VBIL74 0x24 | ||
101 | #define KS_VBIL118 0x25 | ||
102 | #define KS_VBIL1512 0x26 | ||
103 | #define KS_TTFRAM 0x27 | ||
104 | #define KS_TESTA 0x28 | ||
105 | #define KS_UVOFFH 0x29 | ||
106 | #define KS_UVOFFL 0x2a | ||
107 | #define KS_UGAIN 0x2b | ||
108 | #define KS_VGAIN 0x2c | ||
109 | #define KS_VAVB 0x2d | ||
110 | #define KS_VAVE 0x2e | ||
111 | #define KS_CTRACK 0x2f | ||
112 | #define KS_POLCTL 0x30 | ||
113 | #define KS_REFCOD 0x31 | ||
114 | #define KS_INVALY 0x32 | ||
115 | #define KS_INVALU 0x33 | ||
116 | #define KS_INVALV 0x34 | ||
117 | #define KS_UNUSEY 0x35 | ||
118 | #define KS_UNUSEU 0x36 | ||
119 | #define KS_UNUSEV 0x37 | ||
120 | #define KS_USRSAV 0x38 | ||
121 | #define KS_USREAV 0x39 | ||
122 | #define KS_SHS1A 0x3a | ||
123 | #define KS_SHS1B 0x3b | ||
124 | #define KS_SHS1C 0x3c | ||
125 | #define KS_CMDE 0x3d | ||
126 | #define KS_VSDEL 0x3e | ||
127 | #define KS_CMDF 0x3f | ||
128 | #define KS_GAMMA0 0x40 | ||
129 | #define KS_GAMMA1 0x41 | ||
130 | #define KS_GAMMA2 0x42 | ||
131 | #define KS_GAMMA3 0x43 | ||
132 | #define KS_GAMMA4 0x44 | ||
133 | #define KS_GAMMA5 0x45 | ||
134 | #define KS_GAMMA6 0x46 | ||
135 | #define KS_GAMMA7 0x47 | ||
136 | #define KS_GAMMA8 0x48 | ||
137 | #define KS_GAMMA9 0x49 | ||
138 | #define KS_GAMMA10 0x4a | ||
139 | #define KS_GAMMA11 0x4b | ||
140 | #define KS_GAMMA12 0x4c | ||
141 | #define KS_GAMMA13 0x4d | ||
142 | #define KS_GAMMA14 0x4e | ||
143 | #define KS_GAMMA15 0x4f | ||
144 | #define KS_GAMMA16 0x50 | ||
145 | #define KS_GAMMA17 0x51 | ||
146 | #define KS_GAMMA18 0x52 | ||
147 | #define KS_GAMMA19 0x53 | ||
148 | #define KS_GAMMA20 0x54 | ||
149 | #define KS_GAMMA21 0x55 | ||
150 | #define KS_GAMMA22 0x56 | ||
151 | #define KS_GAMMA23 0x57 | ||
152 | #define KS_GAMMA24 0x58 | ||
153 | #define KS_GAMMA25 0x59 | ||
154 | #define KS_GAMMA26 0x5a | ||
155 | #define KS_GAMMA27 0x5b | ||
156 | #define KS_GAMMA28 0x5c | ||
157 | #define KS_GAMMA29 0x5d | ||
158 | #define KS_GAMMA30 0x5e | ||
159 | #define KS_GAMMA31 0x5f | ||
160 | #define KS_GAMMAD0 0x60 | ||
161 | #define KS_GAMMAD1 0x61 | ||
162 | #define KS_GAMMAD2 0x62 | ||
163 | #define KS_GAMMAD3 0x63 | ||
164 | #define KS_GAMMAD4 0x64 | ||
165 | #define KS_GAMMAD5 0x65 | ||
166 | #define KS_GAMMAD6 0x66 | ||
167 | #define KS_GAMMAD7 0x67 | ||
168 | #define KS_GAMMAD8 0x68 | ||
169 | #define KS_GAMMAD9 0x69 | ||
170 | #define KS_GAMMAD10 0x6a | ||
171 | #define KS_GAMMAD11 0x6b | ||
172 | #define KS_GAMMAD12 0x6c | ||
173 | #define KS_GAMMAD13 0x6d | ||
174 | #define KS_GAMMAD14 0x6e | ||
175 | #define KS_GAMMAD15 0x6f | ||
176 | #define KS_GAMMAD16 0x70 | ||
177 | #define KS_GAMMAD17 0x71 | ||
178 | #define KS_GAMMAD18 0x72 | ||
179 | #define KS_GAMMAD19 0x73 | ||
180 | #define KS_GAMMAD20 0x74 | ||
181 | #define KS_GAMMAD21 0x75 | ||
182 | #define KS_GAMMAD22 0x76 | ||
183 | #define KS_GAMMAD23 0x77 | ||
184 | #define KS_GAMMAD24 0x78 | ||
185 | #define KS_GAMMAD25 0x79 | ||
186 | #define KS_GAMMAD26 0x7a | ||
187 | #define KS_GAMMAD27 0x7b | ||
188 | #define KS_GAMMAD28 0x7c | ||
189 | #define KS_GAMMAD29 0x7d | ||
190 | #define KS_GAMMAD30 0x7e | ||
191 | #define KS_GAMMAD31 0x7f | ||
192 | |||
193 | |||
194 | /**************************************************************************** | ||
195 | * mga_dev : represents one ks0127 chip. | ||
196 | ****************************************************************************/ | ||
197 | |||
198 | struct adjust { | ||
199 | int contrast; | ||
200 | int bright; | ||
201 | int hue; | ||
202 | int ugain; | ||
203 | int vgain; | ||
204 | }; | ||
205 | |||
206 | struct ks0127 { | ||
207 | struct i2c_client *client; | ||
208 | unsigned char addr; | ||
209 | int format_width; | ||
210 | int format_height; | ||
211 | int cap_width; | ||
212 | int cap_height; | ||
213 | int norm; | ||
214 | int ks_type; | ||
215 | u8 regs[256]; | ||
216 | }; | ||
217 | |||
218 | |||
219 | static int debug; /* insmod parameter */ | ||
220 | |||
221 | module_param(debug, int, 0); | ||
222 | MODULE_PARM_DESC(debug, "Debug output"); | ||
223 | MODULE_LICENSE("GPL"); | ||
224 | |||
225 | static u8 reg_defaults[64]; | ||
226 | |||
227 | |||
228 | |||
229 | static void init_reg_defaults(void) | ||
230 | { | ||
231 | u8 *table = reg_defaults; | ||
232 | |||
233 | table[KS_CMDA] = 0x2c; /* VSE=0, CCIR 601, autodetect standard */ | ||
234 | table[KS_CMDB] = 0x12; /* VALIGN=0, AGC control and input */ | ||
235 | table[KS_CMDC] = 0x00; /* Test options */ | ||
236 | /* clock & input select, write 1 to PORTA */ | ||
237 | table[KS_CMDD] = 0x01; | ||
238 | table[KS_HAVB] = 0x00; /* HAV Start Control */ | ||
239 | table[KS_HAVE] = 0x00; /* HAV End Control */ | ||
240 | table[KS_HS1B] = 0x10; /* HS1 Start Control */ | ||
241 | table[KS_HS1E] = 0x00; /* HS1 End Control */ | ||
242 | table[KS_HS2B] = 0x00; /* HS2 Start Control */ | ||
243 | table[KS_HS2E] = 0x00; /* HS2 End Control */ | ||
244 | table[KS_AGC] = 0x53; /* Manual setting for AGC */ | ||
245 | table[KS_HXTRA] = 0x00; /* Extra Bits for HAV and HS1/2 */ | ||
246 | table[KS_CDEM] = 0x00; /* Chroma Demodulation Control */ | ||
247 | table[KS_PORTAB] = 0x0f; /* port B is input, port A output GPPORT */ | ||
248 | table[KS_LUMA] = 0x01; /* Luma control */ | ||
249 | table[KS_CON] = 0x00; /* Contrast Control */ | ||
250 | table[KS_BRT] = 0x00; /* Brightness Control */ | ||
251 | table[KS_CHROMA] = 0x2a; /* Chroma control A */ | ||
252 | table[KS_CHROMB] = 0x90; /* Chroma control B */ | ||
253 | table[KS_DEMOD] = 0x00; /* Chroma Demodulation Control & Status */ | ||
254 | table[KS_SAT] = 0x00; /* Color Saturation Control*/ | ||
255 | table[KS_HUE] = 0x00; /* Hue Control */ | ||
256 | table[KS_VERTIA] = 0x00; /* Vertical Processing Control A */ | ||
257 | /* Vertical Processing Control B, luma 1 line delayed */ | ||
258 | table[KS_VERTIB] = 0x12; | ||
259 | table[KS_VERTIC] = 0x0b; /* Vertical Processing Control C */ | ||
260 | table[KS_HSCLL] = 0x00; /* Horizontal Scaling Ratio Low */ | ||
261 | table[KS_HSCLH] = 0x00; /* Horizontal Scaling Ratio High */ | ||
262 | table[KS_VSCLL] = 0x00; /* Vertical Scaling Ratio Low */ | ||
263 | table[KS_VSCLH] = 0x00; /* Vertical Scaling Ratio High */ | ||
264 | /* 16 bit YCbCr 4:2:2 output; I can't make the bt866 like 8 bit /Sam */ | ||
265 | table[KS_OFMTA] = 0x30; | ||
266 | table[KS_OFMTB] = 0x00; /* Output Control B */ | ||
267 | /* VBI Decoder Control; 4bit fmt: avoid Y overflow */ | ||
268 | table[KS_VBICTL] = 0x5d; | ||
269 | table[KS_CCDAT2] = 0x00; /* Read Only register */ | ||
270 | table[KS_CCDAT1] = 0x00; /* Read Only register */ | ||
271 | table[KS_VBIL30] = 0xa8; /* VBI data decoding options */ | ||
272 | table[KS_VBIL74] = 0xaa; /* VBI data decoding options */ | ||
273 | table[KS_VBIL118] = 0x2a; /* VBI data decoding options */ | ||
274 | table[KS_VBIL1512] = 0x00; /* VBI data decoding options */ | ||
275 | table[KS_TTFRAM] = 0x00; /* Teletext frame alignment pattern */ | ||
276 | table[KS_TESTA] = 0x00; /* test register, shouldn't be written */ | ||
277 | table[KS_UVOFFH] = 0x00; /* UV Offset Adjustment High */ | ||
278 | table[KS_UVOFFL] = 0x00; /* UV Offset Adjustment Low */ | ||
279 | table[KS_UGAIN] = 0x00; /* U Component Gain Adjustment */ | ||
280 | table[KS_VGAIN] = 0x00; /* V Component Gain Adjustment */ | ||
281 | table[KS_VAVB] = 0x07; /* VAV Begin */ | ||
282 | table[KS_VAVE] = 0x00; /* VAV End */ | ||
283 | table[KS_CTRACK] = 0x00; /* Chroma Tracking Control */ | ||
284 | table[KS_POLCTL] = 0x41; /* Timing Signal Polarity Control */ | ||
285 | table[KS_REFCOD] = 0x80; /* Reference Code Insertion Control */ | ||
286 | table[KS_INVALY] = 0x10; /* Invalid Y Code */ | ||
287 | table[KS_INVALU] = 0x80; /* Invalid U Code */ | ||
288 | table[KS_INVALV] = 0x80; /* Invalid V Code */ | ||
289 | table[KS_UNUSEY] = 0x10; /* Unused Y Code */ | ||
290 | table[KS_UNUSEU] = 0x80; /* Unused U Code */ | ||
291 | table[KS_UNUSEV] = 0x80; /* Unused V Code */ | ||
292 | table[KS_USRSAV] = 0x00; /* reserved */ | ||
293 | table[KS_USREAV] = 0x00; /* reserved */ | ||
294 | table[KS_SHS1A] = 0x00; /* User Defined SHS1 A */ | ||
295 | /* User Defined SHS1 B, ALT656=1 on 0127B */ | ||
296 | table[KS_SHS1B] = 0x80; | ||
297 | table[KS_SHS1C] = 0x00; /* User Defined SHS1 C */ | ||
298 | table[KS_CMDE] = 0x00; /* Command Register E */ | ||
299 | table[KS_VSDEL] = 0x00; /* VS Delay Control */ | ||
300 | /* Command Register F, update -immediately- */ | ||
301 | /* (there might come no vsync)*/ | ||
302 | table[KS_CMDF] = 0x02; | ||
303 | } | ||
304 | |||
305 | |||
306 | /* We need to manually read because of a bug in the KS0127 chip. | ||
307 | * | ||
308 | * An explanation from kayork@mail.utexas.edu: | ||
309 | * | ||
310 | * During I2C reads, the KS0127 only samples for a stop condition | ||
311 | * during the place where the acknoledge bit should be. Any standard | ||
312 | * I2C implementation (correctly) throws in another clock transition | ||
313 | * at the 9th bit, and the KS0127 will not recognize the stop condition | ||
314 | * and will continue to clock out data. | ||
315 | * | ||
316 | * So we have to do the read ourself. Big deal. | ||
317 | workaround in i2c-algo-bit | ||
318 | */ | ||
319 | |||
320 | |||
321 | static u8 ks0127_read(struct ks0127 *ks, u8 reg) | ||
322 | { | ||
323 | struct i2c_client *c = ks->client; | ||
324 | char val = 0; | ||
325 | struct i2c_msg msgs[] = { | ||
326 | {c->addr, 0, sizeof(reg), ®}, | ||
327 | {c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val}}; | ||
328 | int ret; | ||
329 | |||
330 | ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs)); | ||
331 | if (ret != ARRAY_SIZE(msgs)) | ||
332 | dprintk("ks0127_write error\n"); | ||
333 | |||
334 | return val; | ||
335 | } | ||
336 | |||
337 | |||
338 | static void ks0127_write(struct ks0127 *ks, u8 reg, u8 val) | ||
339 | { | ||
340 | char msg[] = {reg, val}; | ||
341 | |||
342 | if (i2c_master_send(ks->client, msg, sizeof(msg)) != sizeof(msg)) | ||
343 | dprintk("ks0127_write error\n"); | ||
344 | |||
345 | ks->regs[reg] = val; | ||
346 | } | ||
347 | |||
348 | |||
349 | /* generic bit-twiddling */ | ||
350 | static void ks0127_and_or(struct ks0127 *ks, u8 reg, u8 and_v, u8 or_v) | ||
351 | { | ||
352 | u8 val = ks->regs[reg]; | ||
353 | val = (val & and_v) | or_v; | ||
354 | ks0127_write(ks, reg, val); | ||
355 | } | ||
356 | |||
357 | |||
358 | |||
359 | /**************************************************************************** | ||
360 | * ks0127 private api | ||
361 | ****************************************************************************/ | ||
362 | static void ks0127_reset(struct ks0127* ks) | ||
363 | { | ||
364 | int i; | ||
365 | u8 *table = reg_defaults; | ||
366 | |||
367 | ks->ks_type = KS_TYPE_UNKNOWN; | ||
368 | |||
369 | dprintk("ks0127: reset\n"); | ||
370 | msleep(1); | ||
371 | |||
372 | /* initialize all registers to known values */ | ||
373 | /* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */ | ||
374 | |||
375 | for(i = 1; i < 33; i++) | ||
376 | ks0127_write(ks, i, table[i]); | ||
377 | |||
378 | for(i = 35; i < 40; i++) | ||
379 | ks0127_write(ks, i, table[i]); | ||
380 | |||
381 | for(i = 41; i < 56; i++) | ||
382 | ks0127_write(ks, i, table[i]); | ||
383 | |||
384 | for(i = 58; i < 64; i++) | ||
385 | ks0127_write(ks, i, table[i]); | ||
386 | |||
387 | |||
388 | if ((ks0127_read(ks, KS_STAT) & 0x80) == 0) { | ||
389 | ks->ks_type = KS_TYPE_0122S; | ||
390 | dprintk("ks0127: ks0122s Found\n"); | ||
391 | return; | ||
392 | } | ||
393 | |||
394 | switch(ks0127_read(ks, KS_CMDE) & 0x0f) { | ||
395 | |||
396 | case 0: | ||
397 | ks->ks_type = KS_TYPE_0127; | ||
398 | dprintk("ks0127: ks0127 found\n"); | ||
399 | break; | ||
400 | |||
401 | case 9: | ||
402 | ks->ks_type = KS_TYPE_0127B; | ||
403 | dprintk("ks0127: ks0127B Revision A found\n"); | ||
404 | break; | ||
405 | |||
406 | default: | ||
407 | dprintk("ks0127: unknown revision\n"); | ||
408 | break; | ||
409 | } | ||
410 | } | ||
411 | |||
412 | static int ks0127_command(struct i2c_client *client, | ||
413 | unsigned int cmd, void *arg) | ||
414 | { | ||
415 | struct ks0127 *ks = i2c_get_clientdata(client); | ||
416 | |||
417 | int *iarg = (int*)arg; | ||
418 | |||
419 | int status; | ||
420 | |||
421 | if (!ks) | ||
422 | return -ENODEV; | ||
423 | |||
424 | switch (cmd) { | ||
425 | |||
426 | case DECODER_INIT: | ||
427 | dprintk("ks0127: command DECODER_INIT\n"); | ||
428 | ks0127_reset(ks); | ||
429 | break; | ||
430 | |||
431 | case DECODER_SET_INPUT: | ||
432 | switch(*iarg) { | ||
433 | case KS_INPUT_COMPOSITE_1: | ||
434 | case KS_INPUT_COMPOSITE_2: | ||
435 | case KS_INPUT_COMPOSITE_3: | ||
436 | case KS_INPUT_COMPOSITE_4: | ||
437 | case KS_INPUT_COMPOSITE_5: | ||
438 | case KS_INPUT_COMPOSITE_6: | ||
439 | dprintk("ks0127: command DECODER_SET_INPUT %d: " | ||
440 | "Composite\n", *iarg); | ||
441 | /* autodetect 50/60 Hz */ | ||
442 | ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00); | ||
443 | /* VSE=0 */ | ||
444 | ks0127_and_or(ks, KS_CMDA, ~0x40, 0x00); | ||
445 | /* set input line */ | ||
446 | ks0127_and_or(ks, KS_CMDB, 0xb0, *iarg); | ||
447 | /* non-freerunning mode */ | ||
448 | ks0127_and_or(ks, KS_CMDC, 0x70, 0x0a); | ||
449 | /* analog input */ | ||
450 | ks0127_and_or(ks, KS_CMDD, 0x03, 0x00); | ||
451 | /* enable chroma demodulation */ | ||
452 | ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00); | ||
453 | /* chroma trap, HYBWR=1 */ | ||
454 | ks0127_and_or(ks, KS_LUMA, 0x00, | ||
455 | (reg_defaults[KS_LUMA])|0x0c); | ||
456 | /* scaler fullbw, luma comb off */ | ||
457 | ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81); | ||
458 | /* manual chroma comb .25 .5 .25 */ | ||
459 | ks0127_and_or(ks, KS_VERTIC, 0x0f, 0x90); | ||
460 | |||
461 | /* chroma path delay */ | ||
462 | ks0127_and_or(ks, KS_CHROMB, 0x0f, 0x90); | ||
463 | |||
464 | ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]); | ||
465 | ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]); | ||
466 | ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]); | ||
467 | ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]); | ||
468 | break; | ||
469 | |||
470 | case KS_INPUT_SVIDEO_1: | ||
471 | case KS_INPUT_SVIDEO_2: | ||
472 | case KS_INPUT_SVIDEO_3: | ||
473 | dprintk("ks0127: command DECODER_SET_INPUT %d: " | ||
474 | "S-Video\n", *iarg); | ||
475 | /* autodetect 50/60 Hz */ | ||
476 | ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00); | ||
477 | /* VSE=0 */ | ||
478 | ks0127_and_or(ks, KS_CMDA, ~0x40, 0x00); | ||
479 | /* set input line */ | ||
480 | ks0127_and_or(ks, KS_CMDB, 0xb0, *iarg); | ||
481 | /* non-freerunning mode */ | ||
482 | ks0127_and_or(ks, KS_CMDC, 0x70, 0x0a); | ||
483 | /* analog input */ | ||
484 | ks0127_and_or(ks, KS_CMDD, 0x03, 0x00); | ||
485 | /* enable chroma demodulation */ | ||
486 | ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00); | ||
487 | ks0127_and_or(ks, KS_LUMA, 0x00, | ||
488 | reg_defaults[KS_LUMA]); | ||
489 | /* disable luma comb */ | ||
490 | ks0127_and_or(ks, KS_VERTIA, 0x08, | ||
491 | (reg_defaults[KS_VERTIA]&0xf0)|0x01); | ||
492 | ks0127_and_or(ks, KS_VERTIC, 0x0f, | ||
493 | reg_defaults[KS_VERTIC]&0xf0); | ||
494 | |||
495 | ks0127_and_or(ks, KS_CHROMB, 0x0f, | ||
496 | reg_defaults[KS_CHROMB]&0xf0); | ||
497 | |||
498 | ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]); | ||
499 | ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]); | ||
500 | ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]); | ||
501 | ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]); | ||
502 | break; | ||
503 | |||
504 | case KS_INPUT_YUV656: | ||
505 | dprintk("ks0127: command DECODER_SET_INPUT 15: " | ||
506 | "YUV656\n"); | ||
507 | if (ks->norm == VIDEO_MODE_NTSC || | ||
508 | ks->norm == KS_STD_PAL_M) | ||
509 | /* force 60 Hz */ | ||
510 | ks0127_and_or(ks, KS_CMDA, 0xfc, 0x03); | ||
511 | else | ||
512 | /* force 50 Hz */ | ||
513 | ks0127_and_or(ks, KS_CMDA, 0xfc, 0x02); | ||
514 | |||
515 | ks0127_and_or(ks, KS_CMDA, 0xff, 0x40); /* VSE=1 */ | ||
516 | /* set input line and VALIGN */ | ||
517 | ks0127_and_or(ks, KS_CMDB, 0xb0, (*iarg | 0x40)); | ||
518 | /* freerunning mode, */ | ||
519 | /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0 VMEM=1*/ | ||
520 | ks0127_and_or(ks, KS_CMDC, 0x70, 0x87); | ||
521 | /* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */ | ||
522 | ks0127_and_or(ks, KS_CMDD, 0x03, 0x08); | ||
523 | /* disable chroma demodulation */ | ||
524 | ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x30); | ||
525 | /* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */ | ||
526 | ks0127_and_or(ks, KS_LUMA, 0x00, 0x71); | ||
527 | ks0127_and_or(ks, KS_VERTIC, 0x0f, | ||
528 | reg_defaults[KS_VERTIC]&0xf0); | ||
529 | |||
530 | /* scaler fullbw, luma comb off */ | ||
531 | ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81); | ||
532 | |||
533 | ks0127_and_or(ks, KS_CHROMB, 0x0f, | ||
534 | reg_defaults[KS_CHROMB]&0xf0); | ||
535 | |||
536 | ks0127_and_or(ks, KS_CON, 0x00, 0x00); | ||
537 | ks0127_and_or(ks, KS_BRT, 0x00, 32); /* spec: 34 */ | ||
538 | /* spec: 229 (e5) */ | ||
539 | ks0127_and_or(ks, KS_SAT, 0x00, 0xe8); | ||
540 | ks0127_and_or(ks, KS_HUE, 0x00, 0); | ||
541 | |||
542 | ks0127_and_or(ks, KS_UGAIN, 0x00, 238); | ||
543 | ks0127_and_or(ks, KS_VGAIN, 0x00, 0x00); | ||
544 | |||
545 | /*UOFF:0x30, VOFF:0x30, TSTCGN=1 */ | ||
546 | ks0127_and_or(ks, KS_UVOFFH, 0x00, 0x4f); | ||
547 | ks0127_and_or(ks, KS_UVOFFL, 0x00, 0x00); | ||
548 | break; | ||
549 | |||
550 | default: | ||
551 | dprintk("ks0127: command DECODER_SET_INPUT: " | ||
552 | "Unknown input %d\n", *iarg); | ||
553 | break; | ||
554 | } | ||
555 | |||
556 | /* hack: CDMLPF sometimes spontaneously switches on; */ | ||
557 | /* force back off */ | ||
558 | ks0127_write(ks, KS_DEMOD, reg_defaults[KS_DEMOD]); | ||
559 | break; | ||
560 | |||
561 | case DECODER_SET_OUTPUT: | ||
562 | switch(*iarg) { | ||
563 | case KS_OUTPUT_YUV656E: | ||
564 | dprintk("ks0127: command DECODER_SET_OUTPUT: " | ||
565 | "OUTPUT_YUV656E (Missing)\n"); | ||
566 | return -EINVAL; | ||
567 | break; | ||
568 | |||
569 | case KS_OUTPUT_EXV: | ||
570 | dprintk("ks0127: command DECODER_SET_OUTPUT: " | ||
571 | "OUTPUT_EXV\n"); | ||
572 | ks0127_and_or(ks, KS_OFMTA, 0xf0, 0x09); | ||
573 | break; | ||
574 | } | ||
575 | break; | ||
576 | |||
577 | case DECODER_SET_NORM: //sam This block mixes old and new norm names... | ||
578 | /* Set to automatic SECAM/Fsc mode */ | ||
579 | ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00); | ||
580 | |||
581 | ks->norm = *iarg; | ||
582 | switch(*iarg) | ||
583 | { | ||
584 | /* this is untested !! */ | ||
585 | /* It just detects PAL_N/NTSC_M (no special frequencies) */ | ||
586 | /* And you have to set the standard a second time afterwards */ | ||
587 | case VIDEO_MODE_AUTO: | ||
588 | dprintk("ks0127: command DECODER_SET_NORM: AUTO\n"); | ||
589 | |||
590 | /* The chip determines the format */ | ||
591 | /* based on the current field rate */ | ||
592 | ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00); | ||
593 | ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20); | ||
594 | /* This is wrong for PAL ! As I said, */ | ||
595 | /* you need to set the standard once again !! */ | ||
596 | ks->format_height = 240; | ||
597 | ks->format_width = 704; | ||
598 | break; | ||
599 | |||
600 | case VIDEO_MODE_NTSC: | ||
601 | dprintk("ks0127: command DECODER_SET_NORM: NTSC_M\n"); | ||
602 | ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20); | ||
603 | ks->format_height = 240; | ||
604 | ks->format_width = 704; | ||
605 | break; | ||
606 | |||
607 | case KS_STD_NTSC_N: | ||
608 | dprintk("ks0127: command KS0127_SET_STANDARD: " | ||
609 | "NTSC_N (fixme)\n"); | ||
610 | ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40); | ||
611 | ks->format_height = 240; | ||
612 | ks->format_width = 704; | ||
613 | break; | ||
614 | |||
615 | case VIDEO_MODE_PAL: | ||
616 | dprintk("ks0127: command DECODER_SET_NORM: PAL_N\n"); | ||
617 | ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20); | ||
618 | ks->format_height = 290; | ||
619 | ks->format_width = 704; | ||
620 | break; | ||
621 | |||
622 | case KS_STD_PAL_M: | ||
623 | dprintk("ks0127: command KS0127_SET_STANDARD: " | ||
624 | "PAL_M (fixme)\n"); | ||
625 | ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40); | ||
626 | ks->format_height = 290; | ||
627 | ks->format_width = 704; | ||
628 | break; | ||
629 | |||
630 | case VIDEO_MODE_SECAM: | ||
631 | dprintk("ks0127: command KS0127_SET_STANDARD: " | ||
632 | "SECAM\n"); | ||
633 | ks->format_height = 290; | ||
634 | ks->format_width = 704; | ||
635 | |||
636 | /* set to secam autodetection */ | ||
637 | ks0127_and_or(ks, KS_CHROMA, 0xdf, 0x20); | ||
638 | ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00); | ||
639 | schedule_timeout_interruptible(HZ/10+1); | ||
640 | |||
641 | /* did it autodetect? */ | ||
642 | if (ks0127_read(ks, KS_DEMOD) & 0x40) | ||
643 | break; | ||
644 | |||
645 | /* force to secam mode */ | ||
646 | ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x0f); | ||
647 | break; | ||
648 | |||
649 | default: | ||
650 | dprintk("ks0127: command DECODER_SET_NORM: " | ||
651 | "Unknown norm %d\n", *iarg); | ||
652 | break; | ||
653 | } | ||
654 | break; | ||
655 | |||
656 | case DECODER_SET_PICTURE: | ||
657 | dprintk("ks0127: command DECODER_SET_PICTURE " | ||
658 | "not yet supported (fixme)\n"); | ||
659 | return -EINVAL; | ||
660 | |||
661 | //sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE | ||
662 | //sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE | ||
663 | //sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE? | ||
664 | //sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE | ||
665 | //sam todo: KS0127_SET_AGC_MODE: | ||
666 | //sam todo: KS0127_SET_AGC: | ||
667 | //sam todo: KS0127_SET_CHROMA_MODE: | ||
668 | //sam todo: KS0127_SET_PIXCLK_MODE: | ||
669 | //sam todo: KS0127_SET_GAMMA_MODE: | ||
670 | //sam todo: KS0127_SET_UGAIN: | ||
671 | //sam todo: KS0127_SET_VGAIN: | ||
672 | //sam todo: KS0127_SET_INVALY: | ||
673 | //sam todo: KS0127_SET_INVALU: | ||
674 | //sam todo: KS0127_SET_INVALV: | ||
675 | //sam todo: KS0127_SET_UNUSEY: | ||
676 | //sam todo: KS0127_SET_UNUSEU: | ||
677 | //sam todo: KS0127_SET_UNUSEV: | ||
678 | //sam todo: KS0127_SET_VSALIGN_MODE: | ||
679 | |||
680 | case DECODER_ENABLE_OUTPUT: | ||
681 | { | ||
682 | |||
683 | int *iarg = arg; | ||
684 | int enable = (*iarg != 0); | ||
685 | if (enable) { | ||
686 | dprintk("ks0127: command " | ||
687 | "DECODER_ENABLE_OUTPUT on " | ||
688 | "(%d)\n", enable); | ||
689 | /* All output pins on */ | ||
690 | ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30); | ||
691 | /* Obey the OEN pin */ | ||
692 | ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00); | ||
693 | } else { | ||
694 | dprintk("ks0127: command " | ||
695 | "DECODER_ENABLE_OUTPUT off " | ||
696 | "(%d)\n", enable); | ||
697 | /* Video output pins off */ | ||
698 | ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00); | ||
699 | /* Ignore the OEN pin */ | ||
700 | ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80); | ||
701 | } | ||
702 | } | ||
703 | break; | ||
704 | |||
705 | //sam todo: KS0127_SET_OUTPUT_MODE: | ||
706 | //sam todo: KS0127_SET_WIDTH: | ||
707 | //sam todo: KS0127_SET_HEIGHT: | ||
708 | //sam todo: KS0127_SET_HSCALE: | ||
709 | |||
710 | case DECODER_GET_STATUS: | ||
711 | dprintk("ks0127: command DECODER_GET_STATUS\n"); | ||
712 | *iarg = 0; | ||
713 | status = ks0127_read(ks, KS_STAT); | ||
714 | if (!(status & 0x20)) /* NOVID not set */ | ||
715 | *iarg = (*iarg & DECODER_STATUS_GOOD); | ||
716 | if ((status & 0x01)) /* CLOCK set */ | ||
717 | *iarg = (*iarg & DECODER_STATUS_COLOR); | ||
718 | if ((status & 0x08)) /* PALDET set */ | ||
719 | *iarg = (*iarg & DECODER_STATUS_PAL); | ||
720 | else | ||
721 | *iarg = (*iarg & DECODER_STATUS_NTSC); | ||
722 | break; | ||
723 | |||
724 | //Catch any unknown command | ||
725 | default: | ||
726 | dprintk("ks0127: command unknown: %04X\n", cmd); | ||
727 | return -EINVAL; | ||
728 | } | ||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | |||
733 | |||
734 | |||
735 | static int ks0127_probe(struct i2c_adapter *adapter); | ||
736 | static int ks0127_detach(struct i2c_client *client); | ||
737 | static int ks0127_command(struct i2c_client *client, | ||
738 | unsigned int cmd, void *arg); | ||
739 | |||
740 | |||
741 | |||
742 | /* Addresses to scan */ | ||
743 | static unsigned short normal_i2c[] = {I2C_KS0127_ADDON>>1, | ||
744 | I2C_KS0127_ONBOARD>>1, I2C_CLIENT_END}; | ||
745 | static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; | ||
746 | static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; | ||
747 | static struct i2c_client_address_data addr_data = { | ||
748 | normal_i2c, | ||
749 | probe, | ||
750 | ignore, | ||
751 | }; | ||
752 | |||
753 | static struct i2c_driver i2c_driver_ks0127 = { | ||
754 | .driver.name = "ks0127", | ||
755 | .id = I2C_DRIVERID_KS0127, | ||
756 | .attach_adapter = ks0127_probe, | ||
757 | .detach_client = ks0127_detach, | ||
758 | .command = ks0127_command | ||
759 | }; | ||
760 | |||
761 | static struct i2c_client ks0127_client_tmpl = | ||
762 | { | ||
763 | .name = "(ks0127 unset)", | ||
764 | .addr = 0, | ||
765 | .adapter = NULL, | ||
766 | .driver = &i2c_driver_ks0127, | ||
767 | .usage_count = 0 | ||
768 | }; | ||
769 | |||
770 | static int ks0127_found_proc(struct i2c_adapter *adapter, int addr, int kind) | ||
771 | { | ||
772 | struct ks0127 *ks; | ||
773 | struct i2c_client *client; | ||
774 | |||
775 | client = kzalloc(sizeof(*client), GFP_KERNEL); | ||
776 | if (client == NULL) | ||
777 | return -ENOMEM; | ||
778 | memcpy(client, &ks0127_client_tmpl, sizeof(*client)); | ||
779 | |||
780 | ks = kzalloc(sizeof(*ks), GFP_KERNEL); | ||
781 | if (ks == NULL) { | ||
782 | kfree(client); | ||
783 | return -ENOMEM; | ||
784 | } | ||
785 | |||
786 | i2c_set_clientdata(client, ks); | ||
787 | client->adapter = adapter; | ||
788 | client->addr = addr; | ||
789 | sprintf(client->name, "ks0127-%02x", adapter->id); | ||
790 | |||
791 | ks->client = client; | ||
792 | ks->addr = addr; | ||
793 | ks->ks_type = KS_TYPE_UNKNOWN; | ||
794 | |||
795 | /* power up */ | ||
796 | ks0127_write(ks, KS_CMDA, 0x2c); | ||
797 | mdelay(10); | ||
798 | |||
799 | /* reset the device */ | ||
800 | ks0127_reset(ks); | ||
801 | printk(KERN_INFO "ks0127: attach: %s video decoder\n", | ||
802 | ks->addr==(I2C_KS0127_ADDON>>1) ? "addon" : "on-board"); | ||
803 | |||
804 | i2c_attach_client(client); | ||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | |||
809 | static int ks0127_probe(struct i2c_adapter *adapter) | ||
810 | { | ||
811 | if (adapter->id == I2C_HW_B_ZR36067) | ||
812 | return i2c_probe(adapter, &addr_data, ks0127_found_proc); | ||
813 | return 0; | ||
814 | } | ||
815 | |||
816 | static int ks0127_detach(struct i2c_client *client) | ||
817 | { | ||
818 | struct ks0127 *ks = i2c_get_clientdata(client); | ||
819 | |||
820 | ks0127_write(ks, KS_OFMTA, 0x20); /*tristate*/ | ||
821 | ks0127_write(ks, KS_CMDA, 0x2c | 0x80); /* power down */ | ||
822 | |||
823 | i2c_detach_client(client); | ||
824 | kfree(ks); | ||
825 | kfree(client); | ||
826 | |||
827 | dprintk("ks0127: detach\n"); | ||
828 | return 0; | ||
829 | } | ||
830 | |||
831 | |||
832 | static int __devinit ks0127_init_module(void) | ||
833 | { | ||
834 | init_reg_defaults(); | ||
835 | i2c_add_driver(&i2c_driver_ks0127); | ||
836 | return 0; | ||
837 | } | ||
838 | |||
839 | static void __devexit ks0127_cleanup_module(void) | ||
840 | { | ||
841 | i2c_del_driver(&i2c_driver_ks0127); | ||
842 | } | ||
843 | |||
844 | |||
845 | module_init(ks0127_init_module); | ||
846 | module_exit(ks0127_cleanup_module); | ||
diff --git a/drivers/media/video/ks0127.h b/drivers/media/video/ks0127.h new file mode 100644 index 000000000000..1ec578833aea --- /dev/null +++ b/drivers/media/video/ks0127.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Video Capture Driver ( Video for Linux 1/2 ) | ||
3 | * for the Matrox Marvel G200,G400 and Rainbow Runner-G series | ||
4 | * | ||
5 | * This module is an interface to the KS0127 video decoder chip. | ||
6 | * | ||
7 | * Copyright (C) 1999 Ryan Drake <stiletto@mediaone.net> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version 2 | ||
12 | * of the License, or (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | */ | ||
23 | |||
24 | #ifndef KS0127_H | ||
25 | #define KS0127_H | ||
26 | |||
27 | #include <linux/videodev.h> | ||
28 | |||
29 | /* input channels */ | ||
30 | #define KS_INPUT_COMPOSITE_1 0 | ||
31 | #define KS_INPUT_COMPOSITE_2 1 | ||
32 | #define KS_INPUT_COMPOSITE_3 2 | ||
33 | #define KS_INPUT_COMPOSITE_4 4 | ||
34 | #define KS_INPUT_COMPOSITE_5 5 | ||
35 | #define KS_INPUT_COMPOSITE_6 6 | ||
36 | |||
37 | #define KS_INPUT_SVIDEO_1 8 | ||
38 | #define KS_INPUT_SVIDEO_2 9 | ||
39 | #define KS_INPUT_SVIDEO_3 10 | ||
40 | |||
41 | #define KS_INPUT_YUV656 15 | ||
42 | #define KS_INPUT_COUNT 10 | ||
43 | |||
44 | /* output channels */ | ||
45 | #define KS_OUTPUT_YUV656E 0 | ||
46 | #define KS_OUTPUT_EXV 1 | ||
47 | |||
48 | /* video standards */ | ||
49 | #define KS_STD_NTSC_N 112 /* 50 Hz NTSC */ | ||
50 | #define KS_STD_PAL_M 113 /* 60 Hz PAL */ | ||
51 | |||
52 | #endif /* KS0127_H */ | ||
53 | |||
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 850bee97090c..f68ca7d9f531 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | #include <linux/videodev.h> | 34 | #include <linux/videodev.h> |
35 | #include <media/v4l2-common.h> | ||
35 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
36 | #include <asm/io.h> | 37 | #include <asm/io.h> |
37 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
@@ -1682,13 +1683,13 @@ static unsigned int meye_poll(struct file *file, poll_table *wait) | |||
1682 | 1683 | ||
1683 | static void meye_vm_open(struct vm_area_struct *vma) | 1684 | static void meye_vm_open(struct vm_area_struct *vma) |
1684 | { | 1685 | { |
1685 | int idx = (int)vma->vm_private_data; | 1686 | long idx = (long)vma->vm_private_data; |
1686 | meye.vma_use_count[idx]++; | 1687 | meye.vma_use_count[idx]++; |
1687 | } | 1688 | } |
1688 | 1689 | ||
1689 | static void meye_vm_close(struct vm_area_struct *vma) | 1690 | static void meye_vm_close(struct vm_area_struct *vma) |
1690 | { | 1691 | { |
1691 | int idx = (int)vma->vm_private_data; | 1692 | long idx = (long)vma->vm_private_data; |
1692 | meye.vma_use_count[idx]--; | 1693 | meye.vma_use_count[idx]--; |
1693 | } | 1694 | } |
1694 | 1695 | ||
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index b806999d6e0f..dbb75a7db199 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c | |||
@@ -385,67 +385,6 @@ static int msp_mode_v4l1_to_v4l2(int mode) | |||
385 | return V4L2_TUNER_MODE_MONO; | 385 | return V4L2_TUNER_MODE_MONO; |
386 | } | 386 | } |
387 | 387 | ||
388 | static struct v4l2_queryctrl msp_qctrl_std[] = { | ||
389 | { | ||
390 | .id = V4L2_CID_AUDIO_VOLUME, | ||
391 | .name = "Volume", | ||
392 | .minimum = 0, | ||
393 | .maximum = 65535, | ||
394 | .step = 65535/100, | ||
395 | .default_value = 58880, | ||
396 | .flags = 0, | ||
397 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
398 | },{ | ||
399 | .id = V4L2_CID_AUDIO_MUTE, | ||
400 | .name = "Mute", | ||
401 | .minimum = 0, | ||
402 | .maximum = 1, | ||
403 | .step = 1, | ||
404 | .default_value = 1, | ||
405 | .flags = 0, | ||
406 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
407 | }, | ||
408 | }; | ||
409 | |||
410 | static struct v4l2_queryctrl msp_qctrl_sound_processing[] = { | ||
411 | { | ||
412 | .id = V4L2_CID_AUDIO_BALANCE, | ||
413 | .name = "Balance", | ||
414 | .minimum = 0, | ||
415 | .maximum = 65535, | ||
416 | .step = 65535/100, | ||
417 | .default_value = 32768, | ||
418 | .flags = 0, | ||
419 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
420 | },{ | ||
421 | .id = V4L2_CID_AUDIO_BASS, | ||
422 | .name = "Bass", | ||
423 | .minimum = 0, | ||
424 | .maximum = 65535, | ||
425 | .step = 65535/100, | ||
426 | .default_value = 32768, | ||
427 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
428 | },{ | ||
429 | .id = V4L2_CID_AUDIO_TREBLE, | ||
430 | .name = "Treble", | ||
431 | .minimum = 0, | ||
432 | .maximum = 65535, | ||
433 | .step = 65535/100, | ||
434 | .default_value = 32768, | ||
435 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
436 | },{ | ||
437 | .id = V4L2_CID_AUDIO_LOUDNESS, | ||
438 | .name = "Loudness", | ||
439 | .minimum = 0, | ||
440 | .maximum = 1, | ||
441 | .step = 1, | ||
442 | .default_value = 1, | ||
443 | .flags = 0, | ||
444 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
445 | }, | ||
446 | }; | ||
447 | |||
448 | |||
449 | static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) | 388 | static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) |
450 | { | 389 | { |
451 | struct msp_state *state = i2c_get_clientdata(client); | 390 | struct msp_state *state = i2c_get_clientdata(client); |
@@ -674,22 +613,31 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
674 | int sc1_out = rt->output & 0xf; | 613 | int sc1_out = rt->output & 0xf; |
675 | int sc2_out = (rt->output >> 4) & 0xf; | 614 | int sc2_out = (rt->output >> 4) & 0xf; |
676 | u16 val, reg; | 615 | u16 val, reg; |
616 | int i; | ||
617 | int extern_input = 1; | ||
677 | 618 | ||
678 | if (state->routing.input == rt->input && | 619 | if (state->routing.input == rt->input && |
679 | state->routing.output == rt->output) | 620 | state->routing.output == rt->output) |
680 | break; | 621 | break; |
681 | state->routing = *rt; | 622 | state->routing = *rt; |
623 | /* check if the tuner input is used */ | ||
624 | for (i = 0; i < 5; i++) { | ||
625 | if (((rt->input >> (4 + i * 4)) & 0xf) == 0) | ||
626 | extern_input = 0; | ||
627 | } | ||
628 | if (extern_input) | ||
629 | state->mode = MSP_MODE_EXTERN; | ||
630 | else | ||
631 | state->mode = MSP_MODE_AM_DETECT; | ||
682 | msp_set_scart(client, sc_in, 0); | 632 | msp_set_scart(client, sc_in, 0); |
683 | msp_set_scart(client, sc1_out, 1); | 633 | msp_set_scart(client, sc1_out, 1); |
684 | msp_set_scart(client, sc2_out, 2); | 634 | msp_set_scart(client, sc2_out, 2); |
685 | msp_set_audmode(client); | 635 | msp_set_audmode(client); |
686 | reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb; | 636 | reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb; |
687 | val = msp_read_dem(client, reg); | 637 | val = msp_read_dem(client, reg); |
688 | if (tuner != ((val >> 8) & 1)) { | 638 | msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8)); |
689 | msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8)); | 639 | /* wake thread when a new input is chosen */ |
690 | /* wake thread when a new tuner input is chosen */ | 640 | msp_wake_thread(client); |
691 | msp_wake_thread(client); | ||
692 | } | ||
693 | break; | 641 | break; |
694 | } | 642 | } |
695 | 643 | ||
@@ -744,21 +692,25 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
744 | case VIDIOC_QUERYCTRL: | 692 | case VIDIOC_QUERYCTRL: |
745 | { | 693 | { |
746 | struct v4l2_queryctrl *qc = arg; | 694 | struct v4l2_queryctrl *qc = arg; |
747 | int i; | ||
748 | 695 | ||
749 | for (i = 0; i < ARRAY_SIZE(msp_qctrl_std); i++) | 696 | switch (qc->id) { |
750 | if (qc->id && qc->id == msp_qctrl_std[i].id) { | 697 | case V4L2_CID_AUDIO_VOLUME: |
751 | memcpy(qc, &msp_qctrl_std[i], sizeof(*qc)); | 698 | case V4L2_CID_AUDIO_MUTE: |
752 | return 0; | 699 | return v4l2_ctrl_query_fill_std(qc); |
753 | } | 700 | default: |
701 | break; | ||
702 | } | ||
754 | if (!state->has_sound_processing) | 703 | if (!state->has_sound_processing) |
755 | return -EINVAL; | 704 | return -EINVAL; |
756 | for (i = 0; i < ARRAY_SIZE(msp_qctrl_sound_processing); i++) | 705 | switch (qc->id) { |
757 | if (qc->id && qc->id == msp_qctrl_sound_processing[i].id) { | 706 | case V4L2_CID_AUDIO_LOUDNESS: |
758 | memcpy(qc, &msp_qctrl_sound_processing[i], sizeof(*qc)); | 707 | case V4L2_CID_AUDIO_BALANCE: |
759 | return 0; | 708 | case V4L2_CID_AUDIO_BASS: |
760 | } | 709 | case V4L2_CID_AUDIO_TREBLE: |
761 | return -EINVAL; | 710 | return v4l2_ctrl_query_fill_std(qc); |
711 | default: | ||
712 | return -EINVAL; | ||
713 | } | ||
762 | } | 714 | } |
763 | 715 | ||
764 | case VIDIOC_G_CTRL: | 716 | case VIDIOC_G_CTRL: |
@@ -794,7 +746,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
794 | case MSP_MODE_EXTERN: p = "External input"; break; | 746 | case MSP_MODE_EXTERN: p = "External input"; break; |
795 | default: p = "unknown"; break; | 747 | default: p = "unknown"; break; |
796 | } | 748 | } |
797 | if (state->opmode == OPMODE_MANUAL) { | 749 | if (state->mode == MSP_MODE_EXTERN) { |
750 | v4l_info(client, "Mode: %s\n", p); | ||
751 | } else if (state->opmode == OPMODE_MANUAL) { | ||
798 | v4l_info(client, "Mode: %s (%s%s)\n", p, | 752 | v4l_info(client, "Mode: %s (%s%s)\n", p, |
799 | (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", | 753 | (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", |
800 | (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); | 754 | (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); |
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 633a10213789..f2fd9195b3ac 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c | |||
@@ -244,19 +244,21 @@ static void msp3400c_set_audmode(struct i2c_client *client) | |||
244 | the hardware does not support SAP. So the rxsubchans combination | 244 | the hardware does not support SAP. So the rxsubchans combination |
245 | of STEREO | LANG2 does not occur. */ | 245 | of STEREO | LANG2 does not occur. */ |
246 | 246 | ||
247 | /* switch to mono if only mono is available */ | 247 | if (state->mode != MSP_MODE_EXTERN) { |
248 | if (state->rxsubchans == V4L2_TUNER_SUB_MONO) | 248 | /* switch to mono if only mono is available */ |
249 | audmode = V4L2_TUNER_MODE_MONO; | 249 | if (state->rxsubchans == V4L2_TUNER_SUB_MONO) |
250 | /* if bilingual */ | 250 | audmode = V4L2_TUNER_MODE_MONO; |
251 | else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) { | 251 | /* if bilingual */ |
252 | /* and mono or stereo, then fallback to lang1 */ | 252 | else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) { |
253 | if (audmode == V4L2_TUNER_MODE_MONO || | 253 | /* and mono or stereo, then fallback to lang1 */ |
254 | audmode == V4L2_TUNER_MODE_STEREO) | 254 | if (audmode == V4L2_TUNER_MODE_MONO || |
255 | audmode = V4L2_TUNER_MODE_LANG1; | 255 | audmode == V4L2_TUNER_MODE_STEREO) |
256 | audmode = V4L2_TUNER_MODE_LANG1; | ||
257 | } | ||
258 | /* if stereo, and audmode is not mono, then switch to stereo */ | ||
259 | else if (audmode != V4L2_TUNER_MODE_MONO) | ||
260 | audmode = V4L2_TUNER_MODE_STEREO; | ||
256 | } | 261 | } |
257 | /* if stereo, and audmode is not mono, then switch to stereo */ | ||
258 | else if (audmode != V4L2_TUNER_MODE_MONO) | ||
259 | audmode = V4L2_TUNER_MODE_STEREO; | ||
260 | 262 | ||
261 | /* switch demodulator */ | 263 | /* switch demodulator */ |
262 | switch (state->mode) { | 264 | switch (state->mode) { |
@@ -481,6 +483,7 @@ int msp3400c_thread(void *data) | |||
481 | /* no carrier scan, just unmute */ | 483 | /* no carrier scan, just unmute */ |
482 | v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); | 484 | v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); |
483 | state->scan_in_progress = 0; | 485 | state->scan_in_progress = 0; |
486 | state->rxsubchans = V4L2_TUNER_SUB_STEREO; | ||
484 | msp_set_audio(client); | 487 | msp_set_audio(client); |
485 | continue; | 488 | continue; |
486 | } | 489 | } |
@@ -947,6 +950,14 @@ int msp34xxg_thread(void *data) | |||
947 | if (kthread_should_stop()) | 950 | if (kthread_should_stop()) |
948 | break; | 951 | break; |
949 | 952 | ||
953 | if (state->mode == MSP_MODE_EXTERN) { | ||
954 | /* no carrier scan needed, just unmute */ | ||
955 | v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); | ||
956 | state->scan_in_progress = 0; | ||
957 | msp_set_audio(client); | ||
958 | continue; | ||
959 | } | ||
960 | |||
950 | /* setup the chip*/ | 961 | /* setup the chip*/ |
951 | msp34xxg_reset(client); | 962 | msp34xxg_reset(client); |
952 | state->std = state->radio ? 0x40 : msp_standard; | 963 | state->std = state->radio ? 0x40 : msp_standard; |
@@ -978,6 +989,11 @@ int msp34xxg_thread(void *data) | |||
978 | v4l_dbg(1, msp_debug, client, "detected standard: %s (0x%04x)\n", | 989 | v4l_dbg(1, msp_debug, client, "detected standard: %s (0x%04x)\n", |
979 | msp_standard_std_name(state->std), state->std); | 990 | msp_standard_std_name(state->std), state->std); |
980 | 991 | ||
992 | if (state->std == 9) { | ||
993 | /* AM NICAM mode */ | ||
994 | msp_write_dsp(client, 0x0e, 0x7c00); | ||
995 | } | ||
996 | |||
981 | /* unmute: dispatch sound to scart output, set scart volume */ | 997 | /* unmute: dispatch sound to scart output, set scart volume */ |
982 | msp_set_audio(client); | 998 | msp_set_audio(client); |
983 | 999 | ||
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index fdc8e3f13937..a988df226aab 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c | |||
@@ -3239,7 +3239,7 @@ ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n) | |||
3239 | RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); | 3239 | RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); |
3240 | 3240 | ||
3241 | if (frame->scanstate == STATE_LINES) { | 3241 | if (frame->scanstate == STATE_LINES) { |
3242 | int nextf; | 3242 | int nextf; |
3243 | 3243 | ||
3244 | frame->grabstate = FRAME_DONE; | 3244 | frame->grabstate = FRAME_DONE; |
3245 | wake_up_interruptible(&frame->wq); | 3245 | wake_up_interruptible(&frame->wq); |
@@ -3405,7 +3405,7 @@ eof: | |||
3405 | RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); | 3405 | RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); |
3406 | 3406 | ||
3407 | if (frame->scanstate == STATE_LINES) { | 3407 | if (frame->scanstate == STATE_LINES) { |
3408 | int nextf; | 3408 | int nextf; |
3409 | 3409 | ||
3410 | frame->grabstate = FRAME_DONE; | 3410 | frame->grabstate = FRAME_DONE; |
3411 | wake_up_interruptible(&frame->wq); | 3411 | wake_up_interruptible(&frame->wq); |
diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h index 12b3d51e1c34..68b082bcee1d 100644 --- a/drivers/media/video/ov511.h +++ b/drivers/media/video/ov511.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <asm/uaccess.h> | 4 | #include <asm/uaccess.h> |
5 | #include <linux/videodev.h> | 5 | #include <linux/videodev.h> |
6 | #include <media/v4l2-common.h> | ||
6 | #include <linux/smp_lock.h> | 7 | #include <linux/smp_lock.h> |
7 | #include <linux/usb.h> | 8 | #include <linux/usb.h> |
8 | #include <linux/mutex.h> | 9 | #include <linux/mutex.h> |
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index d9e3cada52f4..3484e36b6801 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/mm.h> | 40 | #include <linux/mm.h> |
41 | #include <linux/sched.h> | 41 | #include <linux/sched.h> |
42 | #include <linux/videodev.h> | 42 | #include <linux/videodev.h> |
43 | #include <media/v4l2-common.h> | ||
43 | #include <linux/wait.h> | 44 | #include <linux/wait.h> |
44 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
45 | #include <asm/io.h> | 46 | #include <asm/io.h> |
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 09835ca098b1..5d681fa8bcb1 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <asm/io.h> | 30 | #include <asm/io.h> |
31 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
32 | #include <linux/videodev.h> | 32 | #include <linux/videodev.h> |
33 | #include <media/v4l2-common.h> | ||
33 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
34 | 35 | ||
35 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
@@ -804,7 +805,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file, | |||
804 | struct video_picture *p = arg; | 805 | struct video_picture *p = arg; |
805 | if(!((p->palette==VIDEO_PALETTE_RGB565 && p->depth==16) | 806 | if(!((p->palette==VIDEO_PALETTE_RGB565 && p->depth==16) |
806 | ||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15))) | 807 | ||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15))) |
807 | return -EINVAL; | 808 | return -EINVAL; |
808 | pd->picture= *p; | 809 | pd->picture= *p; |
809 | 810 | ||
810 | /* | 811 | /* |
diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig index 53cbc950f95c..697145e0bf15 100644 --- a/drivers/media/video/pwc/Kconfig +++ b/drivers/media/video/pwc/Kconfig | |||
@@ -7,6 +7,7 @@ config USB_PWC | |||
7 | * Philips PCA645, PCA646 | 7 | * Philips PCA645, PCA646 |
8 | * Philips PCVC675, PCVC680, PCVC690 | 8 | * Philips PCVC675, PCVC680, PCVC690 |
9 | * Philips PCVC720/40, PCVC730, PCVC740, PCVC750 | 9 | * Philips PCVC720/40, PCVC730, PCVC740, PCVC750 |
10 | * Philips SPC900NC | ||
10 | * Askey VC010 | 11 | * Askey VC010 |
11 | * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' | 12 | * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' |
12 | and 'Orbit'/'Sphere' | 13 | and 'Orbit'/'Sphere' |
@@ -19,10 +20,18 @@ config USB_PWC | |||
19 | and never will be, but the 665 and 720/20 are supported by other | 20 | and never will be, but the 665 and 720/20 are supported by other |
20 | drivers. | 21 | drivers. |
21 | 22 | ||
22 | See <file:Documentation/usb/philips.txt> for more information and | 23 | Some newer logitech webcams are not handled by this driver but by the |
23 | installation instructions. | 24 | Usb Video Class driver (linux-uvc). |
24 | 25 | ||
25 | The built-in microphone is enabled by selecting USB Audio support. | 26 | The built-in microphone is enabled by selecting USB Audio support. |
26 | 27 | ||
27 | To compile this driver as a module, choose M here: the | 28 | To compile this driver as a module, choose M here: the |
28 | module will be called pwc. | 29 | module will be called pwc. |
30 | |||
31 | config USB_PWC_DEBUG | ||
32 | bool "USB Philips Cameras verbose debug" | ||
33 | depends USB_PWC | ||
34 | help | ||
35 | Say Y here in order to have the pwc driver generate verbose debugging | ||
36 | messages. | ||
37 | A special module options 'trace' is used to control the verbosity. | ||
diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/video/pwc/Makefile index 33d60126c024..9db2260d10cc 100644 --- a/drivers/media/video/pwc/Makefile +++ b/drivers/media/video/pwc/Makefile | |||
@@ -1,3 +1,12 @@ | |||
1 | pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o | 1 | pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o |
2 | pwc-objs += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o | ||
2 | 3 | ||
3 | obj-$(CONFIG_USB_PWC) += pwc.o | 4 | obj-$(CONFIG_USB_PWC) += pwc.o |
5 | |||
6 | ifeq ($(CONFIG_USB_PWC_DEBUG),y) | ||
7 | EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=1 | ||
8 | else | ||
9 | EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=0 | ||
10 | endif | ||
11 | |||
12 | |||
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index 4ba549bfa0e0..0bd115588f31 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c | |||
@@ -2,7 +2,7 @@ | |||
2 | Functions that send various control messages to the webcam, including | 2 | Functions that send various control messages to the webcam, including |
3 | video modes. | 3 | video modes. |
4 | (C) 1999-2003 Nemosoft Unv. | 4 | (C) 1999-2003 Nemosoft Unv. |
5 | (C) 2004 Luc Saillard (luc@saillard.org) | 5 | (C) 2004-2006 Luc Saillard (luc@saillard.org) |
6 | 6 | ||
7 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 7 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx |
8 | driver and thus may have bugs that are not present in the original version. | 8 | driver and thus may have bugs that are not present in the original version. |
@@ -41,12 +41,14 @@ | |||
41 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
42 | #endif | 42 | #endif |
43 | #include <asm/errno.h> | 43 | #include <asm/errno.h> |
44 | #include <linux/version.h> | ||
44 | 45 | ||
45 | #include "pwc.h" | 46 | #include "pwc.h" |
46 | #include "pwc-ioctl.h" | ||
47 | #include "pwc-uncompress.h" | 47 | #include "pwc-uncompress.h" |
48 | #include "pwc-kiara.h" | 48 | #include "pwc-kiara.h" |
49 | #include "pwc-timon.h" | 49 | #include "pwc-timon.h" |
50 | #include "pwc-dec1.h" | ||
51 | #include "pwc-dec23.h" | ||
50 | 52 | ||
51 | /* Request types: video */ | 53 | /* Request types: video */ |
52 | #define SET_LUM_CTL 0x01 | 54 | #define SET_LUM_CTL 0x01 |
@@ -57,6 +59,10 @@ | |||
57 | #define GET_STATUS_CTL 0x06 | 59 | #define GET_STATUS_CTL 0x06 |
58 | #define SET_EP_STREAM_CTL 0x07 | 60 | #define SET_EP_STREAM_CTL 0x07 |
59 | #define GET_EP_STREAM_CTL 0x08 | 61 | #define GET_EP_STREAM_CTL 0x08 |
62 | #define GET_XX_CTL 0x09 | ||
63 | #define SET_XX_CTL 0x0A | ||
64 | #define GET_XY_CTL 0x0B | ||
65 | #define SET_XY_CTL 0x0C | ||
60 | #define SET_MPT_CTL 0x0D | 66 | #define SET_MPT_CTL 0x0D |
61 | #define GET_MPT_CTL 0x0E | 67 | #define GET_MPT_CTL 0x0E |
62 | 68 | ||
@@ -93,12 +99,20 @@ | |||
93 | #define READ_SHUTTER_FORMATTER 0x0600 | 99 | #define READ_SHUTTER_FORMATTER 0x0600 |
94 | #define READ_RED_GAIN_FORMATTER 0x0700 | 100 | #define READ_RED_GAIN_FORMATTER 0x0700 |
95 | #define READ_BLUE_GAIN_FORMATTER 0x0800 | 101 | #define READ_BLUE_GAIN_FORMATTER 0x0800 |
102 | #define GET_STATUS_B00 0x0B00 | ||
96 | #define SENSOR_TYPE_FORMATTER1 0x0C00 | 103 | #define SENSOR_TYPE_FORMATTER1 0x0C00 |
104 | #define GET_STATUS_3000 0x3000 | ||
97 | #define READ_RAW_Y_MEAN_FORMATTER 0x3100 | 105 | #define READ_RAW_Y_MEAN_FORMATTER 0x3100 |
98 | #define SET_POWER_SAVE_MODE_FORMATTER 0x3200 | 106 | #define SET_POWER_SAVE_MODE_FORMATTER 0x3200 |
99 | #define MIRROR_IMAGE_FORMATTER 0x3300 | 107 | #define MIRROR_IMAGE_FORMATTER 0x3300 |
100 | #define LED_FORMATTER 0x3400 | 108 | #define LED_FORMATTER 0x3400 |
109 | #define LOWLIGHT 0x3500 | ||
110 | #define GET_STATUS_3600 0x3600 | ||
101 | #define SENSOR_TYPE_FORMATTER2 0x3700 | 111 | #define SENSOR_TYPE_FORMATTER2 0x3700 |
112 | #define GET_STATUS_3800 0x3800 | ||
113 | #define GET_STATUS_4000 0x4000 | ||
114 | #define GET_STATUS_4100 0x4100 /* Get */ | ||
115 | #define CTL_STATUS_4200 0x4200 /* [GS] 1 */ | ||
102 | 116 | ||
103 | /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */ | 117 | /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */ |
104 | #define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100 | 118 | #define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100 |
@@ -138,6 +152,7 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][8] = | |||
138 | #include "pwc-nala.h" | 152 | #include "pwc-nala.h" |
139 | }; | 153 | }; |
140 | 154 | ||
155 | static void pwc_set_image_buffer_size(struct pwc_device *pdev); | ||
141 | 156 | ||
142 | /****************************************************************************/ | 157 | /****************************************************************************/ |
143 | 158 | ||
@@ -159,31 +174,7 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][8] = | |||
159 | &buf, buflen, 500) | 174 | &buf, buflen, 500) |
160 | 175 | ||
161 | 176 | ||
162 | #if PWC_DEBUG | 177 | static int send_video_command(struct usb_device *udev, int index, void *buf, int buflen) |
163 | void pwc_hexdump(void *p, int len) | ||
164 | { | ||
165 | int i; | ||
166 | unsigned char *s; | ||
167 | char buf[100], *d; | ||
168 | |||
169 | s = (unsigned char *)p; | ||
170 | d = buf; | ||
171 | *d = '\0'; | ||
172 | Debug("Doing hexdump @ %p, %d bytes.\n", p, len); | ||
173 | for (i = 0; i < len; i++) { | ||
174 | d += sprintf(d, "%02X ", *s++); | ||
175 | if ((i & 0xF) == 0xF) { | ||
176 | Debug("%s\n", buf); | ||
177 | d = buf; | ||
178 | *d = '\0'; | ||
179 | } | ||
180 | } | ||
181 | if ((i & 0xF) != 0) | ||
182 | Debug("%s\n", buf); | ||
183 | } | ||
184 | #endif | ||
185 | |||
186 | static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen) | ||
187 | { | 178 | { |
188 | return usb_control_msg(udev, | 179 | return usb_control_msg(udev, |
189 | usb_sndctrlpipe(udev, 0), | 180 | usb_sndctrlpipe(udev, 0), |
@@ -196,7 +187,7 @@ static inline int send_video_command(struct usb_device *udev, int index, void *b | |||
196 | 187 | ||
197 | 188 | ||
198 | 189 | ||
199 | static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) | 190 | static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) |
200 | { | 191 | { |
201 | unsigned char buf[3]; | 192 | unsigned char buf[3]; |
202 | int ret, fps; | 193 | int ret, fps; |
@@ -229,34 +220,14 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra | |||
229 | if (pEntry->alternate == 0) | 220 | if (pEntry->alternate == 0) |
230 | return -EINVAL; | 221 | return -EINVAL; |
231 | 222 | ||
232 | if (pEntry->compressed) | ||
233 | return -ENOENT; /* Not supported. */ | ||
234 | |||
235 | memcpy(buf, pEntry->mode, 3); | 223 | memcpy(buf, pEntry->mode, 3); |
236 | ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); | 224 | ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); |
237 | if (ret < 0) { | 225 | if (ret < 0) { |
238 | Debug("Failed to send video command... %d\n", ret); | 226 | PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret); |
239 | return ret; | 227 | return ret; |
240 | } | 228 | } |
241 | if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW) | 229 | if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW) |
242 | { | 230 | pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); |
243 | switch(pdev->type) { | ||
244 | case 645: | ||
245 | case 646: | ||
246 | /* pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ | ||
247 | break; | ||
248 | |||
249 | case 675: | ||
250 | case 680: | ||
251 | case 690: | ||
252 | case 720: | ||
253 | case 730: | ||
254 | case 740: | ||
255 | case 750: | ||
256 | /* pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ | ||
257 | break; | ||
258 | } | ||
259 | } | ||
260 | 231 | ||
261 | pdev->cmd_len = 3; | 232 | pdev->cmd_len = 3; |
262 | memcpy(pdev->cmd_buf, buf, 3); | 233 | memcpy(pdev->cmd_buf, buf, 3); |
@@ -283,7 +254,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra | |||
283 | } | 254 | } |
284 | 255 | ||
285 | 256 | ||
286 | static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) | 257 | static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) |
287 | { | 258 | { |
288 | unsigned char buf[13]; | 259 | unsigned char buf[13]; |
289 | const struct Timon_table_entry *pChoose; | 260 | const struct Timon_table_entry *pChoose; |
@@ -315,8 +286,8 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr | |||
315 | if (ret < 0) | 286 | if (ret < 0) |
316 | return ret; | 287 | return ret; |
317 | 288 | ||
318 | /* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) | 289 | if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) |
319 | pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ | 290 | pwc_dec23_init(pdev, pdev->type, buf); |
320 | 291 | ||
321 | pdev->cmd_len = 13; | 292 | pdev->cmd_len = 13; |
322 | memcpy(pdev->cmd_buf, buf, 13); | 293 | memcpy(pdev->cmd_buf, buf, 13); |
@@ -336,7 +307,7 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr | |||
336 | } | 307 | } |
337 | 308 | ||
338 | 309 | ||
339 | static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) | 310 | static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) |
340 | { | 311 | { |
341 | const struct Kiara_table_entry *pChoose = NULL; | 312 | const struct Kiara_table_entry *pChoose = NULL; |
342 | int fps, ret; | 313 | int fps, ret; |
@@ -350,21 +321,14 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr | |||
350 | fps = (frames / 5) - 1; | 321 | fps = (frames / 5) - 1; |
351 | 322 | ||
352 | /* special case: VGA @ 5 fps and snapshot is raw bayer mode */ | 323 | /* special case: VGA @ 5 fps and snapshot is raw bayer mode */ |
353 | if (size == PSZ_VGA && frames == 5 && snapshot) | 324 | if (size == PSZ_VGA && frames == 5 && snapshot && pdev->vpalette == VIDEO_PALETTE_RAW) |
354 | { | 325 | { |
355 | /* Only available in case the raw palette is selected or | 326 | /* Only available in case the raw palette is selected or |
356 | we have the decompressor available. This mode is | 327 | we have the decompressor available. This mode is |
357 | only available in compressed form | 328 | only available in compressed form |
358 | */ | 329 | */ |
359 | if (pdev->vpalette == VIDEO_PALETTE_RAW) | 330 | PWC_DEBUG_SIZE("Choosing VGA/5 BAYER mode.\n"); |
360 | { | 331 | pChoose = &RawEntry; |
361 | Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette); | ||
362 | pChoose = &RawEntry; | ||
363 | } | ||
364 | else | ||
365 | { | ||
366 | Info("VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.\n"); | ||
367 | } | ||
368 | } | 332 | } |
369 | else | 333 | else |
370 | { | 334 | { |
@@ -372,6 +336,7 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr | |||
372 | if the preferred ratio is not available. | 336 | if the preferred ratio is not available. |
373 | Skip this step when using RAW modes. | 337 | Skip this step when using RAW modes. |
374 | */ | 338 | */ |
339 | snapshot = 0; | ||
375 | while (compression <= 3) { | 340 | while (compression <= 3) { |
376 | pChoose = &Kiara_table[size][fps][compression]; | 341 | pChoose = &Kiara_table[size][fps][compression]; |
377 | if (pChoose->alternate != 0) | 342 | if (pChoose->alternate != 0) |
@@ -382,7 +347,7 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr | |||
382 | if (pChoose == NULL || pChoose->alternate == 0) | 347 | if (pChoose == NULL || pChoose->alternate == 0) |
383 | return -ENOENT; /* Not supported. */ | 348 | return -ENOENT; /* Not supported. */ |
384 | 349 | ||
385 | Debug("Using alternate setting %d.\n", pChoose->alternate); | 350 | PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate); |
386 | 351 | ||
387 | /* usb_control_msg won't take staticly allocated arrays as argument?? */ | 352 | /* usb_control_msg won't take staticly allocated arrays as argument?? */ |
388 | memcpy(buf, pChoose->mode, 12); | 353 | memcpy(buf, pChoose->mode, 12); |
@@ -394,8 +359,8 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr | |||
394 | if (ret < 0) | 359 | if (ret < 0) |
395 | return ret; | 360 | return ret; |
396 | 361 | ||
397 | /* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) | 362 | if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) |
398 | pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ | 363 | pwc_dec23_init(pdev, pdev->type, buf); |
399 | 364 | ||
400 | pdev->cmd_len = 12; | 365 | pdev->cmd_len = 12; |
401 | memcpy(pdev->cmd_buf, buf, 12); | 366 | memcpy(pdev->cmd_buf, buf, 12); |
@@ -410,49 +375,13 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr | |||
410 | pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4; | 375 | pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4; |
411 | else | 376 | else |
412 | pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; | 377 | pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; |
378 | PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vsnapshot=%d, vbandlength=%d\n", | ||
379 | pdev->frame_size,pdev->vframes,pdev->vsize,pdev->vsnapshot,pdev->vbandlength); | ||
413 | return 0; | 380 | return 0; |
414 | } | 381 | } |
415 | 382 | ||
416 | 383 | ||
417 | 384 | ||
418 | static void pwc_set_image_buffer_size(struct pwc_device *pdev) | ||
419 | { | ||
420 | int i, factor = 0, filler = 0; | ||
421 | |||
422 | /* for PALETTE_YUV420P */ | ||
423 | switch(pdev->vpalette) | ||
424 | { | ||
425 | case VIDEO_PALETTE_YUV420P: | ||
426 | factor = 6; | ||
427 | filler = 128; | ||
428 | break; | ||
429 | case VIDEO_PALETTE_RAW: | ||
430 | factor = 6; /* can be uncompressed YUV420P */ | ||
431 | filler = 0; | ||
432 | break; | ||
433 | } | ||
434 | |||
435 | /* Set sizes in bytes */ | ||
436 | pdev->image.size = pdev->image.x * pdev->image.y * factor / 4; | ||
437 | pdev->view.size = pdev->view.x * pdev->view.y * factor / 4; | ||
438 | |||
439 | /* Align offset, or you'll get some very weird results in | ||
440 | YUV420 mode... x must be multiple of 4 (to get the Y's in | ||
441 | place), and y even (or you'll mixup U & V). This is less of a | ||
442 | problem for YUV420P. | ||
443 | */ | ||
444 | pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC; | ||
445 | pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE; | ||
446 | |||
447 | /* Fill buffers with gray or black */ | ||
448 | for (i = 0; i < MAX_IMAGES; i++) { | ||
449 | if (pdev->image_ptr[i] != NULL) | ||
450 | memset(pdev->image_ptr[i], filler, pdev->view.size); | ||
451 | } | ||
452 | } | ||
453 | |||
454 | |||
455 | |||
456 | /** | 385 | /** |
457 | @pdev: device structure | 386 | @pdev: device structure |
458 | @width: viewport width | 387 | @width: viewport width |
@@ -465,50 +394,78 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame | |||
465 | { | 394 | { |
466 | int ret, size; | 395 | int ret, size; |
467 | 396 | ||
468 | Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette); | 397 | PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette); |
469 | size = pwc_decode_size(pdev, width, height); | 398 | size = pwc_decode_size(pdev, width, height); |
470 | if (size < 0) { | 399 | if (size < 0) { |
471 | Debug("Could not find suitable size.\n"); | 400 | PWC_DEBUG_MODULE("Could not find suitable size.\n"); |
472 | return -ERANGE; | 401 | return -ERANGE; |
473 | } | 402 | } |
474 | Debug("decode_size = %d.\n", size); | 403 | PWC_TRACE("decode_size = %d.\n", size); |
475 | 404 | ||
476 | ret = -EINVAL; | 405 | if (DEVICE_USE_CODEC1(pdev->type)) { |
477 | switch(pdev->type) { | ||
478 | case 645: | ||
479 | case 646: | ||
480 | ret = set_video_mode_Nala(pdev, size, frames); | 406 | ret = set_video_mode_Nala(pdev, size, frames); |
481 | break; | ||
482 | 407 | ||
483 | case 675: | 408 | } else if (DEVICE_USE_CODEC3(pdev->type)) { |
484 | case 680: | ||
485 | case 690: | ||
486 | ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot); | ||
487 | break; | ||
488 | |||
489 | case 720: | ||
490 | case 730: | ||
491 | case 740: | ||
492 | case 750: | ||
493 | ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot); | 409 | ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot); |
494 | break; | 410 | |
411 | } else { | ||
412 | ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot); | ||
495 | } | 413 | } |
496 | if (ret < 0) { | 414 | if (ret < 0) { |
497 | if (ret == -ENOENT) | 415 | PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); |
498 | Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames); | ||
499 | else { | ||
500 | Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); | ||
501 | } | ||
502 | return ret; | 416 | return ret; |
503 | } | 417 | } |
504 | pdev->view.x = width; | 418 | pdev->view.x = width; |
505 | pdev->view.y = height; | 419 | pdev->view.y = height; |
506 | pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; | 420 | pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; |
507 | pwc_set_image_buffer_size(pdev); | 421 | pwc_set_image_buffer_size(pdev); |
508 | Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y); | 422 | PWC_DEBUG_SIZE("Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y); |
509 | return 0; | 423 | return 0; |
510 | } | 424 | } |
511 | 425 | ||
426 | #define BLACK_Y 0 | ||
427 | #define BLACK_U 128 | ||
428 | #define BLACK_V 128 | ||
429 | |||
430 | static void pwc_set_image_buffer_size(struct pwc_device *pdev) | ||
431 | { | ||
432 | int i, factor = 0; | ||
433 | |||
434 | /* for PALETTE_YUV420P */ | ||
435 | switch(pdev->vpalette) | ||
436 | { | ||
437 | case VIDEO_PALETTE_YUV420P: | ||
438 | factor = 6; | ||
439 | break; | ||
440 | case VIDEO_PALETTE_RAW: | ||
441 | factor = 6; /* can be uncompressed YUV420P */ | ||
442 | break; | ||
443 | } | ||
444 | |||
445 | /* Set sizes in bytes */ | ||
446 | pdev->image.size = pdev->image.x * pdev->image.y * factor / 4; | ||
447 | pdev->view.size = pdev->view.x * pdev->view.y * factor / 4; | ||
448 | |||
449 | /* Align offset, or you'll get some very weird results in | ||
450 | YUV420 mode... x must be multiple of 4 (to get the Y's in | ||
451 | place), and y even (or you'll mixup U & V). This is less of a | ||
452 | problem for YUV420P. | ||
453 | */ | ||
454 | pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC; | ||
455 | pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE; | ||
456 | |||
457 | /* Fill buffers with black colors */ | ||
458 | for (i = 0; i < pwc_mbufs; i++) { | ||
459 | unsigned char *p = pdev->image_data + pdev->images[i].offset; | ||
460 | memset(p, BLACK_Y, pdev->view.x * pdev->view.y); | ||
461 | p += pdev->view.x * pdev->view.y; | ||
462 | memset(p, BLACK_U, pdev->view.x * pdev->view.y/4); | ||
463 | p += pdev->view.x * pdev->view.y/4; | ||
464 | memset(p, BLACK_V, pdev->view.x * pdev->view.y/4); | ||
465 | } | ||
466 | } | ||
467 | |||
468 | |||
512 | 469 | ||
513 | /* BRIGHTNESS */ | 470 | /* BRIGHTNESS */ |
514 | 471 | ||
@@ -520,7 +477,7 @@ int pwc_get_brightness(struct pwc_device *pdev) | |||
520 | ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); | 477 | ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); |
521 | if (ret < 0) | 478 | if (ret < 0) |
522 | return ret; | 479 | return ret; |
523 | return buf << 9; | 480 | return buf; |
524 | } | 481 | } |
525 | 482 | ||
526 | int pwc_set_brightness(struct pwc_device *pdev, int value) | 483 | int pwc_set_brightness(struct pwc_device *pdev, int value) |
@@ -545,7 +502,7 @@ int pwc_get_contrast(struct pwc_device *pdev) | |||
545 | ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1); | 502 | ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1); |
546 | if (ret < 0) | 503 | if (ret < 0) |
547 | return ret; | 504 | return ret; |
548 | return buf << 10; | 505 | return buf; |
549 | } | 506 | } |
550 | 507 | ||
551 | int pwc_set_contrast(struct pwc_device *pdev, int value) | 508 | int pwc_set_contrast(struct pwc_device *pdev, int value) |
@@ -570,7 +527,7 @@ int pwc_get_gamma(struct pwc_device *pdev) | |||
570 | ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1); | 527 | ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1); |
571 | if (ret < 0) | 528 | if (ret < 0) |
572 | return ret; | 529 | return ret; |
573 | return buf << 11; | 530 | return buf; |
574 | } | 531 | } |
575 | 532 | ||
576 | int pwc_set_gamma(struct pwc_device *pdev, int value) | 533 | int pwc_set_gamma(struct pwc_device *pdev, int value) |
@@ -588,37 +545,47 @@ int pwc_set_gamma(struct pwc_device *pdev, int value) | |||
588 | 545 | ||
589 | /* SATURATION */ | 546 | /* SATURATION */ |
590 | 547 | ||
591 | int pwc_get_saturation(struct pwc_device *pdev) | 548 | /* return a value between [-100 , 100] */ |
549 | int pwc_get_saturation(struct pwc_device *pdev, int *value) | ||
592 | { | 550 | { |
593 | char buf; | 551 | char buf; |
594 | int ret; | 552 | int ret, saturation_register; |
595 | 553 | ||
596 | if (pdev->type < 675) | 554 | if (pdev->type < 675) |
597 | return -1; | 555 | return -EINVAL; |
598 | ret = RecvControlMsg(GET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1); | 556 | if (pdev->type < 730) |
557 | saturation_register = SATURATION_MODE_FORMATTER2; | ||
558 | else | ||
559 | saturation_register = SATURATION_MODE_FORMATTER1; | ||
560 | ret = RecvControlMsg(GET_CHROM_CTL, saturation_register, 1); | ||
599 | if (ret < 0) | 561 | if (ret < 0) |
600 | return ret; | 562 | return ret; |
601 | return 32768 + buf * 327; | 563 | *value = (signed)buf; |
564 | return 0; | ||
602 | } | 565 | } |
603 | 566 | ||
567 | /* @param value saturation color between [-100 , 100] */ | ||
604 | int pwc_set_saturation(struct pwc_device *pdev, int value) | 568 | int pwc_set_saturation(struct pwc_device *pdev, int value) |
605 | { | 569 | { |
606 | char buf; | 570 | char buf; |
571 | int saturation_register; | ||
607 | 572 | ||
608 | if (pdev->type < 675) | 573 | if (pdev->type < 675) |
609 | return -EINVAL; | 574 | return -EINVAL; |
610 | if (value < 0) | 575 | if (value < -100) |
611 | value = 0; | 576 | value = -100; |
612 | if (value > 0xffff) | 577 | if (value > 100) |
613 | value = 0xffff; | 578 | value = 100; |
614 | /* saturation ranges from -100 to +100 */ | 579 | if (pdev->type < 730) |
615 | buf = (value - 32768) / 327; | 580 | saturation_register = SATURATION_MODE_FORMATTER2; |
616 | return SendControlMsg(SET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1); | 581 | else |
582 | saturation_register = SATURATION_MODE_FORMATTER1; | ||
583 | return SendControlMsg(SET_CHROM_CTL, saturation_register, 1); | ||
617 | } | 584 | } |
618 | 585 | ||
619 | /* AGC */ | 586 | /* AGC */ |
620 | 587 | ||
621 | static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value) | 588 | int pwc_set_agc(struct pwc_device *pdev, int mode, int value) |
622 | { | 589 | { |
623 | char buf; | 590 | char buf; |
624 | int ret; | 591 | int ret; |
@@ -643,7 +610,7 @@ static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value) | |||
643 | return 0; | 610 | return 0; |
644 | } | 611 | } |
645 | 612 | ||
646 | static inline int pwc_get_agc(struct pwc_device *pdev, int *value) | 613 | int pwc_get_agc(struct pwc_device *pdev, int *value) |
647 | { | 614 | { |
648 | unsigned char buf; | 615 | unsigned char buf; |
649 | int ret; | 616 | int ret; |
@@ -673,7 +640,7 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value) | |||
673 | return 0; | 640 | return 0; |
674 | } | 641 | } |
675 | 642 | ||
676 | static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) | 643 | int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) |
677 | { | 644 | { |
678 | char buf[2]; | 645 | char buf[2]; |
679 | int speed, ret; | 646 | int speed, ret; |
@@ -691,23 +658,16 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v | |||
691 | value = 0; | 658 | value = 0; |
692 | if (value > 0xffff) | 659 | if (value > 0xffff) |
693 | value = 0xffff; | 660 | value = 0xffff; |
694 | switch(pdev->type) { | 661 | |
695 | case 675: | 662 | if (DEVICE_USE_CODEC2(pdev->type)) { |
696 | case 680: | ||
697 | case 690: | ||
698 | /* speed ranges from 0x0 to 0x290 (656) */ | 663 | /* speed ranges from 0x0 to 0x290 (656) */ |
699 | speed = (value / 100); | 664 | speed = (value / 100); |
700 | buf[1] = speed >> 8; | 665 | buf[1] = speed >> 8; |
701 | buf[0] = speed & 0xff; | 666 | buf[0] = speed & 0xff; |
702 | break; | 667 | } else if (DEVICE_USE_CODEC3(pdev->type)) { |
703 | case 720: | ||
704 | case 730: | ||
705 | case 740: | ||
706 | case 750: | ||
707 | /* speed seems to range from 0x0 to 0xff */ | 668 | /* speed seems to range from 0x0 to 0xff */ |
708 | buf[1] = 0; | 669 | buf[1] = 0; |
709 | buf[0] = value >> 8; | 670 | buf[0] = value >> 8; |
710 | break; | ||
711 | } | 671 | } |
712 | 672 | ||
713 | ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2); | 673 | ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2); |
@@ -715,6 +675,25 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v | |||
715 | return ret; | 675 | return ret; |
716 | } | 676 | } |
717 | 677 | ||
678 | /* This function is not exported to v4l1, so output values between 0 -> 256 */ | ||
679 | int pwc_get_shutter_speed(struct pwc_device *pdev, int *value) | ||
680 | { | ||
681 | unsigned char buf[2]; | ||
682 | int ret; | ||
683 | |||
684 | ret = RecvControlMsg(GET_STATUS_CTL, READ_SHUTTER_FORMATTER, 2); | ||
685 | if (ret < 0) | ||
686 | return ret; | ||
687 | *value = buf[0] + (buf[1] << 8); | ||
688 | if (DEVICE_USE_CODEC2(pdev->type)) { | ||
689 | /* speed ranges from 0x0 to 0x290 (656) */ | ||
690 | *value *= 256/656; | ||
691 | } else if (DEVICE_USE_CODEC3(pdev->type)) { | ||
692 | /* speed seems to range from 0x0 to 0xff */ | ||
693 | } | ||
694 | return 0; | ||
695 | } | ||
696 | |||
718 | 697 | ||
719 | /* POWER */ | 698 | /* POWER */ |
720 | 699 | ||
@@ -736,19 +715,19 @@ int pwc_camera_power(struct pwc_device *pdev, int power) | |||
736 | 715 | ||
737 | /* private calls */ | 716 | /* private calls */ |
738 | 717 | ||
739 | static inline int pwc_restore_user(struct pwc_device *pdev) | 718 | int pwc_restore_user(struct pwc_device *pdev) |
740 | { | 719 | { |
741 | char buf; /* dummy */ | 720 | char buf; /* dummy */ |
742 | return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0); | 721 | return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0); |
743 | } | 722 | } |
744 | 723 | ||
745 | static inline int pwc_save_user(struct pwc_device *pdev) | 724 | int pwc_save_user(struct pwc_device *pdev) |
746 | { | 725 | { |
747 | char buf; /* dummy */ | 726 | char buf; /* dummy */ |
748 | return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0); | 727 | return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0); |
749 | } | 728 | } |
750 | 729 | ||
751 | static inline int pwc_restore_factory(struct pwc_device *pdev) | 730 | int pwc_restore_factory(struct pwc_device *pdev) |
752 | { | 731 | { |
753 | char buf; /* dummy */ | 732 | char buf; /* dummy */ |
754 | return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0); | 733 | return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0); |
@@ -766,7 +745,7 @@ static inline int pwc_restore_factory(struct pwc_device *pdev) | |||
766 | * 03: manual | 745 | * 03: manual |
767 | * 04: auto | 746 | * 04: auto |
768 | */ | 747 | */ |
769 | static inline int pwc_set_awb(struct pwc_device *pdev, int mode) | 748 | int pwc_set_awb(struct pwc_device *pdev, int mode) |
770 | { | 749 | { |
771 | char buf; | 750 | char buf; |
772 | int ret; | 751 | int ret; |
@@ -786,7 +765,7 @@ static inline int pwc_set_awb(struct pwc_device *pdev, int mode) | |||
786 | return 0; | 765 | return 0; |
787 | } | 766 | } |
788 | 767 | ||
789 | static inline int pwc_get_awb(struct pwc_device *pdev) | 768 | int pwc_get_awb(struct pwc_device *pdev) |
790 | { | 769 | { |
791 | unsigned char buf; | 770 | unsigned char buf; |
792 | int ret; | 771 | int ret; |
@@ -798,7 +777,7 @@ static inline int pwc_get_awb(struct pwc_device *pdev) | |||
798 | return buf; | 777 | return buf; |
799 | } | 778 | } |
800 | 779 | ||
801 | static inline int pwc_set_red_gain(struct pwc_device *pdev, int value) | 780 | int pwc_set_red_gain(struct pwc_device *pdev, int value) |
802 | { | 781 | { |
803 | unsigned char buf; | 782 | unsigned char buf; |
804 | 783 | ||
@@ -811,7 +790,7 @@ static inline int pwc_set_red_gain(struct pwc_device *pdev, int value) | |||
811 | return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); | 790 | return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); |
812 | } | 791 | } |
813 | 792 | ||
814 | static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value) | 793 | int pwc_get_red_gain(struct pwc_device *pdev, int *value) |
815 | { | 794 | { |
816 | unsigned char buf; | 795 | unsigned char buf; |
817 | int ret; | 796 | int ret; |
@@ -824,7 +803,7 @@ static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value) | |||
824 | } | 803 | } |
825 | 804 | ||
826 | 805 | ||
827 | static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value) | 806 | int pwc_set_blue_gain(struct pwc_device *pdev, int value) |
828 | { | 807 | { |
829 | unsigned char buf; | 808 | unsigned char buf; |
830 | 809 | ||
@@ -837,7 +816,7 @@ static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value) | |||
837 | return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); | 816 | return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); |
838 | } | 817 | } |
839 | 818 | ||
840 | static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value) | 819 | int pwc_get_blue_gain(struct pwc_device *pdev, int *value) |
841 | { | 820 | { |
842 | unsigned char buf; | 821 | unsigned char buf; |
843 | int ret; | 822 | int ret; |
@@ -854,7 +833,7 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value) | |||
854 | internal red/blue gains, which may be different from the manual | 833 | internal red/blue gains, which may be different from the manual |
855 | gains set or read above. | 834 | gains set or read above. |
856 | */ | 835 | */ |
857 | static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value) | 836 | static int pwc_read_red_gain(struct pwc_device *pdev, int *value) |
858 | { | 837 | { |
859 | unsigned char buf; | 838 | unsigned char buf; |
860 | int ret; | 839 | int ret; |
@@ -866,7 +845,7 @@ static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value) | |||
866 | return 0; | 845 | return 0; |
867 | } | 846 | } |
868 | 847 | ||
869 | static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value) | 848 | static int pwc_read_blue_gain(struct pwc_device *pdev, int *value) |
870 | { | 849 | { |
871 | unsigned char buf; | 850 | unsigned char buf; |
872 | int ret; | 851 | int ret; |
@@ -879,7 +858,7 @@ static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value) | |||
879 | } | 858 | } |
880 | 859 | ||
881 | 860 | ||
882 | static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed) | 861 | static int pwc_set_wb_speed(struct pwc_device *pdev, int speed) |
883 | { | 862 | { |
884 | unsigned char buf; | 863 | unsigned char buf; |
885 | 864 | ||
@@ -888,7 +867,7 @@ static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed) | |||
888 | return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); | 867 | return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); |
889 | } | 868 | } |
890 | 869 | ||
891 | static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value) | 870 | static int pwc_get_wb_speed(struct pwc_device *pdev, int *value) |
892 | { | 871 | { |
893 | unsigned char buf; | 872 | unsigned char buf; |
894 | int ret; | 873 | int ret; |
@@ -901,7 +880,7 @@ static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value) | |||
901 | } | 880 | } |
902 | 881 | ||
903 | 882 | ||
904 | static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay) | 883 | static int pwc_set_wb_delay(struct pwc_device *pdev, int delay) |
905 | { | 884 | { |
906 | unsigned char buf; | 885 | unsigned char buf; |
907 | 886 | ||
@@ -910,7 +889,7 @@ static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay) | |||
910 | return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); | 889 | return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); |
911 | } | 890 | } |
912 | 891 | ||
913 | static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value) | 892 | static int pwc_get_wb_delay(struct pwc_device *pdev, int *value) |
914 | { | 893 | { |
915 | unsigned char buf; | 894 | unsigned char buf; |
916 | int ret; | 895 | int ret; |
@@ -965,7 +944,7 @@ static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) | |||
965 | return 0; | 944 | return 0; |
966 | } | 945 | } |
967 | 946 | ||
968 | static inline int pwc_set_contour(struct pwc_device *pdev, int contour) | 947 | int pwc_set_contour(struct pwc_device *pdev, int contour) |
969 | { | 948 | { |
970 | unsigned char buf; | 949 | unsigned char buf; |
971 | int ret; | 950 | int ret; |
@@ -990,7 +969,7 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour) | |||
990 | return 0; | 969 | return 0; |
991 | } | 970 | } |
992 | 971 | ||
993 | static inline int pwc_get_contour(struct pwc_device *pdev, int *contour) | 972 | int pwc_get_contour(struct pwc_device *pdev, int *contour) |
994 | { | 973 | { |
995 | unsigned char buf; | 974 | unsigned char buf; |
996 | int ret; | 975 | int ret; |
@@ -1012,7 +991,7 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour) | |||
1012 | } | 991 | } |
1013 | 992 | ||
1014 | 993 | ||
1015 | static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight) | 994 | int pwc_set_backlight(struct pwc_device *pdev, int backlight) |
1016 | { | 995 | { |
1017 | unsigned char buf; | 996 | unsigned char buf; |
1018 | 997 | ||
@@ -1023,7 +1002,7 @@ static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight) | |||
1023 | return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); | 1002 | return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); |
1024 | } | 1003 | } |
1025 | 1004 | ||
1026 | static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight) | 1005 | int pwc_get_backlight(struct pwc_device *pdev, int *backlight) |
1027 | { | 1006 | { |
1028 | int ret; | 1007 | int ret; |
1029 | unsigned char buf; | 1008 | unsigned char buf; |
@@ -1031,12 +1010,35 @@ static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight) | |||
1031 | ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); | 1010 | ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); |
1032 | if (ret < 0) | 1011 | if (ret < 0) |
1033 | return ret; | 1012 | return ret; |
1034 | *backlight = buf; | 1013 | *backlight = !!buf; |
1035 | return 0; | 1014 | return 0; |
1036 | } | 1015 | } |
1037 | 1016 | ||
1017 | int pwc_set_colour_mode(struct pwc_device *pdev, int colour) | ||
1018 | { | ||
1019 | unsigned char buf; | ||
1038 | 1020 | ||
1039 | static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker) | 1021 | if (colour) |
1022 | buf = 0xff; | ||
1023 | else | ||
1024 | buf = 0x0; | ||
1025 | return SendControlMsg(SET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1); | ||
1026 | } | ||
1027 | |||
1028 | int pwc_get_colour_mode(struct pwc_device *pdev, int *colour) | ||
1029 | { | ||
1030 | int ret; | ||
1031 | unsigned char buf; | ||
1032 | |||
1033 | ret = RecvControlMsg(GET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1); | ||
1034 | if (ret < 0) | ||
1035 | return ret; | ||
1036 | *colour = !!buf; | ||
1037 | return 0; | ||
1038 | } | ||
1039 | |||
1040 | |||
1041 | int pwc_set_flicker(struct pwc_device *pdev, int flicker) | ||
1040 | { | 1042 | { |
1041 | unsigned char buf; | 1043 | unsigned char buf; |
1042 | 1044 | ||
@@ -1047,7 +1049,7 @@ static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker) | |||
1047 | return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); | 1049 | return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); |
1048 | } | 1050 | } |
1049 | 1051 | ||
1050 | static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker) | 1052 | int pwc_get_flicker(struct pwc_device *pdev, int *flicker) |
1051 | { | 1053 | { |
1052 | int ret; | 1054 | int ret; |
1053 | unsigned char buf; | 1055 | unsigned char buf; |
@@ -1055,12 +1057,11 @@ static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker) | |||
1055 | ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); | 1057 | ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); |
1056 | if (ret < 0) | 1058 | if (ret < 0) |
1057 | return ret; | 1059 | return ret; |
1058 | *flicker = buf; | 1060 | *flicker = !!buf; |
1059 | return 0; | 1061 | return 0; |
1060 | } | 1062 | } |
1061 | 1063 | ||
1062 | 1064 | int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise) | |
1063 | static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise) | ||
1064 | { | 1065 | { |
1065 | unsigned char buf; | 1066 | unsigned char buf; |
1066 | 1067 | ||
@@ -1072,7 +1073,7 @@ static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise) | |||
1072 | return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); | 1073 | return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); |
1073 | } | 1074 | } |
1074 | 1075 | ||
1075 | static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) | 1076 | int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) |
1076 | { | 1077 | { |
1077 | int ret; | 1078 | int ret; |
1078 | unsigned char buf; | 1079 | unsigned char buf; |
@@ -1084,7 +1085,7 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) | |||
1084 | return 0; | 1085 | return 0; |
1085 | } | 1086 | } |
1086 | 1087 | ||
1087 | static int pwc_mpt_reset(struct pwc_device *pdev, int flags) | 1088 | static int _pwc_mpt_reset(struct pwc_device *pdev, int flags) |
1088 | { | 1089 | { |
1089 | unsigned char buf; | 1090 | unsigned char buf; |
1090 | 1091 | ||
@@ -1092,7 +1093,18 @@ static int pwc_mpt_reset(struct pwc_device *pdev, int flags) | |||
1092 | return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1); | 1093 | return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1); |
1093 | } | 1094 | } |
1094 | 1095 | ||
1095 | static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) | 1096 | int pwc_mpt_reset(struct pwc_device *pdev, int flags) |
1097 | { | ||
1098 | int ret; | ||
1099 | ret = _pwc_mpt_reset(pdev, flags); | ||
1100 | if (ret >= 0) { | ||
1101 | pdev->pan_angle = 0; | ||
1102 | pdev->tilt_angle = 0; | ||
1103 | } | ||
1104 | return ret; | ||
1105 | } | ||
1106 | |||
1107 | static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) | ||
1096 | { | 1108 | { |
1097 | unsigned char buf[4]; | 1109 | unsigned char buf[4]; |
1098 | 1110 | ||
@@ -1110,7 +1122,35 @@ static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) | |||
1110 | return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4); | 1122 | return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4); |
1111 | } | 1123 | } |
1112 | 1124 | ||
1113 | static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status) | 1125 | int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) |
1126 | { | ||
1127 | int ret; | ||
1128 | |||
1129 | /* check absolute ranges */ | ||
1130 | if (pan < pdev->angle_range.pan_min || | ||
1131 | pan > pdev->angle_range.pan_max || | ||
1132 | tilt < pdev->angle_range.tilt_min || | ||
1133 | tilt > pdev->angle_range.tilt_max) | ||
1134 | return -ERANGE; | ||
1135 | |||
1136 | /* go to relative range, check again */ | ||
1137 | pan -= pdev->pan_angle; | ||
1138 | tilt -= pdev->tilt_angle; | ||
1139 | /* angles are specified in degrees * 100, thus the limit = 36000 */ | ||
1140 | if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000) | ||
1141 | return -ERANGE; | ||
1142 | |||
1143 | ret = _pwc_mpt_set_angle(pdev, pan, tilt); | ||
1144 | if (ret >= 0) { | ||
1145 | pdev->pan_angle += pan; | ||
1146 | pdev->tilt_angle += tilt; | ||
1147 | } | ||
1148 | if (ret == -EPIPE) /* stall -> out of range */ | ||
1149 | ret = -ERANGE; | ||
1150 | return ret; | ||
1151 | } | ||
1152 | |||
1153 | static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status) | ||
1114 | { | 1154 | { |
1115 | int ret; | 1155 | int ret; |
1116 | unsigned char buf[5]; | 1156 | unsigned char buf[5]; |
@@ -1151,6 +1191,26 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) | |||
1151 | /* End of Add-Ons */ | 1191 | /* End of Add-Ons */ |
1152 | /* ************************************************* */ | 1192 | /* ************************************************* */ |
1153 | 1193 | ||
1194 | /* Linux 2.5.something and 2.6 pass direct pointers to arguments of | ||
1195 | ioctl() calls. With 2.4, you have to do tedious copy_from_user() | ||
1196 | and copy_to_user() calls. With these macros we circumvent this, | ||
1197 | and let me maintain only one source file. The functionality is | ||
1198 | exactly the same otherwise. | ||
1199 | */ | ||
1200 | |||
1201 | |||
1202 | /* define local variable for arg */ | ||
1203 | #define ARG_DEF(ARG_type, ARG_name)\ | ||
1204 | ARG_type *ARG_name = arg; | ||
1205 | /* copy arg to local variable */ | ||
1206 | #define ARG_IN(ARG_name) /* nothing */ | ||
1207 | /* argument itself (referenced) */ | ||
1208 | #define ARGR(ARG_name) (*ARG_name) | ||
1209 | /* argument address */ | ||
1210 | #define ARGA(ARG_name) ARG_name | ||
1211 | /* copy local variable to arg */ | ||
1212 | #define ARG_OUT(ARG_name) /* nothing */ | ||
1213 | |||
1154 | 1214 | ||
1155 | int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) | 1215 | int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) |
1156 | { | 1216 | { |
@@ -1180,206 +1240,243 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) | |||
1180 | 1240 | ||
1181 | case VIDIOCPWCSCQUAL: | 1241 | case VIDIOCPWCSCQUAL: |
1182 | { | 1242 | { |
1183 | int *qual = arg; | 1243 | ARG_DEF(int, qual) |
1184 | 1244 | ||
1185 | if (*qual < 0 || *qual > 3) | 1245 | ARG_IN(qual) |
1246 | if (ARGR(qual) < 0 || ARGR(qual) > 3) | ||
1186 | ret = -EINVAL; | 1247 | ret = -EINVAL; |
1187 | else | 1248 | else |
1188 | ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot); | 1249 | ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot); |
1189 | if (ret >= 0) | 1250 | if (ret >= 0) |
1190 | pdev->vcompression = *qual; | 1251 | pdev->vcompression = ARGR(qual); |
1191 | break; | 1252 | break; |
1192 | } | 1253 | } |
1193 | 1254 | ||
1194 | case VIDIOCPWCGCQUAL: | 1255 | case VIDIOCPWCGCQUAL: |
1195 | { | 1256 | { |
1196 | int *qual = arg; | 1257 | ARG_DEF(int, qual) |
1197 | *qual = pdev->vcompression; | 1258 | |
1259 | ARGR(qual) = pdev->vcompression; | ||
1260 | ARG_OUT(qual) | ||
1198 | break; | 1261 | break; |
1199 | } | 1262 | } |
1200 | 1263 | ||
1201 | case VIDIOCPWCPROBE: | 1264 | case VIDIOCPWCPROBE: |
1202 | { | 1265 | { |
1203 | struct pwc_probe *probe = arg; | 1266 | ARG_DEF(struct pwc_probe, probe) |
1204 | strcpy(probe->name, pdev->vdev->name); | 1267 | |
1205 | probe->type = pdev->type; | 1268 | strcpy(ARGR(probe).name, pdev->vdev->name); |
1269 | ARGR(probe).type = pdev->type; | ||
1270 | ARG_OUT(probe) | ||
1206 | break; | 1271 | break; |
1207 | } | 1272 | } |
1208 | 1273 | ||
1209 | case VIDIOCPWCGSERIAL: | 1274 | case VIDIOCPWCGSERIAL: |
1210 | { | 1275 | { |
1211 | struct pwc_serial *serial = arg; | 1276 | ARG_DEF(struct pwc_serial, serial) |
1212 | strcpy(serial->serial, pdev->serial); | 1277 | |
1278 | strcpy(ARGR(serial).serial, pdev->serial); | ||
1279 | ARG_OUT(serial) | ||
1213 | break; | 1280 | break; |
1214 | } | 1281 | } |
1215 | 1282 | ||
1216 | case VIDIOCPWCSAGC: | 1283 | case VIDIOCPWCSAGC: |
1217 | { | 1284 | { |
1218 | int *agc = arg; | 1285 | ARG_DEF(int, agc) |
1219 | if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc)) | 1286 | |
1287 | ARG_IN(agc) | ||
1288 | if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc))) | ||
1220 | ret = -EINVAL; | 1289 | ret = -EINVAL; |
1221 | break; | 1290 | break; |
1222 | } | 1291 | } |
1223 | 1292 | ||
1224 | case VIDIOCPWCGAGC: | 1293 | case VIDIOCPWCGAGC: |
1225 | { | 1294 | { |
1226 | int *agc = arg; | 1295 | ARG_DEF(int, agc) |
1227 | 1296 | ||
1228 | if (pwc_get_agc(pdev, agc)) | 1297 | if (pwc_get_agc(pdev, ARGA(agc))) |
1229 | ret = -EINVAL; | 1298 | ret = -EINVAL; |
1299 | ARG_OUT(agc) | ||
1230 | break; | 1300 | break; |
1231 | } | 1301 | } |
1232 | 1302 | ||
1233 | case VIDIOCPWCSSHUTTER: | 1303 | case VIDIOCPWCSSHUTTER: |
1234 | { | 1304 | { |
1235 | int *shutter_speed = arg; | 1305 | ARG_DEF(int, shutter_speed) |
1236 | ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed); | 1306 | |
1307 | ARG_IN(shutter_speed) | ||
1308 | ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed)); | ||
1237 | break; | 1309 | break; |
1238 | } | 1310 | } |
1239 | 1311 | ||
1240 | case VIDIOCPWCSAWB: | 1312 | case VIDIOCPWCSAWB: |
1241 | { | 1313 | { |
1242 | struct pwc_whitebalance *wb = arg; | 1314 | ARG_DEF(struct pwc_whitebalance, wb) |
1243 | 1315 | ||
1244 | ret = pwc_set_awb(pdev, wb->mode); | 1316 | ARG_IN(wb) |
1245 | if (ret >= 0 && wb->mode == PWC_WB_MANUAL) { | 1317 | ret = pwc_set_awb(pdev, ARGR(wb).mode); |
1246 | pwc_set_red_gain(pdev, wb->manual_red); | 1318 | if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) { |
1247 | pwc_set_blue_gain(pdev, wb->manual_blue); | 1319 | pwc_set_red_gain(pdev, ARGR(wb).manual_red); |
1320 | pwc_set_blue_gain(pdev, ARGR(wb).manual_blue); | ||
1248 | } | 1321 | } |
1249 | break; | 1322 | break; |
1250 | } | 1323 | } |
1251 | 1324 | ||
1252 | case VIDIOCPWCGAWB: | 1325 | case VIDIOCPWCGAWB: |
1253 | { | 1326 | { |
1254 | struct pwc_whitebalance *wb = arg; | 1327 | ARG_DEF(struct pwc_whitebalance, wb) |
1255 | 1328 | ||
1256 | memset(wb, 0, sizeof(struct pwc_whitebalance)); | 1329 | memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance)); |
1257 | wb->mode = pwc_get_awb(pdev); | 1330 | ARGR(wb).mode = pwc_get_awb(pdev); |
1258 | if (wb->mode < 0) | 1331 | if (ARGR(wb).mode < 0) |
1259 | ret = -EINVAL; | 1332 | ret = -EINVAL; |
1260 | else { | 1333 | else { |
1261 | if (wb->mode == PWC_WB_MANUAL) { | 1334 | if (ARGR(wb).mode == PWC_WB_MANUAL) { |
1262 | ret = pwc_get_red_gain(pdev, &wb->manual_red); | 1335 | ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red); |
1263 | if (ret < 0) | 1336 | if (ret < 0) |
1264 | break; | 1337 | break; |
1265 | ret = pwc_get_blue_gain(pdev, &wb->manual_blue); | 1338 | ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue); |
1266 | if (ret < 0) | 1339 | if (ret < 0) |
1267 | break; | 1340 | break; |
1268 | } | 1341 | } |
1269 | if (wb->mode == PWC_WB_AUTO) { | 1342 | if (ARGR(wb).mode == PWC_WB_AUTO) { |
1270 | ret = pwc_read_red_gain(pdev, &wb->read_red); | 1343 | ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red); |
1271 | if (ret < 0) | 1344 | if (ret < 0) |
1272 | break; | 1345 | break; |
1273 | ret = pwc_read_blue_gain(pdev, &wb->read_blue); | 1346 | ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue); |
1274 | if (ret < 0) | 1347 | if (ret < 0) |
1275 | break; | 1348 | break; |
1276 | } | 1349 | } |
1277 | } | 1350 | } |
1351 | ARG_OUT(wb) | ||
1278 | break; | 1352 | break; |
1279 | } | 1353 | } |
1280 | 1354 | ||
1281 | case VIDIOCPWCSAWBSPEED: | 1355 | case VIDIOCPWCSAWBSPEED: |
1282 | { | 1356 | { |
1283 | struct pwc_wb_speed *wbs = arg; | 1357 | ARG_DEF(struct pwc_wb_speed, wbs) |
1284 | 1358 | ||
1285 | if (wbs->control_speed > 0) { | 1359 | if (ARGR(wbs).control_speed > 0) { |
1286 | ret = pwc_set_wb_speed(pdev, wbs->control_speed); | 1360 | ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed); |
1287 | } | 1361 | } |
1288 | if (wbs->control_delay > 0) { | 1362 | if (ARGR(wbs).control_delay > 0) { |
1289 | ret = pwc_set_wb_delay(pdev, wbs->control_delay); | 1363 | ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay); |
1290 | } | 1364 | } |
1291 | break; | 1365 | break; |
1292 | } | 1366 | } |
1293 | 1367 | ||
1294 | case VIDIOCPWCGAWBSPEED: | 1368 | case VIDIOCPWCGAWBSPEED: |
1295 | { | 1369 | { |
1296 | struct pwc_wb_speed *wbs = arg; | 1370 | ARG_DEF(struct pwc_wb_speed, wbs) |
1297 | 1371 | ||
1298 | ret = pwc_get_wb_speed(pdev, &wbs->control_speed); | 1372 | ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed); |
1299 | if (ret < 0) | 1373 | if (ret < 0) |
1300 | break; | 1374 | break; |
1301 | ret = pwc_get_wb_delay(pdev, &wbs->control_delay); | 1375 | ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay); |
1302 | if (ret < 0) | 1376 | if (ret < 0) |
1303 | break; | 1377 | break; |
1378 | ARG_OUT(wbs) | ||
1304 | break; | 1379 | break; |
1305 | } | 1380 | } |
1306 | 1381 | ||
1307 | case VIDIOCPWCSLED: | 1382 | case VIDIOCPWCSLED: |
1308 | { | 1383 | { |
1309 | struct pwc_leds *leds = arg; | 1384 | ARG_DEF(struct pwc_leds, leds) |
1310 | ret = pwc_set_leds(pdev, leds->led_on, leds->led_off); | 1385 | |
1311 | break; | 1386 | ARG_IN(leds) |
1387 | ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off); | ||
1388 | break; | ||
1312 | } | 1389 | } |
1313 | 1390 | ||
1314 | 1391 | ||
1315 | case VIDIOCPWCGLED: | 1392 | case VIDIOCPWCGLED: |
1316 | { | 1393 | { |
1317 | struct pwc_leds *leds = arg; | 1394 | ARG_DEF(struct pwc_leds, leds) |
1318 | ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off); | 1395 | |
1396 | ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off); | ||
1397 | ARG_OUT(leds) | ||
1319 | break; | 1398 | break; |
1320 | } | 1399 | } |
1321 | 1400 | ||
1322 | case VIDIOCPWCSCONTOUR: | 1401 | case VIDIOCPWCSCONTOUR: |
1323 | { | 1402 | { |
1324 | int *contour = arg; | 1403 | ARG_DEF(int, contour) |
1325 | ret = pwc_set_contour(pdev, *contour); | 1404 | |
1405 | ARG_IN(contour) | ||
1406 | ret = pwc_set_contour(pdev, ARGR(contour)); | ||
1326 | break; | 1407 | break; |
1327 | } | 1408 | } |
1328 | 1409 | ||
1329 | case VIDIOCPWCGCONTOUR: | 1410 | case VIDIOCPWCGCONTOUR: |
1330 | { | 1411 | { |
1331 | int *contour = arg; | 1412 | ARG_DEF(int, contour) |
1332 | ret = pwc_get_contour(pdev, contour); | 1413 | |
1414 | ret = pwc_get_contour(pdev, ARGA(contour)); | ||
1415 | ARG_OUT(contour) | ||
1333 | break; | 1416 | break; |
1334 | } | 1417 | } |
1335 | 1418 | ||
1336 | case VIDIOCPWCSBACKLIGHT: | 1419 | case VIDIOCPWCSBACKLIGHT: |
1337 | { | 1420 | { |
1338 | int *backlight = arg; | 1421 | ARG_DEF(int, backlight) |
1339 | ret = pwc_set_backlight(pdev, *backlight); | 1422 | |
1423 | ARG_IN(backlight) | ||
1424 | ret = pwc_set_backlight(pdev, ARGR(backlight)); | ||
1340 | break; | 1425 | break; |
1341 | } | 1426 | } |
1342 | 1427 | ||
1343 | case VIDIOCPWCGBACKLIGHT: | 1428 | case VIDIOCPWCGBACKLIGHT: |
1344 | { | 1429 | { |
1345 | int *backlight = arg; | 1430 | ARG_DEF(int, backlight) |
1346 | ret = pwc_get_backlight(pdev, backlight); | 1431 | |
1432 | ret = pwc_get_backlight(pdev, ARGA(backlight)); | ||
1433 | ARG_OUT(backlight) | ||
1347 | break; | 1434 | break; |
1348 | } | 1435 | } |
1349 | 1436 | ||
1350 | case VIDIOCPWCSFLICKER: | 1437 | case VIDIOCPWCSFLICKER: |
1351 | { | 1438 | { |
1352 | int *flicker = arg; | 1439 | ARG_DEF(int, flicker) |
1353 | ret = pwc_set_flicker(pdev, *flicker); | 1440 | |
1441 | ARG_IN(flicker) | ||
1442 | ret = pwc_set_flicker(pdev, ARGR(flicker)); | ||
1354 | break; | 1443 | break; |
1355 | } | 1444 | } |
1356 | 1445 | ||
1357 | case VIDIOCPWCGFLICKER: | 1446 | case VIDIOCPWCGFLICKER: |
1358 | { | 1447 | { |
1359 | int *flicker = arg; | 1448 | ARG_DEF(int, flicker) |
1360 | ret = pwc_get_flicker(pdev, flicker); | 1449 | |
1450 | ret = pwc_get_flicker(pdev, ARGA(flicker)); | ||
1451 | ARG_OUT(flicker) | ||
1361 | break; | 1452 | break; |
1362 | } | 1453 | } |
1363 | 1454 | ||
1364 | case VIDIOCPWCSDYNNOISE: | 1455 | case VIDIOCPWCSDYNNOISE: |
1365 | { | 1456 | { |
1366 | int *dynnoise = arg; | 1457 | ARG_DEF(int, dynnoise) |
1367 | ret = pwc_set_dynamic_noise(pdev, *dynnoise); | 1458 | |
1459 | ARG_IN(dynnoise) | ||
1460 | ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise)); | ||
1368 | break; | 1461 | break; |
1369 | } | 1462 | } |
1370 | 1463 | ||
1371 | case VIDIOCPWCGDYNNOISE: | 1464 | case VIDIOCPWCGDYNNOISE: |
1372 | { | 1465 | { |
1373 | int *dynnoise = arg; | 1466 | ARG_DEF(int, dynnoise) |
1374 | ret = pwc_get_dynamic_noise(pdev, dynnoise); | 1467 | |
1468 | ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise)); | ||
1469 | ARG_OUT(dynnoise); | ||
1375 | break; | 1470 | break; |
1376 | } | 1471 | } |
1377 | 1472 | ||
1378 | case VIDIOCPWCGREALSIZE: | 1473 | case VIDIOCPWCGREALSIZE: |
1379 | { | 1474 | { |
1380 | struct pwc_imagesize *size = arg; | 1475 | ARG_DEF(struct pwc_imagesize, size) |
1381 | size->width = pdev->image.x; | 1476 | |
1382 | size->height = pdev->image.y; | 1477 | ARGR(size).width = pdev->image.x; |
1478 | ARGR(size).height = pdev->image.y; | ||
1479 | ARG_OUT(size) | ||
1383 | break; | 1480 | break; |
1384 | } | 1481 | } |
1385 | 1482 | ||
@@ -1387,14 +1484,10 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) | |||
1387 | { | 1484 | { |
1388 | if (pdev->features & FEATURE_MOTOR_PANTILT) | 1485 | if (pdev->features & FEATURE_MOTOR_PANTILT) |
1389 | { | 1486 | { |
1390 | int *flags = arg; | 1487 | ARG_DEF(int, flags) |
1391 | 1488 | ||
1392 | ret = pwc_mpt_reset(pdev, *flags); | 1489 | ARG_IN(flags) |
1393 | if (ret >= 0) | 1490 | ret = pwc_mpt_reset(pdev, ARGR(flags)); |
1394 | { | ||
1395 | pdev->pan_angle = 0; | ||
1396 | pdev->tilt_angle = 0; | ||
1397 | } | ||
1398 | } | 1491 | } |
1399 | else | 1492 | else |
1400 | { | 1493 | { |
@@ -1407,8 +1500,10 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) | |||
1407 | { | 1500 | { |
1408 | if (pdev->features & FEATURE_MOTOR_PANTILT) | 1501 | if (pdev->features & FEATURE_MOTOR_PANTILT) |
1409 | { | 1502 | { |
1410 | struct pwc_mpt_range *range = arg; | 1503 | ARG_DEF(struct pwc_mpt_range, range) |
1411 | *range = pdev->angle_range; | 1504 | |
1505 | ARGR(range) = pdev->angle_range; | ||
1506 | ARG_OUT(range) | ||
1412 | } | 1507 | } |
1413 | else | 1508 | else |
1414 | { | 1509 | { |
@@ -1423,48 +1518,23 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) | |||
1423 | 1518 | ||
1424 | if (pdev->features & FEATURE_MOTOR_PANTILT) | 1519 | if (pdev->features & FEATURE_MOTOR_PANTILT) |
1425 | { | 1520 | { |
1426 | struct pwc_mpt_angles *angles = arg; | 1521 | ARG_DEF(struct pwc_mpt_angles, angles) |
1522 | |||
1523 | ARG_IN(angles) | ||
1427 | /* The camera can only set relative angles, so | 1524 | /* The camera can only set relative angles, so |
1428 | do some calculations when getting an absolute angle . | 1525 | do some calculations when getting an absolute angle . |
1429 | */ | 1526 | */ |
1430 | if (angles->absolute) | 1527 | if (ARGR(angles).absolute) |
1431 | { | 1528 | { |
1432 | new_pan = angles->pan; | 1529 | new_pan = ARGR(angles).pan; |
1433 | new_tilt = angles->tilt; | 1530 | new_tilt = ARGR(angles).tilt; |
1434 | } | 1531 | } |
1435 | else | 1532 | else |
1436 | { | 1533 | { |
1437 | new_pan = pdev->pan_angle + angles->pan; | 1534 | new_pan = pdev->pan_angle + ARGR(angles).pan; |
1438 | new_tilt = pdev->tilt_angle + angles->tilt; | 1535 | new_tilt = pdev->tilt_angle + ARGR(angles).tilt; |
1439 | } | ||
1440 | /* check absolute ranges */ | ||
1441 | if (new_pan < pdev->angle_range.pan_min || | ||
1442 | new_pan > pdev->angle_range.pan_max || | ||
1443 | new_tilt < pdev->angle_range.tilt_min || | ||
1444 | new_tilt > pdev->angle_range.tilt_max) | ||
1445 | { | ||
1446 | ret = -ERANGE; | ||
1447 | } | ||
1448 | else | ||
1449 | { | ||
1450 | /* go to relative range, check again */ | ||
1451 | new_pan -= pdev->pan_angle; | ||
1452 | new_tilt -= pdev->tilt_angle; | ||
1453 | /* angles are specified in degrees * 100, thus the limit = 36000 */ | ||
1454 | if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000) | ||
1455 | ret = -ERANGE; | ||
1456 | } | ||
1457 | if (ret == 0) /* no errors so far */ | ||
1458 | { | ||
1459 | ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt); | ||
1460 | if (ret >= 0) | ||
1461 | { | ||
1462 | pdev->pan_angle += new_pan; | ||
1463 | pdev->tilt_angle += new_tilt; | ||
1464 | } | ||
1465 | if (ret == -EPIPE) /* stall -> out of range */ | ||
1466 | ret = -ERANGE; | ||
1467 | } | 1536 | } |
1537 | ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt); | ||
1468 | } | 1538 | } |
1469 | else | 1539 | else |
1470 | { | 1540 | { |
@@ -1478,11 +1548,12 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) | |||
1478 | 1548 | ||
1479 | if (pdev->features & FEATURE_MOTOR_PANTILT) | 1549 | if (pdev->features & FEATURE_MOTOR_PANTILT) |
1480 | { | 1550 | { |
1481 | struct pwc_mpt_angles *angles = arg; | 1551 | ARG_DEF(struct pwc_mpt_angles, angles) |
1482 | 1552 | ||
1483 | angles->absolute = 1; | 1553 | ARGR(angles).absolute = 1; |
1484 | angles->pan = pdev->pan_angle; | 1554 | ARGR(angles).pan = pdev->pan_angle; |
1485 | angles->tilt = pdev->tilt_angle; | 1555 | ARGR(angles).tilt = pdev->tilt_angle; |
1556 | ARG_OUT(angles) | ||
1486 | } | 1557 | } |
1487 | else | 1558 | else |
1488 | { | 1559 | { |
@@ -1495,8 +1566,10 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) | |||
1495 | { | 1566 | { |
1496 | if (pdev->features & FEATURE_MOTOR_PANTILT) | 1567 | if (pdev->features & FEATURE_MOTOR_PANTILT) |
1497 | { | 1568 | { |
1498 | struct pwc_mpt_status *status = arg; | 1569 | ARG_DEF(struct pwc_mpt_status, status) |
1499 | ret = pwc_mpt_get_status(pdev, status); | 1570 | |
1571 | ret = pwc_mpt_get_status(pdev, ARGA(status)); | ||
1572 | ARG_OUT(status) | ||
1500 | } | 1573 | } |
1501 | else | 1574 | else |
1502 | { | 1575 | { |
@@ -1507,22 +1580,24 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) | |||
1507 | 1580 | ||
1508 | case VIDIOCPWCGVIDCMD: | 1581 | case VIDIOCPWCGVIDCMD: |
1509 | { | 1582 | { |
1510 | struct pwc_video_command *cmd = arg; | 1583 | ARG_DEF(struct pwc_video_command, cmd); |
1511 | 1584 | ||
1512 | cmd->type = pdev->type; | 1585 | ARGR(cmd).type = pdev->type; |
1513 | cmd->release = pdev->release; | 1586 | ARGR(cmd).release = pdev->release; |
1514 | cmd->command_len = pdev->cmd_len; | 1587 | ARGR(cmd).command_len = pdev->cmd_len; |
1515 | memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len); | 1588 | memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len); |
1516 | cmd->bandlength = pdev->vbandlength; | 1589 | ARGR(cmd).bandlength = pdev->vbandlength; |
1517 | cmd->frame_size = pdev->frame_size; | 1590 | ARGR(cmd).frame_size = pdev->frame_size; |
1591 | ARG_OUT(cmd) | ||
1518 | break; | 1592 | break; |
1519 | } | 1593 | } |
1520 | /* | 1594 | /* |
1521 | case VIDIOCPWCGVIDTABLE: | 1595 | case VIDIOCPWCGVIDTABLE: |
1522 | { | 1596 | { |
1523 | struct pwc_table_init_buffer *table = arg; | 1597 | ARG_DEF(struct pwc_table_init_buffer, table); |
1524 | table->len = pdev->cmd_len; | 1598 | ARGR(table).len = pdev->cmd_len; |
1525 | memcpy(&table->buffer, pdev->decompress_data, pdev->decompressor->table_size); | 1599 | memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size); |
1600 | ARG_OUT(table) | ||
1526 | break; | 1601 | break; |
1527 | } | 1602 | } |
1528 | */ | 1603 | */ |
@@ -1538,4 +1613,4 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) | |||
1538 | } | 1613 | } |
1539 | 1614 | ||
1540 | 1615 | ||
1541 | 1616 | /* vim: set cinoptions= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | |
diff --git a/drivers/media/video/pwc/pwc-dec1.c b/drivers/media/video/pwc/pwc-dec1.c new file mode 100644 index 000000000000..c29593f589eb --- /dev/null +++ b/drivers/media/video/pwc/pwc-dec1.c | |||
@@ -0,0 +1,50 @@ | |||
1 | /* Linux driver for Philips webcam | ||
2 | Decompression for chipset version 1 | ||
3 | (C) 2004-2006 Luc Saillard (luc@saillard.org) | ||
4 | |||
5 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | ||
6 | driver and thus may have bugs that are not present in the original version. | ||
7 | Please send bug reports and support requests to <luc@saillard.org>. | ||
8 | The decompression routines have been implemented by reverse-engineering the | ||
9 | Nemosoft binary pwcx module. Caveat emptor. | ||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | */ | ||
25 | |||
26 | |||
27 | |||
28 | #include "pwc-dec1.h" | ||
29 | |||
30 | |||
31 | void pwc_dec1_init(int type, int release, void *buffer, void *table) | ||
32 | { | ||
33 | |||
34 | } | ||
35 | |||
36 | void pwc_dec1_exit(void) | ||
37 | { | ||
38 | |||
39 | |||
40 | |||
41 | } | ||
42 | |||
43 | int pwc_dec1_alloc(struct pwc_device *pwc) | ||
44 | { | ||
45 | pwc->decompress_data = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL); | ||
46 | if (pwc->decompress_data == NULL) | ||
47 | return -ENOMEM; | ||
48 | return 0; | ||
49 | } | ||
50 | |||
diff --git a/drivers/media/video/pwc/pwc-dec1.h b/drivers/media/video/pwc/pwc-dec1.h new file mode 100644 index 000000000000..8b62ddcc5c7e --- /dev/null +++ b/drivers/media/video/pwc/pwc-dec1.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* Linux driver for Philips webcam | ||
2 | (C) 2004-2006 Luc Saillard (luc@saillard.org) | ||
3 | |||
4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | ||
5 | driver and thus may have bugs that are not present in the original version. | ||
6 | Please send bug reports and support requests to <luc@saillard.org>. | ||
7 | The decompression routines have been implemented by reverse-engineering the | ||
8 | Nemosoft binary pwcx module. Caveat emptor. | ||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | |||
26 | |||
27 | #ifndef PWC_DEC1_H | ||
28 | #define PWC_DEC1_H | ||
29 | |||
30 | #include "pwc.h" | ||
31 | |||
32 | struct pwc_dec1_private | ||
33 | { | ||
34 | int version; | ||
35 | |||
36 | }; | ||
37 | |||
38 | int pwc_dec1_alloc(struct pwc_device *pwc); | ||
39 | void pwc_dec1_init(int type, int release, void *buffer, void *private_data); | ||
40 | void pwc_dec1_exit(void); | ||
41 | |||
42 | #endif | ||
43 | |||
diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c new file mode 100644 index 000000000000..9e2d91f26bfe --- /dev/null +++ b/drivers/media/video/pwc/pwc-dec23.c | |||
@@ -0,0 +1,941 @@ | |||
1 | /* Linux driver for Philips webcam | ||
2 | Decompression for chipset version 2 et 3 | ||
3 | (C) 2004-2006 Luc Saillard (luc@saillard.org) | ||
4 | |||
5 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | ||
6 | driver and thus may have bugs that are not present in the original version. | ||
7 | Please send bug reports and support requests to <luc@saillard.org>. | ||
8 | The decompression routines have been implemented by reverse-engineering the | ||
9 | Nemosoft binary pwcx module. Caveat emptor. | ||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | |||
25 | */ | ||
26 | |||
27 | #include "pwc-timon.h" | ||
28 | #include "pwc-kiara.h" | ||
29 | #include "pwc-dec23.h" | ||
30 | #include <media/pwc-ioctl.h> | ||
31 | |||
32 | #include <linux/string.h> | ||
33 | |||
34 | /* | ||
35 | * USE_LOOKUP_TABLE_TO_CLAMP | ||
36 | * 0: use a C version of this tests: { a<0?0:(a>255?255:a) } | ||
37 | * 1: use a faster lookup table for cpu with a big cache (intel) | ||
38 | */ | ||
39 | #define USE_LOOKUP_TABLE_TO_CLAMP 1 | ||
40 | /* | ||
41 | * UNROLL_LOOP_FOR_COPYING_BLOCK | ||
42 | * 0: use a loop for a smaller code (but little slower) | ||
43 | * 1: when unrolling the loop, gcc produces some faster code (perhaps only | ||
44 | * valid for intel processor class). Activating this option, automaticaly | ||
45 | * activate USE_LOOKUP_TABLE_TO_CLAMP | ||
46 | */ | ||
47 | #define UNROLL_LOOP_FOR_COPY 1 | ||
48 | #if UNROLL_LOOP_FOR_COPY | ||
49 | # undef USE_LOOKUP_TABLE_TO_CLAMP | ||
50 | # define USE_LOOKUP_TABLE_TO_CLAMP 1 | ||
51 | #endif | ||
52 | |||
53 | /* | ||
54 | * ENABLE_BAYER_DECODER | ||
55 | * 0: bayer decoder is not build (save some space) | ||
56 | * 1: bayer decoder is build and can be used | ||
57 | */ | ||
58 | #define ENABLE_BAYER_DECODER 0 | ||
59 | |||
60 | static void build_subblock_pattern(struct pwc_dec23_private *pdec) | ||
61 | { | ||
62 | static const unsigned int initial_values[12] = { | ||
63 | -0x526500, -0x221200, 0x221200, 0x526500, | ||
64 | -0x3de200, 0x3de200, | ||
65 | -0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480, | ||
66 | -0x12c200, 0x12c200 | ||
67 | |||
68 | }; | ||
69 | static const unsigned int values_derivated[12] = { | ||
70 | 0xa4ca, 0x4424, -0x4424, -0xa4ca, | ||
71 | 0x7bc4, -0x7bc4, | ||
72 | 0xdb69, 0x5aba, -0x5aba, -0xdb69, | ||
73 | 0x2584, -0x2584 | ||
74 | }; | ||
75 | unsigned int temp_values[12]; | ||
76 | int i, j; | ||
77 | |||
78 | memcpy(temp_values, initial_values, sizeof(initial_values)); | ||
79 | for (i = 0; i < 256; i++) { | ||
80 | for (j = 0; j < 12; j++) { | ||
81 | pdec->table_subblock[i][j] = temp_values[j]; | ||
82 | temp_values[j] += values_derivated[j]; | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | |||
87 | static void build_bit_powermask_table(struct pwc_dec23_private *pdec) | ||
88 | { | ||
89 | unsigned char *p; | ||
90 | unsigned int bit, byte, mask, val; | ||
91 | unsigned int bitpower = 1; | ||
92 | |||
93 | for (bit = 0; bit < 8; bit++) { | ||
94 | mask = bitpower - 1; | ||
95 | p = pdec->table_bitpowermask[bit]; | ||
96 | for (byte = 0; byte < 256; byte++) { | ||
97 | val = (byte & mask); | ||
98 | if (byte & bitpower) | ||
99 | val = -val; | ||
100 | *p++ = val; | ||
101 | } | ||
102 | bitpower<<=1; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | |||
107 | static void build_table_color(const unsigned int romtable[16][8], | ||
108 | unsigned char p0004[16][1024], | ||
109 | unsigned char p8004[16][256]) | ||
110 | { | ||
111 | int compression_mode, j, k, bit, pw; | ||
112 | unsigned char *p0, *p8; | ||
113 | const unsigned int *r; | ||
114 | |||
115 | /* We have 16 compressions tables */ | ||
116 | for (compression_mode = 0; compression_mode < 16; compression_mode++) { | ||
117 | p0 = p0004[compression_mode]; | ||
118 | p8 = p8004[compression_mode]; | ||
119 | r = romtable[compression_mode]; | ||
120 | |||
121 | for (j = 0; j < 8; j++, r++, p0 += 128) { | ||
122 | |||
123 | for (k = 0; k < 16; k++) { | ||
124 | if (k == 0) | ||
125 | bit = 1; | ||
126 | else if (k >= 1 && k < 3) | ||
127 | bit = (r[0] >> 15) & 7; | ||
128 | else if (k >= 3 && k < 6) | ||
129 | bit = (r[0] >> 12) & 7; | ||
130 | else if (k >= 6 && k < 10) | ||
131 | bit = (r[0] >> 9) & 7; | ||
132 | else if (k >= 10 && k < 13) | ||
133 | bit = (r[0] >> 6) & 7; | ||
134 | else if (k >= 13 && k < 15) | ||
135 | bit = (r[0] >> 3) & 7; | ||
136 | else | ||
137 | bit = (r[0]) & 7; | ||
138 | if (k == 0) | ||
139 | *p8++ = 8; | ||
140 | else | ||
141 | *p8++ = j - bit; | ||
142 | *p8++ = bit; | ||
143 | |||
144 | pw = 1 << bit; | ||
145 | p0[k + 0x00] = (1 * pw) + 0x80; | ||
146 | p0[k + 0x10] = (2 * pw) + 0x80; | ||
147 | p0[k + 0x20] = (3 * pw) + 0x80; | ||
148 | p0[k + 0x30] = (4 * pw) + 0x80; | ||
149 | p0[k + 0x40] = (-1 * pw) + 0x80; | ||
150 | p0[k + 0x50] = (-2 * pw) + 0x80; | ||
151 | p0[k + 0x60] = (-3 * pw) + 0x80; | ||
152 | p0[k + 0x70] = (-4 * pw) + 0x80; | ||
153 | } /* end of for (k=0; k<16; k++, p8++) */ | ||
154 | } /* end of for (j=0; j<8; j++ , table++) */ | ||
155 | } /* end of foreach compression_mode */ | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * | ||
160 | */ | ||
161 | static void fill_table_dc00_d800(struct pwc_dec23_private *pdec) | ||
162 | { | ||
163 | #define SCALEBITS 15 | ||
164 | #define ONE_HALF (1UL << (SCALEBITS - 1)) | ||
165 | int i; | ||
166 | unsigned int offset1 = ONE_HALF; | ||
167 | unsigned int offset2 = 0x0000; | ||
168 | |||
169 | for (i=0; i<256; i++) { | ||
170 | pdec->table_dc00[i] = offset1 & ~(ONE_HALF); | ||
171 | pdec->table_d800[i] = offset2; | ||
172 | |||
173 | offset1 += 0x7bc4; | ||
174 | offset2 += 0x7bc4; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * To decode the stream: | ||
180 | * if look_bits(2) == 0: # op == 2 in the lookup table | ||
181 | * skip_bits(2) | ||
182 | * end of the stream | ||
183 | * elif look_bits(3) == 7: # op == 1 in the lookup table | ||
184 | * skip_bits(3) | ||
185 | * yyyy = get_bits(4) | ||
186 | * xxxx = get_bits(8) | ||
187 | * else: # op == 0 in the lookup table | ||
188 | * skip_bits(x) | ||
189 | * | ||
190 | * For speedup processing, we build a lookup table and we takes the first 6 bits. | ||
191 | * | ||
192 | * struct { | ||
193 | * unsigned char op; // operation to execute | ||
194 | * unsigned char bits; // bits use to perform operation | ||
195 | * unsigned char offset1; // offset to add to access in the table_0004 % 16 | ||
196 | * unsigned char offset2; // offset to add to access in the table_0004 | ||
197 | * } | ||
198 | * | ||
199 | * How to build this table ? | ||
200 | * op == 2 when (i%4)==0 | ||
201 | * op == 1 when (i%8)==7 | ||
202 | * op == 0 otherwise | ||
203 | * | ||
204 | */ | ||
205 | static const unsigned char hash_table_ops[64*4] = { | ||
206 | 0x02, 0x00, 0x00, 0x00, | ||
207 | 0x00, 0x03, 0x01, 0x00, | ||
208 | 0x00, 0x04, 0x01, 0x10, | ||
209 | 0x00, 0x06, 0x01, 0x30, | ||
210 | 0x02, 0x00, 0x00, 0x00, | ||
211 | 0x00, 0x03, 0x01, 0x40, | ||
212 | 0x00, 0x05, 0x01, 0x20, | ||
213 | 0x01, 0x00, 0x00, 0x00, | ||
214 | 0x02, 0x00, 0x00, 0x00, | ||
215 | 0x00, 0x03, 0x01, 0x00, | ||
216 | 0x00, 0x04, 0x01, 0x50, | ||
217 | 0x00, 0x05, 0x02, 0x00, | ||
218 | 0x02, 0x00, 0x00, 0x00, | ||
219 | 0x00, 0x03, 0x01, 0x40, | ||
220 | 0x00, 0x05, 0x03, 0x00, | ||
221 | 0x01, 0x00, 0x00, 0x00, | ||
222 | 0x02, 0x00, 0x00, 0x00, | ||
223 | 0x00, 0x03, 0x01, 0x00, | ||
224 | 0x00, 0x04, 0x01, 0x10, | ||
225 | 0x00, 0x06, 0x02, 0x10, | ||
226 | 0x02, 0x00, 0x00, 0x00, | ||
227 | 0x00, 0x03, 0x01, 0x40, | ||
228 | 0x00, 0x05, 0x01, 0x60, | ||
229 | 0x01, 0x00, 0x00, 0x00, | ||
230 | 0x02, 0x00, 0x00, 0x00, | ||
231 | 0x00, 0x03, 0x01, 0x00, | ||
232 | 0x00, 0x04, 0x01, 0x50, | ||
233 | 0x00, 0x05, 0x02, 0x40, | ||
234 | 0x02, 0x00, 0x00, 0x00, | ||
235 | 0x00, 0x03, 0x01, 0x40, | ||
236 | 0x00, 0x05, 0x03, 0x40, | ||
237 | 0x01, 0x00, 0x00, 0x00, | ||
238 | 0x02, 0x00, 0x00, 0x00, | ||
239 | 0x00, 0x03, 0x01, 0x00, | ||
240 | 0x00, 0x04, 0x01, 0x10, | ||
241 | 0x00, 0x06, 0x01, 0x70, | ||
242 | 0x02, 0x00, 0x00, 0x00, | ||
243 | 0x00, 0x03, 0x01, 0x40, | ||
244 | 0x00, 0x05, 0x01, 0x20, | ||
245 | 0x01, 0x00, 0x00, 0x00, | ||
246 | 0x02, 0x00, 0x00, 0x00, | ||
247 | 0x00, 0x03, 0x01, 0x00, | ||
248 | 0x00, 0x04, 0x01, 0x50, | ||
249 | 0x00, 0x05, 0x02, 0x00, | ||
250 | 0x02, 0x00, 0x00, 0x00, | ||
251 | 0x00, 0x03, 0x01, 0x40, | ||
252 | 0x00, 0x05, 0x03, 0x00, | ||
253 | 0x01, 0x00, 0x00, 0x00, | ||
254 | 0x02, 0x00, 0x00, 0x00, | ||
255 | 0x00, 0x03, 0x01, 0x00, | ||
256 | 0x00, 0x04, 0x01, 0x10, | ||
257 | 0x00, 0x06, 0x02, 0x50, | ||
258 | 0x02, 0x00, 0x00, 0x00, | ||
259 | 0x00, 0x03, 0x01, 0x40, | ||
260 | 0x00, 0x05, 0x01, 0x60, | ||
261 | 0x01, 0x00, 0x00, 0x00, | ||
262 | 0x02, 0x00, 0x00, 0x00, | ||
263 | 0x00, 0x03, 0x01, 0x00, | ||
264 | 0x00, 0x04, 0x01, 0x50, | ||
265 | 0x00, 0x05, 0x02, 0x40, | ||
266 | 0x02, 0x00, 0x00, 0x00, | ||
267 | 0x00, 0x03, 0x01, 0x40, | ||
268 | 0x00, 0x05, 0x03, 0x40, | ||
269 | 0x01, 0x00, 0x00, 0x00 | ||
270 | }; | ||
271 | |||
272 | /* | ||
273 | * | ||
274 | */ | ||
275 | static const unsigned int MulIdx[16][16] = { | ||
276 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, | ||
277 | {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,}, | ||
278 | {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,}, | ||
279 | {4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,}, | ||
280 | {6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,}, | ||
281 | {4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,}, | ||
282 | {1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,}, | ||
283 | {0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,}, | ||
284 | {0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,}, | ||
285 | {1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,}, | ||
286 | {7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,}, | ||
287 | {4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,}, | ||
288 | {7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,}, | ||
289 | {1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,}, | ||
290 | {1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,}, | ||
291 | {10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10} | ||
292 | }; | ||
293 | |||
294 | #if USE_LOOKUP_TABLE_TO_CLAMP | ||
295 | #define MAX_OUTER_CROP_VALUE (512) | ||
296 | static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE]; | ||
297 | #define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)]) | ||
298 | #else | ||
299 | #define CLAMP(x) ((x)>255?255:((x)<0?0:x)) | ||
300 | #endif | ||
301 | |||
302 | |||
303 | /* If the type or the command change, we rebuild the lookup table */ | ||
304 | int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd) | ||
305 | { | ||
306 | int flags, version, shift, i; | ||
307 | struct pwc_dec23_private *pdec; | ||
308 | |||
309 | if (pwc->decompress_data == NULL) { | ||
310 | pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); | ||
311 | if (pdec == NULL) | ||
312 | return -ENOMEM; | ||
313 | pwc->decompress_data = pdec; | ||
314 | } | ||
315 | pdec = pwc->decompress_data; | ||
316 | |||
317 | if (DEVICE_USE_CODEC3(type)) { | ||
318 | flags = cmd[2] & 0x18; | ||
319 | if (flags == 8) | ||
320 | pdec->nbits = 7; /* More bits, mean more bits to encode the stream, but better quality */ | ||
321 | else if (flags == 0x10) | ||
322 | pdec->nbits = 8; | ||
323 | else | ||
324 | pdec->nbits = 6; | ||
325 | |||
326 | version = cmd[2] >> 5; | ||
327 | build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1); | ||
328 | build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2); | ||
329 | |||
330 | } else { | ||
331 | |||
332 | flags = cmd[2] & 6; | ||
333 | if (flags == 2) | ||
334 | pdec->nbits = 7; | ||
335 | else if (flags == 4) | ||
336 | pdec->nbits = 8; | ||
337 | else | ||
338 | pdec->nbits = 6; | ||
339 | |||
340 | version = cmd[2] >> 3; | ||
341 | build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1); | ||
342 | build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2); | ||
343 | } | ||
344 | |||
345 | /* Informations can be coded on a variable number of bits but never less than 8 */ | ||
346 | shift = 8 - pdec->nbits; | ||
347 | pdec->scalebits = SCALEBITS - shift; | ||
348 | pdec->nbitsmask = 0xFF >> shift; | ||
349 | |||
350 | fill_table_dc00_d800(pdec); | ||
351 | build_subblock_pattern(pdec); | ||
352 | build_bit_powermask_table(pdec); | ||
353 | |||
354 | #if USE_LOOKUP_TABLE_TO_CLAMP | ||
355 | /* Build the static table to clamp value [0-255] */ | ||
356 | for (i=0;i<MAX_OUTER_CROP_VALUE;i++) | ||
357 | pwc_crop_table[i] = 0; | ||
358 | for (i=0; i<256; i++) | ||
359 | pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i; | ||
360 | for (i=0; i<MAX_OUTER_CROP_VALUE; i++) | ||
361 | pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255; | ||
362 | #endif | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | /* | ||
368 | * Copy the 4x4 image block to Y plane buffer | ||
369 | */ | ||
370 | static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) | ||
371 | { | ||
372 | #if UNROLL_LOOP_FOR_COPY | ||
373 | const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; | ||
374 | const int *c = src; | ||
375 | unsigned char *d = dst; | ||
376 | |||
377 | *d++ = cm[c[0] >> scalebits]; | ||
378 | *d++ = cm[c[1] >> scalebits]; | ||
379 | *d++ = cm[c[2] >> scalebits]; | ||
380 | *d++ = cm[c[3] >> scalebits]; | ||
381 | |||
382 | d = dst + bytes_per_line; | ||
383 | *d++ = cm[c[4] >> scalebits]; | ||
384 | *d++ = cm[c[5] >> scalebits]; | ||
385 | *d++ = cm[c[6] >> scalebits]; | ||
386 | *d++ = cm[c[7] >> scalebits]; | ||
387 | |||
388 | d = dst + bytes_per_line*2; | ||
389 | *d++ = cm[c[8] >> scalebits]; | ||
390 | *d++ = cm[c[9] >> scalebits]; | ||
391 | *d++ = cm[c[10] >> scalebits]; | ||
392 | *d++ = cm[c[11] >> scalebits]; | ||
393 | |||
394 | d = dst + bytes_per_line*3; | ||
395 | *d++ = cm[c[12] >> scalebits]; | ||
396 | *d++ = cm[c[13] >> scalebits]; | ||
397 | *d++ = cm[c[14] >> scalebits]; | ||
398 | *d++ = cm[c[15] >> scalebits]; | ||
399 | #else | ||
400 | int i; | ||
401 | const int *c = src; | ||
402 | unsigned char *d = dst; | ||
403 | for (i = 0; i < 4; i++, c++) | ||
404 | *d++ = CLAMP((*c) >> scalebits); | ||
405 | |||
406 | d = dst + bytes_per_line; | ||
407 | for (i = 0; i < 4; i++, c++) | ||
408 | *d++ = CLAMP((*c) >> scalebits); | ||
409 | |||
410 | d = dst + bytes_per_line*2; | ||
411 | for (i = 0; i < 4; i++, c++) | ||
412 | *d++ = CLAMP((*c) >> scalebits); | ||
413 | |||
414 | d = dst + bytes_per_line*3; | ||
415 | for (i = 0; i < 4; i++, c++) | ||
416 | *d++ = CLAMP((*c) >> scalebits); | ||
417 | #endif | ||
418 | } | ||
419 | |||
420 | /* | ||
421 | * Copy the 4x4 image block to a CrCb plane buffer | ||
422 | * | ||
423 | */ | ||
424 | static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) | ||
425 | { | ||
426 | #if UNROLL_LOOP_FOR_COPY | ||
427 | /* Unroll all loops */ | ||
428 | const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; | ||
429 | const int *c = src; | ||
430 | unsigned char *d = dst; | ||
431 | |||
432 | *d++ = cm[c[0] >> scalebits]; | ||
433 | *d++ = cm[c[4] >> scalebits]; | ||
434 | *d++ = cm[c[1] >> scalebits]; | ||
435 | *d++ = cm[c[5] >> scalebits]; | ||
436 | *d++ = cm[c[2] >> scalebits]; | ||
437 | *d++ = cm[c[6] >> scalebits]; | ||
438 | *d++ = cm[c[3] >> scalebits]; | ||
439 | *d++ = cm[c[7] >> scalebits]; | ||
440 | |||
441 | d = dst + bytes_per_line; | ||
442 | *d++ = cm[c[12] >> scalebits]; | ||
443 | *d++ = cm[c[8] >> scalebits]; | ||
444 | *d++ = cm[c[13] >> scalebits]; | ||
445 | *d++ = cm[c[9] >> scalebits]; | ||
446 | *d++ = cm[c[14] >> scalebits]; | ||
447 | *d++ = cm[c[10] >> scalebits]; | ||
448 | *d++ = cm[c[15] >> scalebits]; | ||
449 | *d++ = cm[c[11] >> scalebits]; | ||
450 | #else | ||
451 | int i; | ||
452 | const int *c1 = src; | ||
453 | const int *c2 = src + 4; | ||
454 | unsigned char *d = dst; | ||
455 | |||
456 | for (i = 0; i < 4; i++, c1++, c2++) { | ||
457 | *d++ = CLAMP((*c1) >> scalebits); | ||
458 | *d++ = CLAMP((*c2) >> scalebits); | ||
459 | } | ||
460 | c1 = src + 12; | ||
461 | d = dst + bytes_per_line; | ||
462 | for (i = 0; i < 4; i++, c1++, c2++) { | ||
463 | *d++ = CLAMP((*c1) >> scalebits); | ||
464 | *d++ = CLAMP((*c2) >> scalebits); | ||
465 | } | ||
466 | #endif | ||
467 | } | ||
468 | |||
469 | #if ENABLE_BAYER_DECODER | ||
470 | /* | ||
471 | * Format: 8x2 pixels | ||
472 | * . G . G . G . G . G . G . G | ||
473 | * . . . . . . . . . . . . . . | ||
474 | * . G . G . G . G . G . G . G | ||
475 | * . . . . . . . . . . . . . . | ||
476 | * or | ||
477 | * . . . . . . . . . . . . . . | ||
478 | * G . G . G . G . G . G . G . | ||
479 | * . . . . . . . . . . . . . . | ||
480 | * G . G . G . G . G . G . G . | ||
481 | */ | ||
482 | static void copy_image_block_Green(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) | ||
483 | { | ||
484 | #if UNROLL_LOOP_FOR_COPY | ||
485 | /* Unroll all loops */ | ||
486 | const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; | ||
487 | unsigned char *d = dst; | ||
488 | const int *c = src; | ||
489 | |||
490 | d[0] = cm[c[0] >> scalebits]; | ||
491 | d[2] = cm[c[1] >> scalebits]; | ||
492 | d[4] = cm[c[2] >> scalebits]; | ||
493 | d[6] = cm[c[3] >> scalebits]; | ||
494 | d[8] = cm[c[4] >> scalebits]; | ||
495 | d[10] = cm[c[5] >> scalebits]; | ||
496 | d[12] = cm[c[6] >> scalebits]; | ||
497 | d[14] = cm[c[7] >> scalebits]; | ||
498 | |||
499 | d = dst + bytes_per_line; | ||
500 | d[0] = cm[c[8] >> scalebits]; | ||
501 | d[2] = cm[c[9] >> scalebits]; | ||
502 | d[4] = cm[c[10] >> scalebits]; | ||
503 | d[6] = cm[c[11] >> scalebits]; | ||
504 | d[8] = cm[c[12] >> scalebits]; | ||
505 | d[10] = cm[c[13] >> scalebits]; | ||
506 | d[12] = cm[c[14] >> scalebits]; | ||
507 | d[14] = cm[c[15] >> scalebits]; | ||
508 | #else | ||
509 | int i; | ||
510 | unsigned char *d; | ||
511 | const int *c = src; | ||
512 | |||
513 | d = dst; | ||
514 | for (i = 0; i < 8; i++, c++) | ||
515 | d[i*2] = CLAMP((*c) >> scalebits); | ||
516 | |||
517 | d = dst + bytes_per_line; | ||
518 | for (i = 0; i < 8; i++, c++) | ||
519 | d[i*2] = CLAMP((*c) >> scalebits); | ||
520 | #endif | ||
521 | } | ||
522 | #endif | ||
523 | |||
524 | #if ENABLE_BAYER_DECODER | ||
525 | /* | ||
526 | * Format: 4x4 pixels | ||
527 | * R . R . R . R | ||
528 | * . B . B . B . | ||
529 | * R . R . R . R | ||
530 | * . B . B . B . | ||
531 | */ | ||
532 | static void copy_image_block_RedBlue(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) | ||
533 | { | ||
534 | #if UNROLL_LOOP_FOR_COPY | ||
535 | /* Unroll all loops */ | ||
536 | const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; | ||
537 | unsigned char *d = dst; | ||
538 | const int *c = src; | ||
539 | |||
540 | d[0] = cm[c[0] >> scalebits]; | ||
541 | d[2] = cm[c[1] >> scalebits]; | ||
542 | d[4] = cm[c[2] >> scalebits]; | ||
543 | d[6] = cm[c[3] >> scalebits]; | ||
544 | |||
545 | d = dst + bytes_per_line; | ||
546 | d[1] = cm[c[4] >> scalebits]; | ||
547 | d[3] = cm[c[5] >> scalebits]; | ||
548 | d[5] = cm[c[6] >> scalebits]; | ||
549 | d[7] = cm[c[7] >> scalebits]; | ||
550 | |||
551 | d = dst + bytes_per_line*2; | ||
552 | d[0] = cm[c[8] >> scalebits]; | ||
553 | d[2] = cm[c[9] >> scalebits]; | ||
554 | d[4] = cm[c[10] >> scalebits]; | ||
555 | d[6] = cm[c[11] >> scalebits]; | ||
556 | |||
557 | d = dst + bytes_per_line*3; | ||
558 | d[1] = cm[c[12] >> scalebits]; | ||
559 | d[3] = cm[c[13] >> scalebits]; | ||
560 | d[5] = cm[c[14] >> scalebits]; | ||
561 | d[7] = cm[c[15] >> scalebits]; | ||
562 | #else | ||
563 | int i; | ||
564 | unsigned char *d; | ||
565 | const int *c = src; | ||
566 | |||
567 | d = dst; | ||
568 | for (i = 0; i < 4; i++, c++) | ||
569 | d[i*2] = CLAMP((*c) >> scalebits); | ||
570 | |||
571 | d = dst + bytes_per_line; | ||
572 | for (i = 0; i < 4; i++, c++) | ||
573 | d[i*2+1] = CLAMP((*c) >> scalebits); | ||
574 | |||
575 | d = dst + bytes_per_line*2; | ||
576 | for (i = 0; i < 4; i++, c++) | ||
577 | d[i*2] = CLAMP((*c) >> scalebits); | ||
578 | |||
579 | d = dst + bytes_per_line*3; | ||
580 | for (i = 0; i < 4; i++, c++) | ||
581 | d[i*2+1] = CLAMP((*c) >> scalebits); | ||
582 | #endif | ||
583 | } | ||
584 | #endif | ||
585 | |||
586 | /* | ||
587 | * To manage the stream, we keep bits in a 32 bits register. | ||
588 | * fill_nbits(n): fill the reservoir with at least n bits | ||
589 | * skip_bits(n): discard n bits from the reservoir | ||
590 | * get_bits(n): fill the reservoir, returns the first n bits and discard the | ||
591 | * bits from the reservoir. | ||
592 | * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir | ||
593 | * contains at least n bits. bits returned is discarded. | ||
594 | */ | ||
595 | #define fill_nbits(pdec, nbits_wanted) do { \ | ||
596 | while (pdec->nbits_in_reservoir<(nbits_wanted)) \ | ||
597 | { \ | ||
598 | pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \ | ||
599 | pdec->nbits_in_reservoir += 8; \ | ||
600 | } \ | ||
601 | } while(0); | ||
602 | |||
603 | #define skip_nbits(pdec, nbits_to_skip) do { \ | ||
604 | pdec->reservoir >>= (nbits_to_skip); \ | ||
605 | pdec->nbits_in_reservoir -= (nbits_to_skip); \ | ||
606 | } while(0); | ||
607 | |||
608 | #define get_nbits(pdec, nbits_wanted, result) do { \ | ||
609 | fill_nbits(pdec, nbits_wanted); \ | ||
610 | result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \ | ||
611 | skip_nbits(pdec, nbits_wanted); \ | ||
612 | } while(0); | ||
613 | |||
614 | #define __get_nbits(pdec, nbits_wanted, result) do { \ | ||
615 | result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \ | ||
616 | skip_nbits(pdec, nbits_wanted); \ | ||
617 | } while(0); | ||
618 | |||
619 | #define look_nbits(pdec, nbits_wanted) \ | ||
620 | ((pdec->reservoir) & ((1U<<(nbits_wanted))-1)) | ||
621 | |||
622 | /* | ||
623 | * Decode a 4x4 pixel block | ||
624 | */ | ||
625 | static void decode_block(struct pwc_dec23_private *pdec, | ||
626 | const unsigned char *ptable0004, | ||
627 | const unsigned char *ptable8004) | ||
628 | { | ||
629 | unsigned int primary_color; | ||
630 | unsigned int channel_v, offset1, op; | ||
631 | int i; | ||
632 | |||
633 | fill_nbits(pdec, 16); | ||
634 | __get_nbits(pdec, pdec->nbits, primary_color); | ||
635 | |||
636 | if (look_nbits(pdec,2) == 0) { | ||
637 | skip_nbits(pdec, 2); | ||
638 | /* Very simple, the color is the same for all pixels of the square */ | ||
639 | for (i = 0; i < 16; i++) | ||
640 | pdec->temp_colors[i] = pdec->table_dc00[primary_color]; | ||
641 | |||
642 | return; | ||
643 | } | ||
644 | |||
645 | /* This block is encoded with small pattern */ | ||
646 | for (i = 0; i < 16; i++) | ||
647 | pdec->temp_colors[i] = pdec->table_d800[primary_color]; | ||
648 | |||
649 | __get_nbits(pdec, 3, channel_v); | ||
650 | channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2); | ||
651 | |||
652 | ptable0004 += (channel_v * 128); | ||
653 | ptable8004 += (channel_v * 32); | ||
654 | |||
655 | offset1 = 0; | ||
656 | do | ||
657 | { | ||
658 | unsigned int htable_idx, rows = 0; | ||
659 | const unsigned int *block; | ||
660 | |||
661 | /* [ zzzz y x x ] | ||
662 | * xx == 00 :=> end of the block def, remove the two bits from the stream | ||
663 | * yxx == 111 | ||
664 | * yxx == any other value | ||
665 | * | ||
666 | */ | ||
667 | fill_nbits(pdec, 16); | ||
668 | htable_idx = look_nbits(pdec, 6); | ||
669 | op = hash_table_ops[htable_idx * 4]; | ||
670 | |||
671 | if (op == 2) { | ||
672 | skip_nbits(pdec, 2); | ||
673 | |||
674 | } else if (op == 1) { | ||
675 | /* 15bits [ xxxx xxxx yyyy 111 ] | ||
676 | * yyy => offset in the table8004 | ||
677 | * xxx => offset in the tabled004 (tree) | ||
678 | */ | ||
679 | unsigned int mask, shift; | ||
680 | unsigned int nbits, col1; | ||
681 | unsigned int yyyy; | ||
682 | |||
683 | skip_nbits(pdec, 3); | ||
684 | /* offset1 += yyyy */ | ||
685 | __get_nbits(pdec, 4, yyyy); | ||
686 | offset1 += 1 + yyyy; | ||
687 | offset1 &= 0x0F; | ||
688 | nbits = ptable8004[offset1 * 2]; | ||
689 | |||
690 | /* col1 = xxxx xxxx */ | ||
691 | __get_nbits(pdec, nbits+1, col1); | ||
692 | |||
693 | /* Bit mask table */ | ||
694 | mask = pdec->table_bitpowermask[nbits][col1]; | ||
695 | shift = ptable8004[offset1 * 2 + 1]; | ||
696 | rows = ((mask << shift) + 0x80) & 0xFF; | ||
697 | |||
698 | block = pdec->table_subblock[rows]; | ||
699 | for (i = 0; i < 16; i++) | ||
700 | pdec->temp_colors[i] += block[MulIdx[offset1][i]]; | ||
701 | |||
702 | } else { | ||
703 | /* op == 0 | ||
704 | * offset1 is coded on 3 bits | ||
705 | */ | ||
706 | unsigned int shift; | ||
707 | |||
708 | offset1 += hash_table_ops [htable_idx * 4 + 2]; | ||
709 | offset1 &= 0x0F; | ||
710 | |||
711 | rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]]; | ||
712 | block = pdec->table_subblock[rows]; | ||
713 | for (i = 0; i < 16; i++) | ||
714 | pdec->temp_colors[i] += block[MulIdx[offset1][i]]; | ||
715 | |||
716 | shift = hash_table_ops[htable_idx * 4 + 1]; | ||
717 | skip_nbits(pdec, shift); | ||
718 | } | ||
719 | |||
720 | } while (op != 2); | ||
721 | |||
722 | } | ||
723 | |||
724 | static void DecompressBand23(struct pwc_dec23_private *pdec, | ||
725 | const unsigned char *rawyuv, | ||
726 | unsigned char *planar_y, | ||
727 | unsigned char *planar_u, | ||
728 | unsigned char *planar_v, | ||
729 | unsigned int compressed_image_width, | ||
730 | unsigned int real_image_width) | ||
731 | { | ||
732 | int compression_index, nblocks; | ||
733 | const unsigned char *ptable0004; | ||
734 | const unsigned char *ptable8004; | ||
735 | |||
736 | pdec->reservoir = 0; | ||
737 | pdec->nbits_in_reservoir = 0; | ||
738 | pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */ | ||
739 | |||
740 | get_nbits(pdec, 4, compression_index); | ||
741 | |||
742 | /* pass 1: uncompress Y component */ | ||
743 | nblocks = compressed_image_width / 4; | ||
744 | |||
745 | ptable0004 = pdec->table_0004_pass1[compression_index]; | ||
746 | ptable8004 = pdec->table_8004_pass1[compression_index]; | ||
747 | |||
748 | /* Each block decode a square of 4x4 */ | ||
749 | while (nblocks) { | ||
750 | decode_block(pdec, ptable0004, ptable8004); | ||
751 | copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits); | ||
752 | planar_y += 4; | ||
753 | nblocks--; | ||
754 | } | ||
755 | |||
756 | /* pass 2: uncompress UV component */ | ||
757 | nblocks = compressed_image_width / 8; | ||
758 | |||
759 | ptable0004 = pdec->table_0004_pass2[compression_index]; | ||
760 | ptable8004 = pdec->table_8004_pass2[compression_index]; | ||
761 | |||
762 | /* Each block decode a square of 4x4 */ | ||
763 | while (nblocks) { | ||
764 | decode_block(pdec, ptable0004, ptable8004); | ||
765 | copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits); | ||
766 | |||
767 | decode_block(pdec, ptable0004, ptable8004); | ||
768 | copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits); | ||
769 | |||
770 | planar_v += 8; | ||
771 | planar_u += 8; | ||
772 | nblocks -= 2; | ||
773 | } | ||
774 | |||
775 | } | ||
776 | |||
777 | #if ENABLE_BAYER_DECODER | ||
778 | /* | ||
779 | * Size need to be a multiple of 8 in width | ||
780 | * | ||
781 | * Return a block of four line encoded like this: | ||
782 | * | ||
783 | * G R G R G R G R G R G R G R G R | ||
784 | * B G B G B G B G B G B G B G B G | ||
785 | * G R G R G R G R G R G R G R G R | ||
786 | * B G B G B G B G B G B G B G B G | ||
787 | * | ||
788 | */ | ||
789 | static void DecompressBandBayer(struct pwc_dec23_private *pdec, | ||
790 | const unsigned char *rawyuv, | ||
791 | unsigned char *rgbbayer, | ||
792 | unsigned int compressed_image_width, | ||
793 | unsigned int real_image_width) | ||
794 | { | ||
795 | int compression_index, nblocks; | ||
796 | const unsigned char *ptable0004; | ||
797 | const unsigned char *ptable8004; | ||
798 | unsigned char *dest; | ||
799 | |||
800 | pdec->reservoir = 0; | ||
801 | pdec->nbits_in_reservoir = 0; | ||
802 | pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */ | ||
803 | |||
804 | get_nbits(pdec, 4, compression_index); | ||
805 | |||
806 | /* pass 1: uncompress RB component */ | ||
807 | nblocks = compressed_image_width / 4; | ||
808 | |||
809 | ptable0004 = pdec->table_0004_pass1[compression_index]; | ||
810 | ptable8004 = pdec->table_8004_pass1[compression_index]; | ||
811 | dest = rgbbayer; | ||
812 | |||
813 | /* Each block decode a square of 4x4 */ | ||
814 | while (nblocks) { | ||
815 | decode_block(pdec, ptable0004, ptable8004); | ||
816 | copy_image_block_RedBlue(pdec->temp_colors, rgbbayer, real_image_width, pdec->scalebits); | ||
817 | dest += 8; | ||
818 | nblocks--; | ||
819 | } | ||
820 | |||
821 | /* pass 2: uncompress G component */ | ||
822 | nblocks = compressed_image_width / 8; | ||
823 | |||
824 | ptable0004 = pdec->table_0004_pass2[compression_index]; | ||
825 | ptable8004 = pdec->table_8004_pass2[compression_index]; | ||
826 | |||
827 | /* Each block decode a square of 4x4 */ | ||
828 | while (nblocks) { | ||
829 | decode_block(pdec, ptable0004, ptable8004); | ||
830 | copy_image_block_Green(pdec->temp_colors, rgbbayer+1, real_image_width, pdec->scalebits); | ||
831 | |||
832 | decode_block(pdec, ptable0004, ptable8004); | ||
833 | copy_image_block_Green(pdec->temp_colors, rgbbayer+real_image_width, real_image_width, pdec->scalebits); | ||
834 | |||
835 | rgbbayer += 16; | ||
836 | nblocks -= 2; | ||
837 | } | ||
838 | } | ||
839 | #endif | ||
840 | |||
841 | |||
842 | /** | ||
843 | * | ||
844 | * Uncompress a pwc23 buffer. | ||
845 | * | ||
846 | * pwc.view: size of the image wanted | ||
847 | * pwc.image: size of the image returned by the camera | ||
848 | * pwc.offset: (x,y) to displayer image in the view | ||
849 | * | ||
850 | * src: raw data | ||
851 | * dst: image output | ||
852 | * flags: PWCX_FLAG_PLANAR or PWCX_FLAG_BAYER | ||
853 | */ | ||
854 | void pwc_dec23_decompress(const struct pwc_device *pwc, | ||
855 | const void *src, | ||
856 | void *dst, | ||
857 | int flags) | ||
858 | { | ||
859 | int bandlines_left, stride, bytes_per_block; | ||
860 | |||
861 | bandlines_left = pwc->image.y / 4; | ||
862 | bytes_per_block = pwc->view.x * 4; | ||
863 | |||
864 | if (flags & PWCX_FLAG_BAYER) { | ||
865 | #if ENABLE_BAYER_DECODER | ||
866 | /* RGB Bayer format */ | ||
867 | unsigned char *rgbout; | ||
868 | |||
869 | stride = pwc->view.x * pwc->offset.y; | ||
870 | rgbout = dst + stride + pwc->offset.x; | ||
871 | |||
872 | |||
873 | while (bandlines_left--) { | ||
874 | |||
875 | DecompressBandBayer(pwc->decompress_data, | ||
876 | src, | ||
877 | rgbout, | ||
878 | pwc->image.x, pwc->view.x); | ||
879 | |||
880 | src += pwc->vbandlength; | ||
881 | rgbout += bytes_per_block; | ||
882 | |||
883 | } | ||
884 | #else | ||
885 | memset(dst, 0, pwc->view.x * pwc->view.y); | ||
886 | #endif | ||
887 | |||
888 | } else { | ||
889 | /* YUV420P image format */ | ||
890 | unsigned char *pout_planar_y; | ||
891 | unsigned char *pout_planar_u; | ||
892 | unsigned char *pout_planar_v; | ||
893 | unsigned int plane_size; | ||
894 | |||
895 | plane_size = pwc->view.x * pwc->view.y; | ||
896 | |||
897 | /* offset in Y plane */ | ||
898 | stride = pwc->view.x * pwc->offset.y; | ||
899 | pout_planar_y = dst + stride + pwc->offset.x; | ||
900 | |||
901 | /* offsets in U/V planes */ | ||
902 | stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2; | ||
903 | pout_planar_u = dst + plane_size + stride; | ||
904 | pout_planar_v = dst + plane_size + plane_size / 4 + stride; | ||
905 | |||
906 | while (bandlines_left--) { | ||
907 | |||
908 | DecompressBand23(pwc->decompress_data, | ||
909 | src, | ||
910 | pout_planar_y, pout_planar_u, pout_planar_v, | ||
911 | pwc->image.x, pwc->view.x); | ||
912 | src += pwc->vbandlength; | ||
913 | pout_planar_y += bytes_per_block; | ||
914 | pout_planar_u += pwc->view.x; | ||
915 | pout_planar_v += pwc->view.x; | ||
916 | |||
917 | } | ||
918 | |||
919 | } | ||
920 | |||
921 | } | ||
922 | |||
923 | void pwc_dec23_exit(void) | ||
924 | { | ||
925 | /* Do nothing */ | ||
926 | |||
927 | } | ||
928 | |||
929 | /** | ||
930 | * Allocate a private structure used by lookup table. | ||
931 | * You must call kfree() to free the memory allocated. | ||
932 | */ | ||
933 | int pwc_dec23_alloc(struct pwc_device *pwc) | ||
934 | { | ||
935 | pwc->decompress_data = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); | ||
936 | if (pwc->decompress_data == NULL) | ||
937 | return -ENOMEM; | ||
938 | return 0; | ||
939 | } | ||
940 | |||
941 | /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | ||
diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h new file mode 100644 index 000000000000..1c55298ad153 --- /dev/null +++ b/drivers/media/video/pwc/pwc-dec23.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* Linux driver for Philips webcam | ||
2 | (C) 2004-2006 Luc Saillard (luc@saillard.org) | ||
3 | |||
4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | ||
5 | driver and thus may have bugs that are not present in the original version. | ||
6 | Please send bug reports and support requests to <luc@saillard.org>. | ||
7 | The decompression routines have been implemented by reverse-engineering the | ||
8 | Nemosoft binary pwcx module. Caveat emptor. | ||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | #ifndef PWC_DEC23_H | ||
26 | #define PWC_DEC23_H | ||
27 | |||
28 | #include "pwc.h" | ||
29 | |||
30 | struct pwc_dec23_private | ||
31 | { | ||
32 | unsigned int scalebits; | ||
33 | unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */ | ||
34 | |||
35 | unsigned int reservoir; | ||
36 | unsigned int nbits_in_reservoir; | ||
37 | const unsigned char *stream; | ||
38 | int temp_colors[16]; | ||
39 | |||
40 | unsigned char table_0004_pass1[16][1024]; | ||
41 | unsigned char table_0004_pass2[16][1024]; | ||
42 | unsigned char table_8004_pass1[16][256]; | ||
43 | unsigned char table_8004_pass2[16][256]; | ||
44 | unsigned int table_subblock[256][12]; | ||
45 | |||
46 | unsigned char table_bitpowermask[8][256]; | ||
47 | unsigned int table_d800[256]; | ||
48 | unsigned int table_dc00[256]; | ||
49 | |||
50 | }; | ||
51 | |||
52 | |||
53 | int pwc_dec23_alloc(struct pwc_device *pwc); | ||
54 | int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd); | ||
55 | void pwc_dec23_exit(void); | ||
56 | void pwc_dec23_decompress(const struct pwc_device *pwc, | ||
57 | const void *src, | ||
58 | void *dst, | ||
59 | int flags); | ||
60 | |||
61 | |||
62 | |||
63 | #endif | ||
64 | |||
65 | |||
66 | /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | ||
67 | |||
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 41418294a32b..47d0d83a0264 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* Linux driver for Philips webcam | 1 | /* Linux driver for Philips webcam |
2 | USB and Video4Linux interface part. | 2 | USB and Video4Linux interface part. |
3 | (C) 1999-2004 Nemosoft Unv. | 3 | (C) 1999-2004 Nemosoft Unv. |
4 | (C) 2004 Luc Saillard (luc@saillard.org) | 4 | (C) 2004-2006 Luc Saillard (luc@saillard.org) |
5 | 5 | ||
6 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 6 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx |
7 | driver and thus may have bugs that are not present in the original version. | 7 | driver and thus may have bugs that are not present in the original version. |
@@ -62,18 +62,21 @@ | |||
62 | #include <linux/poll.h> | 62 | #include <linux/poll.h> |
63 | #include <linux/slab.h> | 63 | #include <linux/slab.h> |
64 | #include <linux/vmalloc.h> | 64 | #include <linux/vmalloc.h> |
65 | #include <linux/version.h> | ||
65 | #include <asm/io.h> | 66 | #include <asm/io.h> |
67 | #include <linux/moduleparam.h> | ||
66 | 68 | ||
67 | #include "pwc.h" | 69 | #include "pwc.h" |
68 | #include "pwc-ioctl.h" | ||
69 | #include "pwc-kiara.h" | 70 | #include "pwc-kiara.h" |
70 | #include "pwc-timon.h" | 71 | #include "pwc-timon.h" |
72 | #include "pwc-dec23.h" | ||
73 | #include "pwc-dec1.h" | ||
71 | #include "pwc-uncompress.h" | 74 | #include "pwc-uncompress.h" |
72 | 75 | ||
73 | /* Function prototypes and driver templates */ | 76 | /* Function prototypes and driver templates */ |
74 | 77 | ||
75 | /* hotplug device table support */ | 78 | /* hotplug device table support */ |
76 | static struct usb_device_id pwc_device_table [] = { | 79 | static const struct usb_device_id pwc_device_table [] = { |
77 | { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */ | 80 | { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */ |
78 | { USB_DEVICE(0x0471, 0x0303) }, | 81 | { USB_DEVICE(0x0471, 0x0303) }, |
79 | { USB_DEVICE(0x0471, 0x0304) }, | 82 | { USB_DEVICE(0x0471, 0x0304) }, |
@@ -81,9 +84,10 @@ static struct usb_device_id pwc_device_table [] = { | |||
81 | { USB_DEVICE(0x0471, 0x0308) }, | 84 | { USB_DEVICE(0x0471, 0x0308) }, |
82 | { USB_DEVICE(0x0471, 0x030C) }, | 85 | { USB_DEVICE(0x0471, 0x030C) }, |
83 | { USB_DEVICE(0x0471, 0x0310) }, | 86 | { USB_DEVICE(0x0471, 0x0310) }, |
84 | { USB_DEVICE(0x0471, 0x0311) }, | 87 | { USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */ |
85 | { USB_DEVICE(0x0471, 0x0312) }, | 88 | { USB_DEVICE(0x0471, 0x0312) }, |
86 | { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ | 89 | { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ |
90 | { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */ | ||
87 | { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ | 91 | { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ |
88 | { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ | 92 | { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ |
89 | { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ | 93 | { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ |
@@ -94,8 +98,9 @@ static struct usb_device_id pwc_device_table [] = { | |||
94 | { USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */ | 98 | { USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */ |
95 | { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */ | 99 | { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */ |
96 | { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */ | 100 | { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */ |
97 | { USB_DEVICE(0x055D, 0x9000) }, /* Samsung */ | 101 | { USB_DEVICE(0x055D, 0x9000) }, /* Samsung MPC-C10 */ |
98 | { USB_DEVICE(0x055D, 0x9001) }, | 102 | { USB_DEVICE(0x055D, 0x9001) }, /* Samsung MPC-C30 */ |
103 | { USB_DEVICE(0x055D, 0x9002) }, /* Samsung SNC-35E (Ver3.0) */ | ||
99 | { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */ | 104 | { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */ |
100 | { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */ | 105 | { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */ |
101 | { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */ | 106 | { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */ |
@@ -122,11 +127,13 @@ static struct usb_driver pwc_driver = { | |||
122 | static int default_size = PSZ_QCIF; | 127 | static int default_size = PSZ_QCIF; |
123 | static int default_fps = 10; | 128 | static int default_fps = 10; |
124 | static int default_fbufs = 3; /* Default number of frame buffers */ | 129 | static int default_fbufs = 3; /* Default number of frame buffers */ |
125 | static int default_mbufs = 2; /* Default number of mmap() buffers */ | 130 | int pwc_mbufs = 2; /* Default number of mmap() buffers */ |
126 | int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX; | 131 | #if CONFIG_PWC_DEBUG |
132 | int pwc_trace = PWC_DEBUG_LEVEL; | ||
133 | #endif | ||
127 | static int power_save = 0; | 134 | static int power_save = 0; |
128 | static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */ | 135 | static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */ |
129 | static int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */ | 136 | static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */ |
130 | static struct { | 137 | static struct { |
131 | int type; | 138 | int type; |
132 | char serial_number[30]; | 139 | char serial_number[30]; |
@@ -138,7 +145,7 @@ static struct { | |||
138 | 145 | ||
139 | static int pwc_video_open(struct inode *inode, struct file *file); | 146 | static int pwc_video_open(struct inode *inode, struct file *file); |
140 | static int pwc_video_close(struct inode *inode, struct file *file); | 147 | static int pwc_video_close(struct inode *inode, struct file *file); |
141 | static ssize_t pwc_video_read(struct file *file, char __user * buf, | 148 | static ssize_t pwc_video_read(struct file *file, char __user *buf, |
142 | size_t count, loff_t *ppos); | 149 | size_t count, loff_t *ppos); |
143 | static unsigned int pwc_video_poll(struct file *file, poll_table *wait); | 150 | static unsigned int pwc_video_poll(struct file *file, poll_table *wait); |
144 | static int pwc_video_ioctl(struct inode *inode, struct file *file, | 151 | static int pwc_video_ioctl(struct inode *inode, struct file *file, |
@@ -153,7 +160,6 @@ static struct file_operations pwc_fops = { | |||
153 | .poll = pwc_video_poll, | 160 | .poll = pwc_video_poll, |
154 | .mmap = pwc_video_mmap, | 161 | .mmap = pwc_video_mmap, |
155 | .ioctl = pwc_video_ioctl, | 162 | .ioctl = pwc_video_ioctl, |
156 | .compat_ioctl = v4l_compat_ioctl32, | ||
157 | .llseek = no_llseek, | 163 | .llseek = no_llseek, |
158 | }; | 164 | }; |
159 | static struct video_device pwc_template = { | 165 | static struct video_device pwc_template = { |
@@ -203,52 +209,44 @@ static struct video_device pwc_template = { | |||
203 | /* Here we want the physical address of the memory. | 209 | /* Here we want the physical address of the memory. |
204 | * This is used when initializing the contents of the area. | 210 | * This is used when initializing the contents of the area. |
205 | */ | 211 | */ |
206 | static inline unsigned long kvirt_to_pa(unsigned long adr) | ||
207 | { | ||
208 | unsigned long kva, ret; | ||
209 | 212 | ||
210 | kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); | ||
211 | kva |= adr & (PAGE_SIZE-1); /* restore the offset */ | ||
212 | ret = __pa(kva); | ||
213 | return ret; | ||
214 | } | ||
215 | 213 | ||
216 | static void * rvmalloc(unsigned long size) | 214 | |
215 | static void *pwc_rvmalloc(unsigned long size) | ||
217 | { | 216 | { |
218 | void * mem; | 217 | void * mem; |
219 | unsigned long adr; | 218 | unsigned long adr; |
220 | 219 | ||
221 | size=PAGE_ALIGN(size); | ||
222 | mem=vmalloc_32(size); | 220 | mem=vmalloc_32(size); |
223 | if (mem) | 221 | if (!mem) |
224 | { | 222 | return NULL; |
225 | memset(mem, 0, size); /* Clear the ram out, no junk to the user */ | 223 | |
226 | adr=(unsigned long) mem; | 224 | memset(mem, 0, size); /* Clear the ram out, no junk to the user */ |
227 | while (size > 0) | 225 | adr=(unsigned long) mem; |
228 | { | 226 | while (size > 0) |
229 | SetPageReserved(vmalloc_to_page((void *)adr)); | 227 | { |
230 | adr+=PAGE_SIZE; | 228 | SetPageReserved(vmalloc_to_page((void *)adr)); |
231 | size-=PAGE_SIZE; | 229 | adr += PAGE_SIZE; |
232 | } | 230 | size -= PAGE_SIZE; |
233 | } | 231 | } |
234 | return mem; | 232 | return mem; |
235 | } | 233 | } |
236 | 234 | ||
237 | static void rvfree(void * mem, unsigned long size) | 235 | static void pwc_rvfree(void * mem, unsigned long size) |
238 | { | 236 | { |
239 | unsigned long adr; | 237 | unsigned long adr; |
240 | 238 | ||
241 | if (mem) | 239 | if (!mem) |
242 | { | 240 | return; |
243 | adr=(unsigned long) mem; | 241 | |
244 | while ((long) size > 0) | 242 | adr=(unsigned long) mem; |
245 | { | 243 | while ((long) size > 0) |
246 | ClearPageReserved(vmalloc_to_page((void *)adr)); | 244 | { |
247 | adr+=PAGE_SIZE; | 245 | ClearPageReserved(vmalloc_to_page((void *)adr)); |
248 | size-=PAGE_SIZE; | 246 | adr += PAGE_SIZE; |
249 | } | 247 | size -= PAGE_SIZE; |
250 | vfree(mem); | 248 | } |
251 | } | 249 | vfree(mem); |
252 | } | 250 | } |
253 | 251 | ||
254 | 252 | ||
@@ -256,100 +254,83 @@ static void rvfree(void * mem, unsigned long size) | |||
256 | 254 | ||
257 | static int pwc_allocate_buffers(struct pwc_device *pdev) | 255 | static int pwc_allocate_buffers(struct pwc_device *pdev) |
258 | { | 256 | { |
259 | int i; | 257 | int i, err; |
260 | void *kbuf; | 258 | void *kbuf; |
261 | 259 | ||
262 | Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev); | 260 | PWC_DEBUG_MEMORY(">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev); |
263 | 261 | ||
264 | if (pdev == NULL) | 262 | if (pdev == NULL) |
265 | return -ENXIO; | 263 | return -ENXIO; |
266 | 264 | ||
267 | #ifdef PWC_MAGIC | 265 | /* Allocate Isochronuous pipe buffers */ |
268 | if (pdev->magic != PWC_MAGIC) { | ||
269 | Err("allocate_buffers(): magic failed.\n"); | ||
270 | return -ENXIO; | ||
271 | } | ||
272 | #endif | ||
273 | /* Allocate Isochronous pipe buffers */ | ||
274 | for (i = 0; i < MAX_ISO_BUFS; i++) { | 266 | for (i = 0; i < MAX_ISO_BUFS; i++) { |
275 | if (pdev->sbuf[i].data == NULL) { | 267 | if (pdev->sbuf[i].data == NULL) { |
276 | kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL); | 268 | kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL); |
277 | if (kbuf == NULL) { | 269 | if (kbuf == NULL) { |
278 | Err("Failed to allocate iso buffer %d.\n", i); | 270 | PWC_ERROR("Failed to allocate iso buffer %d.\n", i); |
279 | return -ENOMEM; | 271 | return -ENOMEM; |
280 | } | 272 | } |
281 | Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf); | 273 | PWC_DEBUG_MEMORY("Allocated iso buffer at %p.\n", kbuf); |
282 | pdev->sbuf[i].data = kbuf; | 274 | pdev->sbuf[i].data = kbuf; |
283 | memset(kbuf, 0, ISO_BUFFER_SIZE); | ||
284 | } | 275 | } |
285 | } | 276 | } |
286 | 277 | ||
287 | /* Allocate frame buffer structure */ | 278 | /* Allocate frame buffer structure */ |
288 | if (pdev->fbuf == NULL) { | 279 | if (pdev->fbuf == NULL) { |
289 | kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL); | 280 | kbuf = kzalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL); |
290 | if (kbuf == NULL) { | 281 | if (kbuf == NULL) { |
291 | Err("Failed to allocate frame buffer structure.\n"); | 282 | PWC_ERROR("Failed to allocate frame buffer structure.\n"); |
292 | return -ENOMEM; | 283 | return -ENOMEM; |
293 | } | 284 | } |
294 | Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf); | 285 | PWC_DEBUG_MEMORY("Allocated frame buffer structure at %p.\n", kbuf); |
295 | pdev->fbuf = kbuf; | 286 | pdev->fbuf = kbuf; |
296 | memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf)); | ||
297 | } | 287 | } |
288 | |||
298 | /* create frame buffers, and make circular ring */ | 289 | /* create frame buffers, and make circular ring */ |
299 | for (i = 0; i < default_fbufs; i++) { | 290 | for (i = 0; i < default_fbufs; i++) { |
300 | if (pdev->fbuf[i].data == NULL) { | 291 | if (pdev->fbuf[i].data == NULL) { |
301 | kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ | 292 | kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ |
302 | if (kbuf == NULL) { | 293 | if (kbuf == NULL) { |
303 | Err("Failed to allocate frame buffer %d.\n", i); | 294 | PWC_ERROR("Failed to allocate frame buffer %d.\n", i); |
304 | return -ENOMEM; | 295 | return -ENOMEM; |
305 | } | 296 | } |
306 | Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf); | 297 | PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf); |
307 | pdev->fbuf[i].data = kbuf; | 298 | pdev->fbuf[i].data = kbuf; |
308 | memset(kbuf, 128, PWC_FRAME_SIZE); | 299 | memset(kbuf, 0, PWC_FRAME_SIZE); |
309 | } | 300 | } |
310 | } | 301 | } |
311 | 302 | ||
312 | /* Allocate decompressor table space */ | 303 | /* Allocate decompressor table space */ |
313 | kbuf = NULL; | 304 | if (DEVICE_USE_CODEC1(pdev->type)) |
314 | switch (pdev->type) | 305 | err = pwc_dec1_alloc(pdev); |
315 | { | 306 | else |
316 | case 675: | 307 | err = pwc_dec23_alloc(pdev); |
317 | case 680: | 308 | |
318 | case 690: | 309 | if (err) { |
319 | case 720: | 310 | PWC_ERROR("Failed to allocate decompress table.\n"); |
320 | case 730: | 311 | return err; |
321 | case 740: | 312 | } |
322 | case 750: | ||
323 | #if 0 | ||
324 | Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private)); | ||
325 | kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */ | ||
326 | break; | ||
327 | case 645: | ||
328 | case 646: | ||
329 | /* TODO & FIXME */ | ||
330 | kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); | ||
331 | break; | ||
332 | #endif | ||
333 | ; | ||
334 | } | ||
335 | pdev->decompress_data = kbuf; | ||
336 | 313 | ||
337 | /* Allocate image buffer; double buffer for mmap() */ | 314 | /* Allocate image buffer; double buffer for mmap() */ |
338 | kbuf = rvmalloc(default_mbufs * pdev->len_per_image); | 315 | kbuf = pwc_rvmalloc(pwc_mbufs * pdev->len_per_image); |
339 | if (kbuf == NULL) { | 316 | if (kbuf == NULL) { |
340 | Err("Failed to allocate image buffer(s). needed (%d)\n",default_mbufs * pdev->len_per_image); | 317 | PWC_ERROR("Failed to allocate image buffer(s). needed (%d)\n", |
318 | pwc_mbufs * pdev->len_per_image); | ||
341 | return -ENOMEM; | 319 | return -ENOMEM; |
342 | } | 320 | } |
343 | Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf); | 321 | PWC_DEBUG_MEMORY("Allocated image buffer at %p.\n", kbuf); |
344 | pdev->image_data = kbuf; | 322 | pdev->image_data = kbuf; |
345 | for (i = 0; i < default_mbufs; i++) | 323 | for (i = 0; i < pwc_mbufs; i++) { |
346 | pdev->image_ptr[i] = kbuf + i * pdev->len_per_image; | 324 | pdev->images[i].offset = i * pdev->len_per_image; |
347 | for (; i < MAX_IMAGES; i++) | 325 | pdev->images[i].vma_use_count = 0; |
348 | pdev->image_ptr[i] = NULL; | 326 | } |
327 | for (; i < MAX_IMAGES; i++) { | ||
328 | pdev->images[i].offset = 0; | ||
329 | } | ||
349 | 330 | ||
350 | kbuf = NULL; | 331 | kbuf = NULL; |
351 | 332 | ||
352 | Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n"); | 333 | PWC_DEBUG_MEMORY("<< pwc_allocate_buffers()\n"); |
353 | return 0; | 334 | return 0; |
354 | } | 335 | } |
355 | 336 | ||
@@ -357,21 +338,14 @@ static void pwc_free_buffers(struct pwc_device *pdev) | |||
357 | { | 338 | { |
358 | int i; | 339 | int i; |
359 | 340 | ||
360 | Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev); | 341 | PWC_DEBUG_MEMORY("Entering free_buffers(%p).\n", pdev); |
361 | 342 | ||
362 | if (pdev == NULL) | 343 | if (pdev == NULL) |
363 | return; | 344 | return; |
364 | #ifdef PWC_MAGIC | ||
365 | if (pdev->magic != PWC_MAGIC) { | ||
366 | Err("free_buffers(): magic failed.\n"); | ||
367 | return; | ||
368 | } | ||
369 | #endif | ||
370 | |||
371 | /* Release Iso-pipe buffers */ | 345 | /* Release Iso-pipe buffers */ |
372 | for (i = 0; i < MAX_ISO_BUFS; i++) | 346 | for (i = 0; i < MAX_ISO_BUFS; i++) |
373 | if (pdev->sbuf[i].data != NULL) { | 347 | if (pdev->sbuf[i].data != NULL) { |
374 | Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data); | 348 | PWC_DEBUG_MEMORY("Freeing ISO buffer at %p.\n", pdev->sbuf[i].data); |
375 | kfree(pdev->sbuf[i].data); | 349 | kfree(pdev->sbuf[i].data); |
376 | pdev->sbuf[i].data = NULL; | 350 | pdev->sbuf[i].data = NULL; |
377 | } | 351 | } |
@@ -380,7 +354,7 @@ static void pwc_free_buffers(struct pwc_device *pdev) | |||
380 | if (pdev->fbuf != NULL) { | 354 | if (pdev->fbuf != NULL) { |
381 | for (i = 0; i < default_fbufs; i++) { | 355 | for (i = 0; i < default_fbufs; i++) { |
382 | if (pdev->fbuf[i].data != NULL) { | 356 | if (pdev->fbuf[i].data != NULL) { |
383 | Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data); | 357 | PWC_DEBUG_MEMORY("Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data); |
384 | vfree(pdev->fbuf[i].data); | 358 | vfree(pdev->fbuf[i].data); |
385 | pdev->fbuf[i].data = NULL; | 359 | pdev->fbuf[i].data = NULL; |
386 | } | 360 | } |
@@ -391,20 +365,19 @@ static void pwc_free_buffers(struct pwc_device *pdev) | |||
391 | 365 | ||
392 | /* Intermediate decompression buffer & tables */ | 366 | /* Intermediate decompression buffer & tables */ |
393 | if (pdev->decompress_data != NULL) { | 367 | if (pdev->decompress_data != NULL) { |
394 | Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data); | 368 | PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n", pdev->decompress_data); |
395 | kfree(pdev->decompress_data); | 369 | kfree(pdev->decompress_data); |
396 | pdev->decompress_data = NULL; | 370 | pdev->decompress_data = NULL; |
397 | } | 371 | } |
398 | pdev->decompressor = NULL; | ||
399 | 372 | ||
400 | /* Release image buffers */ | 373 | /* Release image buffers */ |
401 | if (pdev->image_data != NULL) { | 374 | if (pdev->image_data != NULL) { |
402 | Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data); | 375 | PWC_DEBUG_MEMORY("Freeing image buffer at %p.\n", pdev->image_data); |
403 | rvfree(pdev->image_data, default_mbufs * pdev->len_per_image); | 376 | pwc_rvfree(pdev->image_data, pwc_mbufs * pdev->len_per_image); |
404 | } | 377 | } |
405 | pdev->image_data = NULL; | 378 | pdev->image_data = NULL; |
406 | 379 | ||
407 | Trace(TRACE_MEMORY, "Leaving free_buffers().\n"); | 380 | PWC_DEBUG_MEMORY("Leaving free_buffers().\n"); |
408 | } | 381 | } |
409 | 382 | ||
410 | /* The frame & image buffer mess. | 383 | /* The frame & image buffer mess. |
@@ -464,7 +437,7 @@ static void pwc_free_buffers(struct pwc_device *pdev) | |||
464 | /** | 437 | /** |
465 | \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first. | 438 | \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first. |
466 | */ | 439 | */ |
467 | static inline int pwc_next_fill_frame(struct pwc_device *pdev) | 440 | static int pwc_next_fill_frame(struct pwc_device *pdev) |
468 | { | 441 | { |
469 | int ret; | 442 | int ret; |
470 | unsigned long flags; | 443 | unsigned long flags; |
@@ -489,23 +462,17 @@ static inline int pwc_next_fill_frame(struct pwc_device *pdev) | |||
489 | } | 462 | } |
490 | else { | 463 | else { |
491 | /* Hmm. Take it from the full list */ | 464 | /* Hmm. Take it from the full list */ |
492 | #if PWC_DEBUG | ||
493 | /* sanity check */ | 465 | /* sanity check */ |
494 | if (pdev->full_frames == NULL) { | 466 | if (pdev->full_frames == NULL) { |
495 | Err("Neither empty or full frames available!\n"); | 467 | PWC_ERROR("Neither empty or full frames available!\n"); |
496 | spin_unlock_irqrestore(&pdev->ptrlock, flags); | 468 | spin_unlock_irqrestore(&pdev->ptrlock, flags); |
497 | return -EINVAL; | 469 | return -EINVAL; |
498 | } | 470 | } |
499 | #endif | ||
500 | pdev->fill_frame = pdev->full_frames; | 471 | pdev->fill_frame = pdev->full_frames; |
501 | pdev->full_frames = pdev->full_frames->next; | 472 | pdev->full_frames = pdev->full_frames->next; |
502 | ret = 1; | 473 | ret = 1; |
503 | } | 474 | } |
504 | pdev->fill_frame->next = NULL; | 475 | pdev->fill_frame->next = NULL; |
505 | #if PWC_DEBUG | ||
506 | Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence); | ||
507 | pdev->fill_frame->sequence = pdev->sequence++; | ||
508 | #endif | ||
509 | spin_unlock_irqrestore(&pdev->ptrlock, flags); | 476 | spin_unlock_irqrestore(&pdev->ptrlock, flags); |
510 | return ret; | 477 | return ret; |
511 | } | 478 | } |
@@ -521,6 +488,8 @@ static void pwc_reset_buffers(struct pwc_device *pdev) | |||
521 | int i; | 488 | int i; |
522 | unsigned long flags; | 489 | unsigned long flags; |
523 | 490 | ||
491 | PWC_DEBUG_MEMORY(">> %s __enter__\n", __FUNCTION__); | ||
492 | |||
524 | spin_lock_irqsave(&pdev->ptrlock, flags); | 493 | spin_lock_irqsave(&pdev->ptrlock, flags); |
525 | pdev->full_frames = NULL; | 494 | pdev->full_frames = NULL; |
526 | pdev->full_frames_tail = NULL; | 495 | pdev->full_frames_tail = NULL; |
@@ -540,13 +509,15 @@ static void pwc_reset_buffers(struct pwc_device *pdev) | |||
540 | pdev->image_read_pos = 0; | 509 | pdev->image_read_pos = 0; |
541 | pdev->fill_image = 0; | 510 | pdev->fill_image = 0; |
542 | spin_unlock_irqrestore(&pdev->ptrlock, flags); | 511 | spin_unlock_irqrestore(&pdev->ptrlock, flags); |
512 | |||
513 | PWC_DEBUG_MEMORY("<< %s __leaving__\n", __FUNCTION__); | ||
543 | } | 514 | } |
544 | 515 | ||
545 | 516 | ||
546 | /** | 517 | /** |
547 | \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers. | 518 | \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers. |
548 | */ | 519 | */ |
549 | static int pwc_handle_frame(struct pwc_device *pdev) | 520 | int pwc_handle_frame(struct pwc_device *pdev) |
550 | { | 521 | { |
551 | int ret = 0; | 522 | int ret = 0; |
552 | unsigned long flags; | 523 | unsigned long flags; |
@@ -556,41 +527,40 @@ static int pwc_handle_frame(struct pwc_device *pdev) | |||
556 | we can release the lock after this without problems */ | 527 | we can release the lock after this without problems */ |
557 | if (pdev->read_frame != NULL) { | 528 | if (pdev->read_frame != NULL) { |
558 | /* This can't theoretically happen */ | 529 | /* This can't theoretically happen */ |
559 | Err("Huh? Read frame still in use?\n"); | 530 | PWC_ERROR("Huh? Read frame still in use?\n"); |
531 | spin_unlock_irqrestore(&pdev->ptrlock, flags); | ||
532 | return ret; | ||
533 | } | ||
534 | |||
535 | |||
536 | if (pdev->full_frames == NULL) { | ||
537 | PWC_ERROR("Woops. No frames ready.\n"); | ||
560 | } | 538 | } |
561 | else { | 539 | else { |
562 | if (pdev->full_frames == NULL) { | 540 | pdev->read_frame = pdev->full_frames; |
563 | Err("Woops. No frames ready.\n"); | 541 | pdev->full_frames = pdev->full_frames->next; |
542 | pdev->read_frame->next = NULL; | ||
543 | } | ||
544 | |||
545 | if (pdev->read_frame != NULL) { | ||
546 | /* Decompression is a lenghty process, so it's outside of the lock. | ||
547 | This gives the isoc_handler the opportunity to fill more frames | ||
548 | in the mean time. | ||
549 | */ | ||
550 | spin_unlock_irqrestore(&pdev->ptrlock, flags); | ||
551 | ret = pwc_decompress(pdev); | ||
552 | spin_lock_irqsave(&pdev->ptrlock, flags); | ||
553 | |||
554 | /* We're done with read_buffer, tack it to the end of the empty buffer list */ | ||
555 | if (pdev->empty_frames == NULL) { | ||
556 | pdev->empty_frames = pdev->read_frame; | ||
557 | pdev->empty_frames_tail = pdev->empty_frames; | ||
564 | } | 558 | } |
565 | else { | 559 | else { |
566 | pdev->read_frame = pdev->full_frames; | 560 | pdev->empty_frames_tail->next = pdev->read_frame; |
567 | pdev->full_frames = pdev->full_frames->next; | 561 | pdev->empty_frames_tail = pdev->read_frame; |
568 | pdev->read_frame->next = NULL; | ||
569 | } | ||
570 | |||
571 | if (pdev->read_frame != NULL) { | ||
572 | #if PWC_DEBUG | ||
573 | Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence); | ||
574 | #endif | ||
575 | /* Decompression is a lenghty process, so it's outside of the lock. | ||
576 | This gives the isoc_handler the opportunity to fill more frames | ||
577 | in the mean time. | ||
578 | */ | ||
579 | spin_unlock_irqrestore(&pdev->ptrlock, flags); | ||
580 | ret = pwc_decompress(pdev); | ||
581 | spin_lock_irqsave(&pdev->ptrlock, flags); | ||
582 | |||
583 | /* We're done with read_buffer, tack it to the end of the empty buffer list */ | ||
584 | if (pdev->empty_frames == NULL) { | ||
585 | pdev->empty_frames = pdev->read_frame; | ||
586 | pdev->empty_frames_tail = pdev->empty_frames; | ||
587 | } | ||
588 | else { | ||
589 | pdev->empty_frames_tail->next = pdev->read_frame; | ||
590 | pdev->empty_frames_tail = pdev->read_frame; | ||
591 | } | ||
592 | pdev->read_frame = NULL; | ||
593 | } | 562 | } |
563 | pdev->read_frame = NULL; | ||
594 | } | 564 | } |
595 | spin_unlock_irqrestore(&pdev->ptrlock, flags); | 565 | spin_unlock_irqrestore(&pdev->ptrlock, flags); |
596 | return ret; | 566 | return ret; |
@@ -599,12 +569,114 @@ static int pwc_handle_frame(struct pwc_device *pdev) | |||
599 | /** | 569 | /** |
600 | \brief Advance pointers of image buffer (after each user request) | 570 | \brief Advance pointers of image buffer (after each user request) |
601 | */ | 571 | */ |
602 | static inline void pwc_next_image(struct pwc_device *pdev) | 572 | void pwc_next_image(struct pwc_device *pdev) |
603 | { | 573 | { |
604 | pdev->image_used[pdev->fill_image] = 0; | 574 | pdev->image_used[pdev->fill_image] = 0; |
605 | pdev->fill_image = (pdev->fill_image + 1) % default_mbufs; | 575 | pdev->fill_image = (pdev->fill_image + 1) % pwc_mbufs; |
606 | } | 576 | } |
607 | 577 | ||
578 | /** | ||
579 | * Print debug information when a frame is discarded because all of our buffer | ||
580 | * is full | ||
581 | */ | ||
582 | static void pwc_frame_dumped(struct pwc_device *pdev) | ||
583 | { | ||
584 | pdev->vframes_dumped++; | ||
585 | if (pdev->vframe_count < FRAME_LOWMARK) | ||
586 | return; | ||
587 | |||
588 | if (pdev->vframes_dumped < 20) | ||
589 | PWC_DEBUG_FLOW("Dumping frame %d\n", pdev->vframe_count); | ||
590 | else if (pdev->vframes_dumped == 20) | ||
591 | PWC_DEBUG_FLOW("Dumping frame %d (last message)\n", | ||
592 | pdev->vframe_count); | ||
593 | } | ||
594 | |||
595 | static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf) | ||
596 | { | ||
597 | int awake = 0; | ||
598 | |||
599 | /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus | ||
600 | frames on the USB wire after an exposure change. This conditition is | ||
601 | however detected in the cam and a bit is set in the header. | ||
602 | */ | ||
603 | if (pdev->type == 730) { | ||
604 | unsigned char *ptr = (unsigned char *)fbuf->data; | ||
605 | |||
606 | if (ptr[1] == 1 && ptr[0] & 0x10) { | ||
607 | PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n"); | ||
608 | pdev->drop_frames += 2; | ||
609 | pdev->vframes_error++; | ||
610 | } | ||
611 | if ((ptr[0] ^ pdev->vmirror) & 0x01) { | ||
612 | if (ptr[0] & 0x01) { | ||
613 | pdev->snapshot_button_status = 1; | ||
614 | PWC_TRACE("Snapshot button pressed.\n"); | ||
615 | } | ||
616 | else { | ||
617 | PWC_TRACE("Snapshot button released.\n"); | ||
618 | } | ||
619 | } | ||
620 | if ((ptr[0] ^ pdev->vmirror) & 0x02) { | ||
621 | if (ptr[0] & 0x02) | ||
622 | PWC_TRACE("Image is mirrored.\n"); | ||
623 | else | ||
624 | PWC_TRACE("Image is normal.\n"); | ||
625 | } | ||
626 | pdev->vmirror = ptr[0] & 0x03; | ||
627 | /* Sometimes the trailer of the 730 is still sent as a 4 byte packet | ||
628 | after a short frame; this condition is filtered out specifically. A 4 byte | ||
629 | frame doesn't make sense anyway. | ||
630 | So we get either this sequence: | ||
631 | drop_bit set -> 4 byte frame -> short frame -> good frame | ||
632 | Or this one: | ||
633 | drop_bit set -> short frame -> good frame | ||
634 | So we drop either 3 or 2 frames in all! | ||
635 | */ | ||
636 | if (fbuf->filled == 4) | ||
637 | pdev->drop_frames++; | ||
638 | } | ||
639 | else if (pdev->type == 740 || pdev->type == 720) { | ||
640 | unsigned char *ptr = (unsigned char *)fbuf->data; | ||
641 | if ((ptr[0] ^ pdev->vmirror) & 0x01) { | ||
642 | if (ptr[0] & 0x01) { | ||
643 | pdev->snapshot_button_status = 1; | ||
644 | PWC_TRACE("Snapshot button pressed.\n"); | ||
645 | } | ||
646 | else | ||
647 | PWC_TRACE("Snapshot button released.\n"); | ||
648 | } | ||
649 | pdev->vmirror = ptr[0] & 0x03; | ||
650 | } | ||
651 | |||
652 | /* In case we were instructed to drop the frame, do so silently. | ||
653 | The buffer pointers are not updated either (but the counters are reset below). | ||
654 | */ | ||
655 | if (pdev->drop_frames > 0) | ||
656 | pdev->drop_frames--; | ||
657 | else { | ||
658 | /* Check for underflow first */ | ||
659 | if (fbuf->filled < pdev->frame_total_size) { | ||
660 | PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);" | ||
661 | " discarded.\n", fbuf->filled); | ||
662 | pdev->vframes_error++; | ||
663 | } | ||
664 | else { | ||
665 | /* Send only once per EOF */ | ||
666 | awake = 1; /* delay wake_ups */ | ||
667 | |||
668 | /* Find our next frame to fill. This will always succeed, since we | ||
669 | * nick a frame from either empty or full list, but if we had to | ||
670 | * take it from the full list, it means a frame got dropped. | ||
671 | */ | ||
672 | if (pwc_next_fill_frame(pdev)) | ||
673 | pwc_frame_dumped(pdev); | ||
674 | |||
675 | } | ||
676 | } /* !drop_frames */ | ||
677 | pdev->vframe_count++; | ||
678 | return awake; | ||
679 | } | ||
608 | 680 | ||
609 | /* This gets called for the Isochronous pipe (video). This is done in | 681 | /* This gets called for the Isochronous pipe (video). This is done in |
610 | * interrupt time, so it has to be fast, not crash, and not stall. Neat. | 682 | * interrupt time, so it has to be fast, not crash, and not stall. Neat. |
@@ -620,17 +692,12 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) | |||
620 | awake = 0; | 692 | awake = 0; |
621 | pdev = (struct pwc_device *)urb->context; | 693 | pdev = (struct pwc_device *)urb->context; |
622 | if (pdev == NULL) { | 694 | if (pdev == NULL) { |
623 | Err("isoc_handler() called with NULL device?!\n"); | 695 | PWC_ERROR("isoc_handler() called with NULL device?!\n"); |
624 | return; | ||
625 | } | ||
626 | #ifdef PWC_MAGIC | ||
627 | if (pdev->magic != PWC_MAGIC) { | ||
628 | Err("isoc_handler() called with bad magic!\n"); | ||
629 | return; | 696 | return; |
630 | } | 697 | } |
631 | #endif | 698 | |
632 | if (urb->status == -ENOENT || urb->status == -ECONNRESET) { | 699 | if (urb->status == -ENOENT || urb->status == -ECONNRESET) { |
633 | Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a"); | 700 | PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a"); |
634 | return; | 701 | return; |
635 | } | 702 | } |
636 | if (urb->status != -EINPROGRESS && urb->status != 0) { | 703 | if (urb->status != -EINPROGRESS && urb->status != 0) { |
@@ -645,13 +712,13 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) | |||
645 | case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break; | 712 | case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break; |
646 | case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break; | 713 | case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break; |
647 | } | 714 | } |
648 | Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg); | 715 | PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg); |
649 | /* Give up after a number of contiguous errors on the USB bus. | 716 | /* Give up after a number of contiguous errors on the USB bus. |
650 | Appearantly something is wrong so we simulate an unplug event. | 717 | Appearantly something is wrong so we simulate an unplug event. |
651 | */ | 718 | */ |
652 | if (++pdev->visoc_errors > MAX_ISOC_ERRORS) | 719 | if (++pdev->visoc_errors > MAX_ISOC_ERRORS) |
653 | { | 720 | { |
654 | Info("Too many ISOC errors, bailing out.\n"); | 721 | PWC_INFO("Too many ISOC errors, bailing out.\n"); |
655 | pdev->error_status = EIO; | 722 | pdev->error_status = EIO; |
656 | awake = 1; | 723 | awake = 1; |
657 | wake_up_interruptible(&pdev->frameq); | 724 | wake_up_interruptible(&pdev->frameq); |
@@ -661,7 +728,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) | |||
661 | 728 | ||
662 | fbuf = pdev->fill_frame; | 729 | fbuf = pdev->fill_frame; |
663 | if (fbuf == NULL) { | 730 | if (fbuf == NULL) { |
664 | Err("pwc_isoc_handler without valid fill frame.\n"); | 731 | PWC_ERROR("pwc_isoc_handler without valid fill frame.\n"); |
665 | awake = 1; | 732 | awake = 1; |
666 | goto handler_end; | 733 | goto handler_end; |
667 | } | 734 | } |
@@ -688,7 +755,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) | |||
688 | 755 | ||
689 | /* ...copy data to frame buffer, if possible */ | 756 | /* ...copy data to frame buffer, if possible */ |
690 | if (flen + fbuf->filled > pdev->frame_total_size) { | 757 | if (flen + fbuf->filled > pdev->frame_total_size) { |
691 | Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size); | 758 | PWC_DEBUG_FLOW("Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size); |
692 | pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */ | 759 | pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */ |
693 | pdev->vframes_error++; | 760 | pdev->vframes_error++; |
694 | } | 761 | } |
@@ -704,96 +771,28 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) | |||
704 | /* Shorter packet... We probably have the end of an image-frame; | 771 | /* Shorter packet... We probably have the end of an image-frame; |
705 | wake up read() process and let select()/poll() do something. | 772 | wake up read() process and let select()/poll() do something. |
706 | Decompression is done in user time over there. | 773 | Decompression is done in user time over there. |
707 | */ | 774 | */ |
708 | if (pdev->vsync == 2) { | 775 | if (pdev->vsync == 2) { |
709 | /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus | 776 | if (pwc_rcv_short_packet(pdev, fbuf)) { |
710 | frames on the USB wire after an exposure change. This conditition is | 777 | awake = 1; |
711 | however detected in the cam and a bit is set in the header. | 778 | fbuf = pdev->fill_frame; |
712 | */ | ||
713 | if (pdev->type == 730) { | ||
714 | unsigned char *ptr = (unsigned char *)fbuf->data; | ||
715 | |||
716 | if (ptr[1] == 1 && ptr[0] & 0x10) { | ||
717 | #if PWC_DEBUG | ||
718 | Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence); | ||
719 | #endif | ||
720 | pdev->drop_frames += 2; | ||
721 | pdev->vframes_error++; | ||
722 | } | ||
723 | if ((ptr[0] ^ pdev->vmirror) & 0x01) { | ||
724 | if (ptr[0] & 0x01) | ||
725 | Info("Snapshot button pressed.\n"); | ||
726 | else | ||
727 | Info("Snapshot button released.\n"); | ||
728 | } | ||
729 | if ((ptr[0] ^ pdev->vmirror) & 0x02) { | ||
730 | if (ptr[0] & 0x02) | ||
731 | Info("Image is mirrored.\n"); | ||
732 | else | ||
733 | Info("Image is normal.\n"); | ||
734 | } | ||
735 | pdev->vmirror = ptr[0] & 0x03; | ||
736 | /* Sometimes the trailer of the 730 is still sent as a 4 byte packet | ||
737 | after a short frame; this condition is filtered out specifically. A 4 byte | ||
738 | frame doesn't make sense anyway. | ||
739 | So we get either this sequence: | ||
740 | drop_bit set -> 4 byte frame -> short frame -> good frame | ||
741 | Or this one: | ||
742 | drop_bit set -> short frame -> good frame | ||
743 | So we drop either 3 or 2 frames in all! | ||
744 | */ | ||
745 | if (fbuf->filled == 4) | ||
746 | pdev->drop_frames++; | ||
747 | } | 779 | } |
748 | |||
749 | /* In case we were instructed to drop the frame, do so silently. | ||
750 | The buffer pointers are not updated either (but the counters are reset below). | ||
751 | */ | ||
752 | if (pdev->drop_frames > 0) | ||
753 | pdev->drop_frames--; | ||
754 | else { | ||
755 | /* Check for underflow first */ | ||
756 | if (fbuf->filled < pdev->frame_total_size) { | ||
757 | Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled); | ||
758 | pdev->vframes_error++; | ||
759 | } | ||
760 | else { | ||
761 | /* Send only once per EOF */ | ||
762 | awake = 1; /* delay wake_ups */ | ||
763 | |||
764 | /* Find our next frame to fill. This will always succeed, since we | ||
765 | * nick a frame from either empty or full list, but if we had to | ||
766 | * take it from the full list, it means a frame got dropped. | ||
767 | */ | ||
768 | if (pwc_next_fill_frame(pdev)) { | ||
769 | pdev->vframes_dumped++; | ||
770 | if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) { | ||
771 | if (pdev->vframes_dumped < 20) | ||
772 | Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count); | ||
773 | if (pdev->vframes_dumped == 20) | ||
774 | Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count); | ||
775 | } | ||
776 | } | ||
777 | fbuf = pdev->fill_frame; | ||
778 | } | ||
779 | } /* !drop_frames */ | ||
780 | pdev->vframe_count++; | ||
781 | } | 780 | } |
782 | fbuf->filled = 0; | 781 | fbuf->filled = 0; |
783 | fillptr = fbuf->data; | 782 | fillptr = fbuf->data; |
784 | pdev->vsync = 1; | 783 | pdev->vsync = 1; |
785 | } /* .. flen < last_packet_size */ | 784 | } |
785 | |||
786 | pdev->vlast_packet_size = flen; | 786 | pdev->vlast_packet_size = flen; |
787 | } /* ..status == 0 */ | 787 | } /* ..status == 0 */ |
788 | #if PWC_DEBUG | ||
789 | /* This is normally not interesting to the user, unless you are really debugging something */ | ||
790 | else { | 788 | else { |
789 | /* This is normally not interesting to the user, unless | ||
790 | * you are really debugging something */ | ||
791 | static int iso_error = 0; | 791 | static int iso_error = 0; |
792 | iso_error++; | 792 | iso_error++; |
793 | if (iso_error < 20) | 793 | if (iso_error < 20) |
794 | Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst); | 794 | PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst); |
795 | } | 795 | } |
796 | #endif | ||
797 | } | 796 | } |
798 | 797 | ||
799 | handler_end: | 798 | handler_end: |
@@ -803,11 +802,11 @@ handler_end: | |||
803 | urb->dev = pdev->udev; | 802 | urb->dev = pdev->udev; |
804 | i = usb_submit_urb(urb, GFP_ATOMIC); | 803 | i = usb_submit_urb(urb, GFP_ATOMIC); |
805 | if (i != 0) | 804 | if (i != 0) |
806 | Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i); | 805 | PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i); |
807 | } | 806 | } |
808 | 807 | ||
809 | 808 | ||
810 | static int pwc_isoc_init(struct pwc_device *pdev) | 809 | int pwc_isoc_init(struct pwc_device *pdev) |
811 | { | 810 | { |
812 | struct usb_device *udev; | 811 | struct usb_device *udev; |
813 | struct urb *urb; | 812 | struct urb *urb; |
@@ -826,7 +825,6 @@ static int pwc_isoc_init(struct pwc_device *pdev) | |||
826 | /* Get the current alternate interface, adjust packet size */ | 825 | /* Get the current alternate interface, adjust packet size */ |
827 | if (!udev->actconfig) | 826 | if (!udev->actconfig) |
828 | return -EFAULT; | 827 | return -EFAULT; |
829 | |||
830 | intf = usb_ifnum_to_if(udev, 0); | 828 | intf = usb_ifnum_to_if(udev, 0); |
831 | if (intf) | 829 | if (intf) |
832 | idesc = usb_altnum_to_altsetting(intf, pdev->valternate); | 830 | idesc = usb_altnum_to_altsetting(intf, pdev->valternate); |
@@ -836,20 +834,21 @@ static int pwc_isoc_init(struct pwc_device *pdev) | |||
836 | 834 | ||
837 | /* Search video endpoint */ | 835 | /* Search video endpoint */ |
838 | pdev->vmax_packet_size = -1; | 836 | pdev->vmax_packet_size = -1; |
839 | for (i = 0; i < idesc->desc.bNumEndpoints; i++) | 837 | for (i = 0; i < idesc->desc.bNumEndpoints; i++) { |
840 | if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) { | 838 | if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) { |
841 | pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize); | 839 | pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize); |
842 | break; | 840 | break; |
843 | } | 841 | } |
842 | } | ||
844 | 843 | ||
845 | if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) { | 844 | if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) { |
846 | Err("Failed to find packet size for video endpoint in current alternate setting.\n"); | 845 | PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n"); |
847 | return -ENFILE; /* Odd error, that should be noticeable */ | 846 | return -ENFILE; /* Odd error, that should be noticeable */ |
848 | } | 847 | } |
849 | 848 | ||
850 | /* Set alternate interface */ | 849 | /* Set alternate interface */ |
851 | ret = 0; | 850 | ret = 0; |
852 | Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate); | 851 | PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate); |
853 | ret = usb_set_interface(pdev->udev, 0, pdev->valternate); | 852 | ret = usb_set_interface(pdev->udev, 0, pdev->valternate); |
854 | if (ret < 0) | 853 | if (ret < 0) |
855 | return ret; | 854 | return ret; |
@@ -857,12 +856,12 @@ static int pwc_isoc_init(struct pwc_device *pdev) | |||
857 | for (i = 0; i < MAX_ISO_BUFS; i++) { | 856 | for (i = 0; i < MAX_ISO_BUFS; i++) { |
858 | urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); | 857 | urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); |
859 | if (urb == NULL) { | 858 | if (urb == NULL) { |
860 | Err("Failed to allocate urb %d\n", i); | 859 | PWC_ERROR("Failed to allocate urb %d\n", i); |
861 | ret = -ENOMEM; | 860 | ret = -ENOMEM; |
862 | break; | 861 | break; |
863 | } | 862 | } |
864 | pdev->sbuf[i].urb = urb; | 863 | pdev->sbuf[i].urb = urb; |
865 | Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb); | 864 | PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb); |
866 | } | 865 | } |
867 | if (ret) { | 866 | if (ret) { |
868 | /* De-allocate in reverse order */ | 867 | /* De-allocate in reverse order */ |
@@ -899,24 +898,26 @@ static int pwc_isoc_init(struct pwc_device *pdev) | |||
899 | for (i = 0; i < MAX_ISO_BUFS; i++) { | 898 | for (i = 0; i < MAX_ISO_BUFS; i++) { |
900 | ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL); | 899 | ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL); |
901 | if (ret) | 900 | if (ret) |
902 | Err("isoc_init() submit_urb %d failed with error %d\n", i, ret); | 901 | PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret); |
903 | else | 902 | else |
904 | Trace(TRACE_MEMORY, "URB 0x%p submitted.\n", pdev->sbuf[i].urb); | 903 | PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb); |
905 | } | 904 | } |
906 | 905 | ||
907 | /* All is done... */ | 906 | /* All is done... */ |
908 | pdev->iso_init = 1; | 907 | pdev->iso_init = 1; |
909 | Trace(TRACE_OPEN, "<< pwc_isoc_init()\n"); | 908 | PWC_DEBUG_OPEN("<< pwc_isoc_init()\n"); |
910 | return 0; | 909 | return 0; |
911 | } | 910 | } |
912 | 911 | ||
913 | static void pwc_isoc_cleanup(struct pwc_device *pdev) | 912 | void pwc_isoc_cleanup(struct pwc_device *pdev) |
914 | { | 913 | { |
915 | int i; | 914 | int i; |
916 | 915 | ||
917 | Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n"); | 916 | PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n"); |
918 | if (pdev == NULL) | 917 | if (pdev == NULL) |
919 | return; | 918 | return; |
919 | if (pdev->iso_init == 0) | ||
920 | return; | ||
920 | 921 | ||
921 | /* Unlinking ISOC buffers one by one */ | 922 | /* Unlinking ISOC buffers one by one */ |
922 | for (i = 0; i < MAX_ISO_BUFS; i++) { | 923 | for (i = 0; i < MAX_ISO_BUFS; i++) { |
@@ -925,10 +926,10 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev) | |||
925 | urb = pdev->sbuf[i].urb; | 926 | urb = pdev->sbuf[i].urb; |
926 | if (urb != 0) { | 927 | if (urb != 0) { |
927 | if (pdev->iso_init) { | 928 | if (pdev->iso_init) { |
928 | Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb); | 929 | PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb); |
929 | usb_kill_urb(urb); | 930 | usb_kill_urb(urb); |
930 | } | 931 | } |
931 | Trace(TRACE_MEMORY, "Freeing URB\n"); | 932 | PWC_DEBUG_MEMORY("Freeing URB\n"); |
932 | usb_free_urb(urb); | 933 | usb_free_urb(urb); |
933 | pdev->sbuf[i].urb = NULL; | 934 | pdev->sbuf[i].urb = NULL; |
934 | } | 935 | } |
@@ -938,12 +939,12 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev) | |||
938 | is signalled by EPIPE) | 939 | is signalled by EPIPE) |
939 | */ | 940 | */ |
940 | if (pdev->error_status && pdev->error_status != EPIPE) { | 941 | if (pdev->error_status && pdev->error_status != EPIPE) { |
941 | Trace(TRACE_OPEN, "Setting alternate interface 0.\n"); | 942 | PWC_DEBUG_OPEN("Setting alternate interface 0.\n"); |
942 | usb_set_interface(pdev->udev, 0, 0); | 943 | usb_set_interface(pdev->udev, 0, 0); |
943 | } | 944 | } |
944 | 945 | ||
945 | pdev->iso_init = 0; | 946 | pdev->iso_init = 0; |
946 | Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n"); | 947 | PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n"); |
947 | } | 948 | } |
948 | 949 | ||
949 | int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot) | 950 | int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot) |
@@ -957,18 +958,18 @@ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_f | |||
957 | /* Try to set video mode... */ | 958 | /* Try to set video mode... */ |
958 | start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); | 959 | start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); |
959 | if (ret) { | 960 | if (ret) { |
960 | Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n"); | 961 | PWC_DEBUG_FLOW("pwc_set_video_mode attempt 1 failed.\n"); |
961 | /* That failed... restore old mode (we know that worked) */ | 962 | /* That failed... restore old mode (we know that worked) */ |
962 | start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); | 963 | start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); |
963 | if (start) { | 964 | if (start) { |
964 | Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n"); | 965 | PWC_DEBUG_FLOW("pwc_set_video_mode attempt 2 failed.\n"); |
965 | } | 966 | } |
966 | } | 967 | } |
967 | if (start == 0) | 968 | if (start == 0) |
968 | { | 969 | { |
969 | if (pwc_isoc_init(pdev) < 0) | 970 | if (pwc_isoc_init(pdev) < 0) |
970 | { | 971 | { |
971 | Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n"); | 972 | PWC_WARNING("Failed to restart ISOC transfers in pwc_try_video_mode.\n"); |
972 | ret = -EAGAIN; /* let's try again, who knows if it works a second time */ | 973 | ret = -EAGAIN; /* let's try again, who knows if it works a second time */ |
973 | } | 974 | } |
974 | } | 975 | } |
@@ -976,54 +977,129 @@ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_f | |||
976 | return ret; /* Return original error code */ | 977 | return ret; /* Return original error code */ |
977 | } | 978 | } |
978 | 979 | ||
980 | /********* | ||
981 | * sysfs | ||
982 | *********/ | ||
983 | static struct pwc_device *cd_to_pwc(struct class_device *cd) | ||
984 | { | ||
985 | struct video_device *vdev = to_video_device(cd); | ||
986 | return video_get_drvdata(vdev); | ||
987 | } | ||
988 | |||
989 | static ssize_t show_pan_tilt(struct class_device *class_dev, char *buf) | ||
990 | { | ||
991 | struct pwc_device *pdev = cd_to_pwc(class_dev); | ||
992 | return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle); | ||
993 | } | ||
994 | |||
995 | static ssize_t store_pan_tilt(struct class_device *class_dev, const char *buf, | ||
996 | size_t count) | ||
997 | { | ||
998 | struct pwc_device *pdev = cd_to_pwc(class_dev); | ||
999 | int pan, tilt; | ||
1000 | int ret = -EINVAL; | ||
1001 | |||
1002 | if (strncmp(buf, "reset", 5) == 0) | ||
1003 | ret = pwc_mpt_reset(pdev, 0x3); | ||
1004 | |||
1005 | else if (sscanf(buf, "%d %d", &pan, &tilt) > 0) | ||
1006 | ret = pwc_mpt_set_angle(pdev, pan, tilt); | ||
1007 | |||
1008 | if (ret < 0) | ||
1009 | return ret; | ||
1010 | return strlen(buf); | ||
1011 | } | ||
1012 | static CLASS_DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt, | ||
1013 | store_pan_tilt); | ||
1014 | |||
1015 | static ssize_t show_snapshot_button_status(struct class_device *class_dev, char *buf) | ||
1016 | { | ||
1017 | struct pwc_device *pdev = cd_to_pwc(class_dev); | ||
1018 | int status = pdev->snapshot_button_status; | ||
1019 | pdev->snapshot_button_status = 0; | ||
1020 | return sprintf(buf, "%d\n", status); | ||
1021 | } | ||
1022 | |||
1023 | static CLASS_DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status, | ||
1024 | NULL); | ||
1025 | |||
1026 | static void pwc_create_sysfs_files(struct video_device *vdev) | ||
1027 | { | ||
1028 | struct pwc_device *pdev = video_get_drvdata(vdev); | ||
1029 | if (pdev->features & FEATURE_MOTOR_PANTILT) | ||
1030 | video_device_create_file(vdev, &class_device_attr_pan_tilt); | ||
1031 | video_device_create_file(vdev, &class_device_attr_button); | ||
1032 | } | ||
1033 | |||
1034 | static void pwc_remove_sysfs_files(struct video_device *vdev) | ||
1035 | { | ||
1036 | struct pwc_device *pdev = video_get_drvdata(vdev); | ||
1037 | if (pdev->features & FEATURE_MOTOR_PANTILT) | ||
1038 | video_device_remove_file(vdev, &class_device_attr_pan_tilt); | ||
1039 | video_device_remove_file(vdev, &class_device_attr_button); | ||
1040 | } | ||
1041 | |||
1042 | #if CONFIG_PWC_DEBUG | ||
1043 | static const char *pwc_sensor_type_to_string(unsigned int sensor_type) | ||
1044 | { | ||
1045 | switch(sensor_type) { | ||
1046 | case 0x00: | ||
1047 | return "Hyundai CMOS sensor"; | ||
1048 | case 0x20: | ||
1049 | return "Sony CCD sensor + TDA8787"; | ||
1050 | case 0x2E: | ||
1051 | return "Sony CCD sensor + Exas 98L59"; | ||
1052 | case 0x2F: | ||
1053 | return "Sony CCD sensor + ADI 9804"; | ||
1054 | case 0x30: | ||
1055 | return "Sharp CCD sensor + TDA8787"; | ||
1056 | case 0x3E: | ||
1057 | return "Sharp CCD sensor + Exas 98L59"; | ||
1058 | case 0x3F: | ||
1059 | return "Sharp CCD sensor + ADI 9804"; | ||
1060 | case 0x40: | ||
1061 | return "UPA 1021 sensor"; | ||
1062 | case 0x100: | ||
1063 | return "VGA sensor"; | ||
1064 | case 0x101: | ||
1065 | return "PAL MR sensor"; | ||
1066 | default: | ||
1067 | return "unknown type of sensor"; | ||
1068 | } | ||
1069 | } | ||
1070 | #endif | ||
979 | 1071 | ||
980 | /***************************************************************************/ | 1072 | /***************************************************************************/ |
981 | /* Video4Linux functions */ | 1073 | /* Video4Linux functions */ |
982 | 1074 | ||
983 | static int pwc_video_open(struct inode *inode, struct file *file) | 1075 | static int pwc_video_open(struct inode *inode, struct file *file) |
984 | { | 1076 | { |
985 | int i; | 1077 | int i, ret; |
986 | struct video_device *vdev = video_devdata(file); | 1078 | struct video_device *vdev = video_devdata(file); |
987 | struct pwc_device *pdev; | 1079 | struct pwc_device *pdev; |
988 | 1080 | ||
989 | Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev); | 1081 | PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev); |
990 | 1082 | ||
991 | pdev = (struct pwc_device *)vdev->priv; | 1083 | pdev = (struct pwc_device *)vdev->priv; |
992 | if (pdev == NULL) | 1084 | if (pdev == NULL) |
993 | BUG(); | 1085 | BUG(); |
994 | if (pdev->vopen) | 1086 | if (pdev->vopen) { |
1087 | PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n"); | ||
995 | return -EBUSY; | 1088 | return -EBUSY; |
1089 | } | ||
996 | 1090 | ||
997 | down(&pdev->modlock); | 1091 | down(&pdev->modlock); |
998 | if (!pdev->usb_init) { | 1092 | if (!pdev->usb_init) { |
999 | Trace(TRACE_OPEN, "Doing first time initialization.\n"); | 1093 | PWC_DEBUG_OPEN("Doing first time initialization.\n"); |
1000 | pdev->usb_init = 1; | 1094 | pdev->usb_init = 1; |
1001 | 1095 | ||
1002 | if (pwc_trace & TRACE_OPEN) | 1096 | /* Query sensor type */ |
1097 | ret = pwc_get_cmos_sensor(pdev, &i); | ||
1098 | if (ret >= 0) | ||
1003 | { | 1099 | { |
1004 | /* Query sensor type */ | 1100 | PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n", |
1005 | const char *sensor_type = NULL; | 1101 | pdev->vdev->name, |
1006 | int ret; | 1102 | pwc_sensor_type_to_string(i), i); |
1007 | |||
1008 | ret = pwc_get_cmos_sensor(pdev, &i); | ||
1009 | if (ret >= 0) | ||
1010 | { | ||
1011 | switch(i) { | ||
1012 | case 0x00: sensor_type = "Hyundai CMOS sensor"; break; | ||
1013 | case 0x20: sensor_type = "Sony CCD sensor + TDA8787"; break; | ||
1014 | case 0x2E: sensor_type = "Sony CCD sensor + Exas 98L59"; break; | ||
1015 | case 0x2F: sensor_type = "Sony CCD sensor + ADI 9804"; break; | ||
1016 | case 0x30: sensor_type = "Sharp CCD sensor + TDA8787"; break; | ||
1017 | case 0x3E: sensor_type = "Sharp CCD sensor + Exas 98L59"; break; | ||
1018 | case 0x3F: sensor_type = "Sharp CCD sensor + ADI 9804"; break; | ||
1019 | case 0x40: sensor_type = "UPA 1021 sensor"; break; | ||
1020 | case 0x100: sensor_type = "VGA sensor"; break; | ||
1021 | case 0x101: sensor_type = "PAL MR sensor"; break; | ||
1022 | default: sensor_type = "unknown type of sensor"; break; | ||
1023 | } | ||
1024 | } | ||
1025 | if (sensor_type != NULL) | ||
1026 | Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i); | ||
1027 | } | 1103 | } |
1028 | } | 1104 | } |
1029 | 1105 | ||
@@ -1031,34 +1107,32 @@ static int pwc_video_open(struct inode *inode, struct file *file) | |||
1031 | if (power_save) { | 1107 | if (power_save) { |
1032 | i = pwc_camera_power(pdev, 1); | 1108 | i = pwc_camera_power(pdev, 1); |
1033 | if (i < 0) | 1109 | if (i < 0) |
1034 | Info("Failed to restore power to the camera! (%d)\n", i); | 1110 | PWC_DEBUG_OPEN("Failed to restore power to the camera! (%d)\n", i); |
1035 | } | 1111 | } |
1036 | /* Set LED on/off time */ | 1112 | /* Set LED on/off time */ |
1037 | if (pwc_set_leds(pdev, led_on, led_off) < 0) | 1113 | if (pwc_set_leds(pdev, led_on, led_off) < 0) |
1038 | Info("Failed to set LED on/off time.\n"); | 1114 | PWC_DEBUG_OPEN("Failed to set LED on/off time.\n"); |
1039 | 1115 | ||
1040 | pwc_construct(pdev); /* set min/max sizes correct */ | 1116 | pwc_construct(pdev); /* set min/max sizes correct */ |
1041 | 1117 | ||
1042 | /* So far, so good. Allocate memory. */ | 1118 | /* So far, so good. Allocate memory. */ |
1043 | i = pwc_allocate_buffers(pdev); | 1119 | i = pwc_allocate_buffers(pdev); |
1044 | if (i < 0) { | 1120 | if (i < 0) { |
1045 | Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n"); | 1121 | PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n"); |
1122 | pwc_free_buffers(pdev); | ||
1046 | up(&pdev->modlock); | 1123 | up(&pdev->modlock); |
1047 | return i; | 1124 | return i; |
1048 | } | 1125 | } |
1049 | 1126 | ||
1050 | /* Reset buffers & parameters */ | 1127 | /* Reset buffers & parameters */ |
1051 | pwc_reset_buffers(pdev); | 1128 | pwc_reset_buffers(pdev); |
1052 | for (i = 0; i < default_mbufs; i++) | 1129 | for (i = 0; i < pwc_mbufs; i++) |
1053 | pdev->image_used[i] = 0; | 1130 | pdev->image_used[i] = 0; |
1054 | pdev->vframe_count = 0; | 1131 | pdev->vframe_count = 0; |
1055 | pdev->vframes_dumped = 0; | 1132 | pdev->vframes_dumped = 0; |
1056 | pdev->vframes_error = 0; | 1133 | pdev->vframes_error = 0; |
1057 | pdev->visoc_errors = 0; | 1134 | pdev->visoc_errors = 0; |
1058 | pdev->error_status = 0; | 1135 | pdev->error_status = 0; |
1059 | #if PWC_DEBUG | ||
1060 | pdev->sequence = 0; | ||
1061 | #endif | ||
1062 | pwc_construct(pdev); /* set min/max sizes correct */ | 1136 | pwc_construct(pdev); /* set min/max sizes correct */ |
1063 | 1137 | ||
1064 | /* Set some defaults */ | 1138 | /* Set some defaults */ |
@@ -1070,29 +1144,44 @@ static int pwc_video_open(struct inode *inode, struct file *file) | |||
1070 | */ | 1144 | */ |
1071 | i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0); | 1145 | i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0); |
1072 | if (i) { | 1146 | if (i) { |
1073 | Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n"); | 1147 | unsigned int default_resolution; |
1074 | if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750) | 1148 | PWC_DEBUG_OPEN("First attempt at set_video_mode failed.\n"); |
1075 | i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0); | 1149 | if (pdev->type>= 730) |
1150 | default_resolution = PSZ_QSIF; | ||
1076 | else | 1151 | else |
1077 | i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0); | 1152 | default_resolution = PSZ_QCIF; |
1153 | |||
1154 | i = pwc_set_video_mode(pdev, | ||
1155 | pwc_image_sizes[default_resolution].x, | ||
1156 | pwc_image_sizes[default_resolution].y, | ||
1157 | 10, | ||
1158 | pdev->vcompression, | ||
1159 | 0); | ||
1078 | } | 1160 | } |
1079 | if (i) { | 1161 | if (i) { |
1080 | Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n"); | 1162 | PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n"); |
1163 | pwc_free_buffers(pdev); | ||
1081 | up(&pdev->modlock); | 1164 | up(&pdev->modlock); |
1082 | return i; | 1165 | return i; |
1083 | } | 1166 | } |
1084 | 1167 | ||
1085 | i = pwc_isoc_init(pdev); | 1168 | i = pwc_isoc_init(pdev); |
1086 | if (i) { | 1169 | if (i) { |
1087 | Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i); | 1170 | PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i); |
1171 | pwc_isoc_cleanup(pdev); | ||
1172 | pwc_free_buffers(pdev); | ||
1088 | up(&pdev->modlock); | 1173 | up(&pdev->modlock); |
1089 | return i; | 1174 | return i; |
1090 | } | 1175 | } |
1091 | 1176 | ||
1177 | /* Initialize the webcam to sane value */ | ||
1178 | pwc_set_brightness(pdev, 0x7fff); | ||
1179 | pwc_set_agc(pdev, 1, 0); | ||
1180 | |||
1092 | pdev->vopen++; | 1181 | pdev->vopen++; |
1093 | file->private_data = vdev; | 1182 | file->private_data = vdev; |
1094 | up(&pdev->modlock); | 1183 | up(&pdev->modlock); |
1095 | Trace(TRACE_OPEN, "<< video_open() returns 0.\n"); | 1184 | PWC_DEBUG_OPEN("<< video_open() returns 0.\n"); |
1096 | return 0; | 1185 | return 0; |
1097 | } | 1186 | } |
1098 | 1187 | ||
@@ -1103,35 +1192,23 @@ static int pwc_video_close(struct inode *inode, struct file *file) | |||
1103 | struct pwc_device *pdev; | 1192 | struct pwc_device *pdev; |
1104 | int i; | 1193 | int i; |
1105 | 1194 | ||
1106 | Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev); | 1195 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); |
1107 | 1196 | ||
1108 | pdev = (struct pwc_device *)vdev->priv; | 1197 | pdev = (struct pwc_device *)vdev->priv; |
1109 | if (pdev->vopen == 0) | 1198 | if (pdev->vopen == 0) |
1110 | Info("video_close() called on closed device?\n"); | 1199 | PWC_DEBUG_MODULE("video_close() called on closed device?\n"); |
1111 | 1200 | ||
1112 | /* Dump statistics, but only if a reasonable amount of frames were | 1201 | /* Dump statistics, but only if a reasonable amount of frames were |
1113 | processed (to prevent endless log-entries in case of snap-shot | 1202 | processed (to prevent endless log-entries in case of snap-shot |
1114 | programs) | 1203 | programs) |
1115 | */ | 1204 | */ |
1116 | if (pdev->vframe_count > 20) | 1205 | if (pdev->vframe_count > 20) |
1117 | Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error); | 1206 | PWC_DEBUG_MODULE("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error); |
1118 | 1207 | ||
1119 | switch (pdev->type) | 1208 | if (DEVICE_USE_CODEC1(pdev->type)) |
1120 | { | 1209 | pwc_dec1_exit(); |
1121 | case 675: | 1210 | else |
1122 | case 680: | 1211 | pwc_dec23_exit(); |
1123 | case 690: | ||
1124 | case 720: | ||
1125 | case 730: | ||
1126 | case 740: | ||
1127 | case 750: | ||
1128 | /* pwc_dec23_exit(); *//* Timon & Kiara */ | ||
1129 | break; | ||
1130 | case 645: | ||
1131 | case 646: | ||
1132 | /* pwc_dec1_exit(); */ | ||
1133 | break; | ||
1134 | } | ||
1135 | 1212 | ||
1136 | pwc_isoc_cleanup(pdev); | 1213 | pwc_isoc_cleanup(pdev); |
1137 | pwc_free_buffers(pdev); | 1214 | pwc_free_buffers(pdev); |
@@ -1140,15 +1217,15 @@ static int pwc_video_close(struct inode *inode, struct file *file) | |||
1140 | if (pdev->error_status != EPIPE) { | 1217 | if (pdev->error_status != EPIPE) { |
1141 | /* Turn LEDs off */ | 1218 | /* Turn LEDs off */ |
1142 | if (pwc_set_leds(pdev, 0, 0) < 0) | 1219 | if (pwc_set_leds(pdev, 0, 0) < 0) |
1143 | Info("Failed to set LED on/off time.\n"); | 1220 | PWC_DEBUG_MODULE("Failed to set LED on/off time.\n"); |
1144 | if (power_save) { | 1221 | if (power_save) { |
1145 | i = pwc_camera_power(pdev, 0); | 1222 | i = pwc_camera_power(pdev, 0); |
1146 | if (i < 0) | 1223 | if (i < 0) |
1147 | Err("Failed to power down camera (%d)\n", i); | 1224 | PWC_ERROR("Failed to power down camera (%d)\n", i); |
1148 | } | 1225 | } |
1149 | } | 1226 | } |
1150 | pdev->vopen = 0; | 1227 | pdev->vopen--; |
1151 | Trace(TRACE_OPEN, "<< video_close()\n"); | 1228 | PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); |
1152 | return 0; | 1229 | return 0; |
1153 | } | 1230 | } |
1154 | 1231 | ||
@@ -1164,7 +1241,7 @@ static int pwc_video_close(struct inode *inode, struct file *file) | |||
1164 | device is tricky anyhow. | 1241 | device is tricky anyhow. |
1165 | */ | 1242 | */ |
1166 | 1243 | ||
1167 | static ssize_t pwc_video_read(struct file *file, char __user * buf, | 1244 | static ssize_t pwc_video_read(struct file *file, char __user *buf, |
1168 | size_t count, loff_t *ppos) | 1245 | size_t count, loff_t *ppos) |
1169 | { | 1246 | { |
1170 | struct video_device *vdev = file->private_data; | 1247 | struct video_device *vdev = file->private_data; |
@@ -1172,8 +1249,10 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf, | |||
1172 | int noblock = file->f_flags & O_NONBLOCK; | 1249 | int noblock = file->f_flags & O_NONBLOCK; |
1173 | DECLARE_WAITQUEUE(wait, current); | 1250 | DECLARE_WAITQUEUE(wait, current); |
1174 | int bytes_to_read; | 1251 | int bytes_to_read; |
1252 | void *image_buffer_addr; | ||
1175 | 1253 | ||
1176 | Trace(TRACE_READ, "video_read(0x%p, %p, %zu) called.\n", vdev, buf, count); | 1254 | PWC_DEBUG_READ("pwc_video_read(vdev=0x%p, buf=%p, count=%zd) called.\n", |
1255 | vdev, buf, count); | ||
1177 | if (vdev == NULL) | 1256 | if (vdev == NULL) |
1178 | return -EFAULT; | 1257 | return -EFAULT; |
1179 | pdev = vdev->priv; | 1258 | pdev = vdev->priv; |
@@ -1214,16 +1293,19 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf, | |||
1214 | return -EFAULT; | 1293 | return -EFAULT; |
1215 | } | 1294 | } |
1216 | 1295 | ||
1217 | Trace(TRACE_READ, "Copying data to user space.\n"); | 1296 | PWC_DEBUG_READ("Copying data to user space.\n"); |
1218 | if (pdev->vpalette == VIDEO_PALETTE_RAW) | 1297 | if (pdev->vpalette == VIDEO_PALETTE_RAW) |
1219 | bytes_to_read = pdev->frame_size; | 1298 | bytes_to_read = pdev->frame_size + sizeof(struct pwc_raw_frame); |
1220 | else | 1299 | else |
1221 | bytes_to_read = pdev->view.size; | 1300 | bytes_to_read = pdev->view.size; |
1222 | 1301 | ||
1223 | /* copy bytes to user space; we allow for partial reads */ | 1302 | /* copy bytes to user space; we allow for partial reads */ |
1224 | if (count + pdev->image_read_pos > bytes_to_read) | 1303 | if (count + pdev->image_read_pos > bytes_to_read) |
1225 | count = bytes_to_read - pdev->image_read_pos; | 1304 | count = bytes_to_read - pdev->image_read_pos; |
1226 | if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count)) | 1305 | image_buffer_addr = pdev->image_data; |
1306 | image_buffer_addr += pdev->images[pdev->fill_image].offset; | ||
1307 | image_buffer_addr += pdev->image_read_pos; | ||
1308 | if (copy_to_user(buf, image_buffer_addr, count)) | ||
1227 | return -EFAULT; | 1309 | return -EFAULT; |
1228 | pdev->image_read_pos += count; | 1310 | pdev->image_read_pos += count; |
1229 | if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */ | 1311 | if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */ |
@@ -1253,370 +1335,56 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) | |||
1253 | return 0; | 1335 | return 0; |
1254 | } | 1336 | } |
1255 | 1337 | ||
1256 | static int pwc_video_do_ioctl(struct inode *inode, struct file *file, | ||
1257 | unsigned int cmd, void *arg) | ||
1258 | { | ||
1259 | struct video_device *vdev = file->private_data; | ||
1260 | struct pwc_device *pdev; | ||
1261 | DECLARE_WAITQUEUE(wait, current); | ||
1262 | |||
1263 | if (vdev == NULL) | ||
1264 | return -EFAULT; | ||
1265 | pdev = vdev->priv; | ||
1266 | if (pdev == NULL) | ||
1267 | return -EFAULT; | ||
1268 | |||
1269 | switch (cmd) { | ||
1270 | /* Query cabapilities */ | ||
1271 | case VIDIOCGCAP: | ||
1272 | { | ||
1273 | struct video_capability *caps = arg; | ||
1274 | |||
1275 | strcpy(caps->name, vdev->name); | ||
1276 | caps->type = VID_TYPE_CAPTURE; | ||
1277 | caps->channels = 1; | ||
1278 | caps->audios = 1; | ||
1279 | caps->minwidth = pdev->view_min.x; | ||
1280 | caps->minheight = pdev->view_min.y; | ||
1281 | caps->maxwidth = pdev->view_max.x; | ||
1282 | caps->maxheight = pdev->view_max.y; | ||
1283 | break; | ||
1284 | } | ||
1285 | |||
1286 | /* Channel functions (simulate 1 channel) */ | ||
1287 | case VIDIOCGCHAN: | ||
1288 | { | ||
1289 | struct video_channel *v = arg; | ||
1290 | |||
1291 | if (v->channel != 0) | ||
1292 | return -EINVAL; | ||
1293 | v->flags = 0; | ||
1294 | v->tuners = 0; | ||
1295 | v->type = VIDEO_TYPE_CAMERA; | ||
1296 | strcpy(v->name, "Webcam"); | ||
1297 | return 0; | ||
1298 | } | ||
1299 | |||
1300 | case VIDIOCSCHAN: | ||
1301 | { | ||
1302 | /* The spec says the argument is an integer, but | ||
1303 | the bttv driver uses a video_channel arg, which | ||
1304 | makes sense becasue it also has the norm flag. | ||
1305 | */ | ||
1306 | struct video_channel *v = arg; | ||
1307 | if (v->channel != 0) | ||
1308 | return -EINVAL; | ||
1309 | return 0; | ||
1310 | } | ||
1311 | |||
1312 | |||
1313 | /* Picture functions; contrast etc. */ | ||
1314 | case VIDIOCGPICT: | ||
1315 | { | ||
1316 | struct video_picture *p = arg; | ||
1317 | int val; | ||
1318 | |||
1319 | val = pwc_get_brightness(pdev); | ||
1320 | if (val >= 0) | ||
1321 | p->brightness = val; | ||
1322 | else | ||
1323 | p->brightness = 0xffff; | ||
1324 | val = pwc_get_contrast(pdev); | ||
1325 | if (val >= 0) | ||
1326 | p->contrast = val; | ||
1327 | else | ||
1328 | p->contrast = 0xffff; | ||
1329 | /* Gamma, Whiteness, what's the difference? :) */ | ||
1330 | val = pwc_get_gamma(pdev); | ||
1331 | if (val >= 0) | ||
1332 | p->whiteness = val; | ||
1333 | else | ||
1334 | p->whiteness = 0xffff; | ||
1335 | val = pwc_get_saturation(pdev); | ||
1336 | if (val >= 0) | ||
1337 | p->colour = val; | ||
1338 | else | ||
1339 | p->colour = 0xffff; | ||
1340 | p->depth = 24; | ||
1341 | p->palette = pdev->vpalette; | ||
1342 | p->hue = 0xFFFF; /* N/A */ | ||
1343 | break; | ||
1344 | } | ||
1345 | |||
1346 | case VIDIOCSPICT: | ||
1347 | { | ||
1348 | struct video_picture *p = arg; | ||
1349 | /* | ||
1350 | * FIXME: Suppose we are mid read | ||
1351 | ANSWER: No problem: the firmware of the camera | ||
1352 | can handle brightness/contrast/etc | ||
1353 | changes at _any_ time, and the palette | ||
1354 | is used exactly once in the uncompress | ||
1355 | routine. | ||
1356 | */ | ||
1357 | pwc_set_brightness(pdev, p->brightness); | ||
1358 | pwc_set_contrast(pdev, p->contrast); | ||
1359 | pwc_set_gamma(pdev, p->whiteness); | ||
1360 | pwc_set_saturation(pdev, p->colour); | ||
1361 | if (p->palette && p->palette != pdev->vpalette) { | ||
1362 | switch (p->palette) { | ||
1363 | case VIDEO_PALETTE_YUV420P: | ||
1364 | case VIDEO_PALETTE_RAW: | ||
1365 | pdev->vpalette = p->palette; | ||
1366 | return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); | ||
1367 | break; | ||
1368 | default: | ||
1369 | return -EINVAL; | ||
1370 | break; | ||
1371 | } | ||
1372 | } | ||
1373 | break; | ||
1374 | } | ||
1375 | |||
1376 | /* Window/size parameters */ | ||
1377 | case VIDIOCGWIN: | ||
1378 | { | ||
1379 | struct video_window *vw = arg; | ||
1380 | |||
1381 | vw->x = 0; | ||
1382 | vw->y = 0; | ||
1383 | vw->width = pdev->view.x; | ||
1384 | vw->height = pdev->view.y; | ||
1385 | vw->chromakey = 0; | ||
1386 | vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | | ||
1387 | (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0); | ||
1388 | break; | ||
1389 | } | ||
1390 | |||
1391 | case VIDIOCSWIN: | ||
1392 | { | ||
1393 | struct video_window *vw = arg; | ||
1394 | int fps, snapshot, ret; | ||
1395 | |||
1396 | fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; | ||
1397 | snapshot = vw->flags & PWC_FPS_SNAPSHOT; | ||
1398 | if (fps == 0) | ||
1399 | fps = pdev->vframes; | ||
1400 | if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot) | ||
1401 | return 0; | ||
1402 | ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot); | ||
1403 | if (ret) | ||
1404 | return ret; | ||
1405 | break; | ||
1406 | } | ||
1407 | |||
1408 | /* We don't have overlay support (yet) */ | ||
1409 | case VIDIOCGFBUF: | ||
1410 | { | ||
1411 | struct video_buffer *vb = arg; | ||
1412 | |||
1413 | memset(vb,0,sizeof(*vb)); | ||
1414 | break; | ||
1415 | } | ||
1416 | |||
1417 | /* mmap() functions */ | ||
1418 | case VIDIOCGMBUF: | ||
1419 | { | ||
1420 | /* Tell the user program how much memory is needed for a mmap() */ | ||
1421 | struct video_mbuf *vm = arg; | ||
1422 | int i; | ||
1423 | |||
1424 | memset(vm, 0, sizeof(*vm)); | ||
1425 | vm->size = default_mbufs * pdev->len_per_image; | ||
1426 | vm->frames = default_mbufs; /* double buffering should be enough for most applications */ | ||
1427 | for (i = 0; i < default_mbufs; i++) | ||
1428 | vm->offsets[i] = i * pdev->len_per_image; | ||
1429 | break; | ||
1430 | } | ||
1431 | |||
1432 | case VIDIOCMCAPTURE: | ||
1433 | { | ||
1434 | /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */ | ||
1435 | struct video_mmap *vm = arg; | ||
1436 | |||
1437 | Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format); | ||
1438 | if (vm->frame < 0 || vm->frame >= default_mbufs) | ||
1439 | return -EINVAL; | ||
1440 | |||
1441 | /* xawtv is nasty. It probes the available palettes | ||
1442 | by setting a very small image size and trying | ||
1443 | various palettes... The driver doesn't support | ||
1444 | such small images, so I'm working around it. | ||
1445 | */ | ||
1446 | if (vm->format) | ||
1447 | { | ||
1448 | switch (vm->format) | ||
1449 | { | ||
1450 | case VIDEO_PALETTE_YUV420P: | ||
1451 | case VIDEO_PALETTE_RAW: | ||
1452 | break; | ||
1453 | default: | ||
1454 | return -EINVAL; | ||
1455 | break; | ||
1456 | } | ||
1457 | } | ||
1458 | |||
1459 | if ((vm->width != pdev->view.x || vm->height != pdev->view.y) && | ||
1460 | (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) { | ||
1461 | int ret; | ||
1462 | |||
1463 | Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n"); | ||
1464 | ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot); | ||
1465 | if (ret) | ||
1466 | return ret; | ||
1467 | } /* ... size mismatch */ | ||
1468 | |||
1469 | /* FIXME: should we lock here? */ | ||
1470 | if (pdev->image_used[vm->frame]) | ||
1471 | return -EBUSY; /* buffer wasn't available. Bummer */ | ||
1472 | pdev->image_used[vm->frame] = 1; | ||
1473 | |||
1474 | /* Okay, we're done here. In the SYNC call we wait until a | ||
1475 | frame comes available, then expand image into the given | ||
1476 | buffer. | ||
1477 | In contrast to the CPiA cam the Philips cams deliver a | ||
1478 | constant stream, almost like a grabber card. Also, | ||
1479 | we have separate buffers for the rawdata and the image, | ||
1480 | meaning we can nearly always expand into the requested buffer. | ||
1481 | */ | ||
1482 | Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n"); | ||
1483 | break; | ||
1484 | } | ||
1485 | |||
1486 | case VIDIOCSYNC: | ||
1487 | { | ||
1488 | /* The doc says: "Whenever a buffer is used it should | ||
1489 | call VIDIOCSYNC to free this frame up and continue." | ||
1490 | |||
1491 | The only odd thing about this whole procedure is | ||
1492 | that MCAPTURE flags the buffer as "in use", and | ||
1493 | SYNC immediately unmarks it, while it isn't | ||
1494 | after SYNC that you know that the buffer actually | ||
1495 | got filled! So you better not start a CAPTURE in | ||
1496 | the same frame immediately (use double buffering). | ||
1497 | This is not a problem for this cam, since it has | ||
1498 | extra intermediate buffers, but a hardware | ||
1499 | grabber card will then overwrite the buffer | ||
1500 | you're working on. | ||
1501 | */ | ||
1502 | int *mbuf = arg; | ||
1503 | int ret; | ||
1504 | |||
1505 | Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", *mbuf); | ||
1506 | |||
1507 | /* bounds check */ | ||
1508 | if (*mbuf < 0 || *mbuf >= default_mbufs) | ||
1509 | return -EINVAL; | ||
1510 | /* check if this buffer was requested anyway */ | ||
1511 | if (pdev->image_used[*mbuf] == 0) | ||
1512 | return -EINVAL; | ||
1513 | |||
1514 | /* Add ourselves to the frame wait-queue. | ||
1515 | |||
1516 | FIXME: needs auditing for safety. | ||
1517 | QUESTION: In what respect? I think that using the | ||
1518 | frameq is safe now. | ||
1519 | */ | ||
1520 | add_wait_queue(&pdev->frameq, &wait); | ||
1521 | while (pdev->full_frames == NULL) { | ||
1522 | if (pdev->error_status) { | ||
1523 | remove_wait_queue(&pdev->frameq, &wait); | ||
1524 | set_current_state(TASK_RUNNING); | ||
1525 | return -pdev->error_status; | ||
1526 | } | ||
1527 | |||
1528 | if (signal_pending(current)) { | ||
1529 | remove_wait_queue(&pdev->frameq, &wait); | ||
1530 | set_current_state(TASK_RUNNING); | ||
1531 | return -ERESTARTSYS; | ||
1532 | } | ||
1533 | schedule(); | ||
1534 | set_current_state(TASK_INTERRUPTIBLE); | ||
1535 | } | ||
1536 | remove_wait_queue(&pdev->frameq, &wait); | ||
1537 | set_current_state(TASK_RUNNING); | ||
1538 | |||
1539 | /* The frame is ready. Expand in the image buffer | ||
1540 | requested by the user. I don't care if you | ||
1541 | mmap() 5 buffers and request data in this order: | ||
1542 | buffer 4 2 3 0 1 2 3 0 4 3 1 . . . | ||
1543 | Grabber hardware may not be so forgiving. | ||
1544 | */ | ||
1545 | Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n"); | ||
1546 | pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */ | ||
1547 | /* Decompress, etc */ | ||
1548 | ret = pwc_handle_frame(pdev); | ||
1549 | pdev->image_used[*mbuf] = 0; | ||
1550 | if (ret) | ||
1551 | return -EFAULT; | ||
1552 | break; | ||
1553 | } | ||
1554 | |||
1555 | case VIDIOCGAUDIO: | ||
1556 | { | ||
1557 | struct video_audio *v = arg; | ||
1558 | |||
1559 | strcpy(v->name, "Microphone"); | ||
1560 | v->audio = -1; /* unknown audio minor */ | ||
1561 | v->flags = 0; | ||
1562 | v->mode = VIDEO_SOUND_MONO; | ||
1563 | v->volume = 0; | ||
1564 | v->bass = 0; | ||
1565 | v->treble = 0; | ||
1566 | v->balance = 0x8000; | ||
1567 | v->step = 1; | ||
1568 | break; | ||
1569 | } | ||
1570 | |||
1571 | case VIDIOCSAUDIO: | ||
1572 | { | ||
1573 | /* Dummy: nothing can be set */ | ||
1574 | break; | ||
1575 | } | ||
1576 | |||
1577 | case VIDIOCGUNIT: | ||
1578 | { | ||
1579 | struct video_unit *vu = arg; | ||
1580 | |||
1581 | vu->video = pdev->vdev->minor & 0x3F; | ||
1582 | vu->audio = -1; /* not known yet */ | ||
1583 | vu->vbi = -1; | ||
1584 | vu->radio = -1; | ||
1585 | vu->teletext = -1; | ||
1586 | break; | ||
1587 | } | ||
1588 | default: | ||
1589 | return pwc_ioctl(pdev, cmd, arg); | ||
1590 | } /* ..switch */ | ||
1591 | return 0; | ||
1592 | } | ||
1593 | |||
1594 | static int pwc_video_ioctl(struct inode *inode, struct file *file, | 1338 | static int pwc_video_ioctl(struct inode *inode, struct file *file, |
1595 | unsigned int cmd, unsigned long arg) | 1339 | unsigned int cmd, unsigned long arg) |
1596 | { | 1340 | { |
1597 | return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl); | 1341 | return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl); |
1598 | } | 1342 | } |
1599 | 1343 | ||
1600 | |||
1601 | static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) | 1344 | static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) |
1602 | { | 1345 | { |
1603 | struct video_device *vdev = file->private_data; | 1346 | struct video_device *vdev = file->private_data; |
1604 | struct pwc_device *pdev; | 1347 | struct pwc_device *pdev; |
1605 | unsigned long start = vma->vm_start; | 1348 | unsigned long start; |
1606 | unsigned long size = vma->vm_end-vma->vm_start; | 1349 | unsigned long size; |
1607 | unsigned long page, pos; | 1350 | unsigned long page, pos = 0; |
1351 | int index; | ||
1608 | 1352 | ||
1609 | Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size); | 1353 | PWC_DEBUG_MEMORY(">> %s\n", __FUNCTION__); |
1610 | pdev = vdev->priv; | 1354 | pdev = vdev->priv; |
1355 | size = vma->vm_end - vma->vm_start; | ||
1356 | start = vma->vm_start; | ||
1611 | 1357 | ||
1612 | vma->vm_flags |= VM_IO; | 1358 | /* Find the idx buffer for this mapping */ |
1359 | for (index = 0; index < pwc_mbufs; index++) { | ||
1360 | pos = pdev->images[index].offset; | ||
1361 | if ((pos>>PAGE_SHIFT) == vma->vm_pgoff) | ||
1362 | break; | ||
1363 | } | ||
1364 | if (index == MAX_IMAGES) | ||
1365 | return -EINVAL; | ||
1366 | if (index == 0) { | ||
1367 | /* | ||
1368 | * Special case for v4l1. In v4l1, we map only one big buffer, | ||
1369 | * but in v4l2 each buffer is mapped | ||
1370 | */ | ||
1371 | unsigned long total_size; | ||
1372 | total_size = pwc_mbufs * pdev->len_per_image; | ||
1373 | if (size != pdev->len_per_image && size != total_size) { | ||
1374 | PWC_ERROR("Wrong size (%lu) needed to be len_per_image=%d or total_size=%lu\n", | ||
1375 | size, pdev->len_per_image, total_size); | ||
1376 | return -EINVAL; | ||
1377 | } | ||
1378 | } else if (size > pdev->len_per_image) | ||
1379 | return -EINVAL; | ||
1613 | 1380 | ||
1614 | pos = (unsigned long)pdev->image_data; | 1381 | vma->vm_flags |= VM_IO; /* from 2.6.9-acX */ |
1382 | |||
1383 | pos += (unsigned long)pdev->image_data; | ||
1615 | while (size > 0) { | 1384 | while (size > 0) { |
1616 | page = vmalloc_to_pfn((void *)pos); | 1385 | page = vmalloc_to_pfn((void *)pos); |
1617 | if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) | 1386 | if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) |
1618 | return -EAGAIN; | 1387 | return -EAGAIN; |
1619 | |||
1620 | start += PAGE_SIZE; | 1388 | start += PAGE_SIZE; |
1621 | pos += PAGE_SIZE; | 1389 | pos += PAGE_SIZE; |
1622 | if (size > PAGE_SIZE) | 1390 | if (size > PAGE_SIZE) |
@@ -1624,7 +1392,6 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) | |||
1624 | else | 1392 | else |
1625 | size = 0; | 1393 | size = 0; |
1626 | } | 1394 | } |
1627 | |||
1628 | return 0; | 1395 | return 0; |
1629 | } | 1396 | } |
1630 | 1397 | ||
@@ -1645,10 +1412,12 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1645 | int video_nr = -1; /* default: use next available device */ | 1412 | int video_nr = -1; /* default: use next available device */ |
1646 | char serial_number[30], *name; | 1413 | char serial_number[30], *name; |
1647 | 1414 | ||
1415 | vendor_id = le16_to_cpu(udev->descriptor.idVendor); | ||
1416 | product_id = le16_to_cpu(udev->descriptor.idProduct); | ||
1417 | |||
1648 | /* Check if we can handle this device */ | 1418 | /* Check if we can handle this device */ |
1649 | Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", | 1419 | PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n", |
1650 | le16_to_cpu(udev->descriptor.idVendor), | 1420 | vendor_id, product_id, |
1651 | le16_to_cpu(udev->descriptor.idProduct), | ||
1652 | intf->altsetting->desc.bInterfaceNumber); | 1421 | intf->altsetting->desc.bInterfaceNumber); |
1653 | 1422 | ||
1654 | /* the interfaces are probed one by one. We are only interested in the | 1423 | /* the interfaces are probed one by one. We are only interested in the |
@@ -1658,61 +1427,63 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1658 | if (intf->altsetting->desc.bInterfaceNumber > 0) | 1427 | if (intf->altsetting->desc.bInterfaceNumber > 0) |
1659 | return -ENODEV; | 1428 | return -ENODEV; |
1660 | 1429 | ||
1661 | vendor_id = le16_to_cpu(udev->descriptor.idVendor); | ||
1662 | product_id = le16_to_cpu(udev->descriptor.idProduct); | ||
1663 | |||
1664 | if (vendor_id == 0x0471) { | 1430 | if (vendor_id == 0x0471) { |
1665 | switch (product_id) { | 1431 | switch (product_id) { |
1666 | case 0x0302: | 1432 | case 0x0302: |
1667 | Info("Philips PCA645VC USB webcam detected.\n"); | 1433 | PWC_INFO("Philips PCA645VC USB webcam detected.\n"); |
1668 | name = "Philips 645 webcam"; | 1434 | name = "Philips 645 webcam"; |
1669 | type_id = 645; | 1435 | type_id = 645; |
1670 | break; | 1436 | break; |
1671 | case 0x0303: | 1437 | case 0x0303: |
1672 | Info("Philips PCA646VC USB webcam detected.\n"); | 1438 | PWC_INFO("Philips PCA646VC USB webcam detected.\n"); |
1673 | name = "Philips 646 webcam"; | 1439 | name = "Philips 646 webcam"; |
1674 | type_id = 646; | 1440 | type_id = 646; |
1675 | break; | 1441 | break; |
1676 | case 0x0304: | 1442 | case 0x0304: |
1677 | Info("Askey VC010 type 2 USB webcam detected.\n"); | 1443 | PWC_INFO("Askey VC010 type 2 USB webcam detected.\n"); |
1678 | name = "Askey VC010 webcam"; | 1444 | name = "Askey VC010 webcam"; |
1679 | type_id = 646; | 1445 | type_id = 646; |
1680 | break; | 1446 | break; |
1681 | case 0x0307: | 1447 | case 0x0307: |
1682 | Info("Philips PCVC675K (Vesta) USB webcam detected.\n"); | 1448 | PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n"); |
1683 | name = "Philips 675 webcam"; | 1449 | name = "Philips 675 webcam"; |
1684 | type_id = 675; | 1450 | type_id = 675; |
1685 | break; | 1451 | break; |
1686 | case 0x0308: | 1452 | case 0x0308: |
1687 | Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n"); | 1453 | PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n"); |
1688 | name = "Philips 680 webcam"; | 1454 | name = "Philips 680 webcam"; |
1689 | type_id = 680; | 1455 | type_id = 680; |
1690 | break; | 1456 | break; |
1691 | case 0x030C: | 1457 | case 0x030C: |
1692 | Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n"); | 1458 | PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n"); |
1693 | name = "Philips 690 webcam"; | 1459 | name = "Philips 690 webcam"; |
1694 | type_id = 690; | 1460 | type_id = 690; |
1695 | break; | 1461 | break; |
1696 | case 0x0310: | 1462 | case 0x0310: |
1697 | Info("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n"); | 1463 | PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n"); |
1698 | name = "Philips 730 webcam"; | 1464 | name = "Philips 730 webcam"; |
1699 | type_id = 730; | 1465 | type_id = 730; |
1700 | break; | 1466 | break; |
1701 | case 0x0311: | 1467 | case 0x0311: |
1702 | Info("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n"); | 1468 | PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n"); |
1703 | name = "Philips 740 webcam"; | 1469 | name = "Philips 740 webcam"; |
1704 | type_id = 740; | 1470 | type_id = 740; |
1705 | break; | 1471 | break; |
1706 | case 0x0312: | 1472 | case 0x0312: |
1707 | Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n"); | 1473 | PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n"); |
1708 | name = "Philips 750 webcam"; | 1474 | name = "Philips 750 webcam"; |
1709 | type_id = 750; | 1475 | type_id = 750; |
1710 | break; | 1476 | break; |
1711 | case 0x0313: | 1477 | case 0x0313: |
1712 | Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n"); | 1478 | PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n"); |
1713 | name = "Philips 720K/40 webcam"; | 1479 | name = "Philips 720K/40 webcam"; |
1714 | type_id = 720; | 1480 | type_id = 720; |
1715 | break; | 1481 | break; |
1482 | case 0x0329: | ||
1483 | PWC_INFO("Philips SPC 900NC USB webcam detected.\n"); | ||
1484 | name = "Philips SPC 900NC webcam"; | ||
1485 | type_id = 720; | ||
1486 | break; | ||
1716 | default: | 1487 | default: |
1717 | return -ENODEV; | 1488 | return -ENODEV; |
1718 | break; | 1489 | break; |
@@ -1721,7 +1492,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1721 | else if (vendor_id == 0x069A) { | 1492 | else if (vendor_id == 0x069A) { |
1722 | switch(product_id) { | 1493 | switch(product_id) { |
1723 | case 0x0001: | 1494 | case 0x0001: |
1724 | Info("Askey VC010 type 1 USB webcam detected.\n"); | 1495 | PWC_INFO("Askey VC010 type 1 USB webcam detected.\n"); |
1725 | name = "Askey VC010 webcam"; | 1496 | name = "Askey VC010 webcam"; |
1726 | type_id = 645; | 1497 | type_id = 645; |
1727 | break; | 1498 | break; |
@@ -1733,32 +1504,33 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1733 | else if (vendor_id == 0x046d) { | 1504 | else if (vendor_id == 0x046d) { |
1734 | switch(product_id) { | 1505 | switch(product_id) { |
1735 | case 0x08b0: | 1506 | case 0x08b0: |
1736 | Info("Logitech QuickCam Pro 3000 USB webcam detected.\n"); | 1507 | PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n"); |
1737 | name = "Logitech QuickCam Pro 3000"; | 1508 | name = "Logitech QuickCam Pro 3000"; |
1738 | type_id = 740; /* CCD sensor */ | 1509 | type_id = 740; /* CCD sensor */ |
1739 | break; | 1510 | break; |
1740 | case 0x08b1: | 1511 | case 0x08b1: |
1741 | Info("Logitech QuickCam Notebook Pro USB webcam detected.\n"); | 1512 | PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n"); |
1742 | name = "Logitech QuickCam Notebook Pro"; | 1513 | name = "Logitech QuickCam Notebook Pro"; |
1743 | type_id = 740; /* CCD sensor */ | 1514 | type_id = 740; /* CCD sensor */ |
1744 | break; | 1515 | break; |
1745 | case 0x08b2: | 1516 | case 0x08b2: |
1746 | Info("Logitech QuickCam 4000 Pro USB webcam detected.\n"); | 1517 | PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n"); |
1747 | name = "Logitech QuickCam Pro 4000"; | 1518 | name = "Logitech QuickCam Pro 4000"; |
1748 | type_id = 740; /* CCD sensor */ | 1519 | type_id = 740; /* CCD sensor */ |
1749 | break; | 1520 | break; |
1750 | case 0x08b3: | 1521 | case 0x08b3: |
1751 | Info("Logitech QuickCam Zoom USB webcam detected.\n"); | 1522 | PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n"); |
1752 | name = "Logitech QuickCam Zoom"; | 1523 | name = "Logitech QuickCam Zoom"; |
1753 | type_id = 740; /* CCD sensor */ | 1524 | type_id = 740; /* CCD sensor */ |
1754 | break; | 1525 | break; |
1755 | case 0x08B4: | 1526 | case 0x08B4: |
1756 | Info("Logitech QuickCam Zoom (new model) USB webcam detected.\n"); | 1527 | PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n"); |
1757 | name = "Logitech QuickCam Zoom"; | 1528 | name = "Logitech QuickCam Zoom"; |
1758 | type_id = 740; /* CCD sensor */ | 1529 | type_id = 740; /* CCD sensor */ |
1530 | power_save = 1; | ||
1759 | break; | 1531 | break; |
1760 | case 0x08b5: | 1532 | case 0x08b5: |
1761 | Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n"); | 1533 | PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n"); |
1762 | name = "Logitech QuickCam Orbit"; | 1534 | name = "Logitech QuickCam Orbit"; |
1763 | type_id = 740; /* CCD sensor */ | 1535 | type_id = 740; /* CCD sensor */ |
1764 | features |= FEATURE_MOTOR_PANTILT; | 1536 | features |= FEATURE_MOTOR_PANTILT; |
@@ -1766,7 +1538,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1766 | case 0x08b6: | 1538 | case 0x08b6: |
1767 | case 0x08b7: | 1539 | case 0x08b7: |
1768 | case 0x08b8: | 1540 | case 0x08b8: |
1769 | Info("Logitech QuickCam detected (reserved ID).\n"); | 1541 | PWC_INFO("Logitech QuickCam detected (reserved ID).\n"); |
1770 | name = "Logitech QuickCam (res.)"; | 1542 | name = "Logitech QuickCam (res.)"; |
1771 | type_id = 730; /* Assuming CMOS */ | 1543 | type_id = 730; /* Assuming CMOS */ |
1772 | break; | 1544 | break; |
@@ -1782,15 +1554,20 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1782 | */ | 1554 | */ |
1783 | switch(product_id) { | 1555 | switch(product_id) { |
1784 | case 0x9000: | 1556 | case 0x9000: |
1785 | Info("Samsung MPC-C10 USB webcam detected.\n"); | 1557 | PWC_INFO("Samsung MPC-C10 USB webcam detected.\n"); |
1786 | name = "Samsung MPC-C10"; | 1558 | name = "Samsung MPC-C10"; |
1787 | type_id = 675; | 1559 | type_id = 675; |
1788 | break; | 1560 | break; |
1789 | case 0x9001: | 1561 | case 0x9001: |
1790 | Info("Samsung MPC-C30 USB webcam detected.\n"); | 1562 | PWC_INFO("Samsung MPC-C30 USB webcam detected.\n"); |
1791 | name = "Samsung MPC-C30"; | 1563 | name = "Samsung MPC-C30"; |
1792 | type_id = 675; | 1564 | type_id = 675; |
1793 | break; | 1565 | break; |
1566 | case 0x9002: | ||
1567 | PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n"); | ||
1568 | name = "Samsung MPC-C30"; | ||
1569 | type_id = 740; | ||
1570 | break; | ||
1794 | default: | 1571 | default: |
1795 | return -ENODEV; | 1572 | return -ENODEV; |
1796 | break; | 1573 | break; |
@@ -1799,12 +1576,12 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1799 | else if (vendor_id == 0x041e) { | 1576 | else if (vendor_id == 0x041e) { |
1800 | switch(product_id) { | 1577 | switch(product_id) { |
1801 | case 0x400c: | 1578 | case 0x400c: |
1802 | Info("Creative Labs Webcam 5 detected.\n"); | 1579 | PWC_INFO("Creative Labs Webcam 5 detected.\n"); |
1803 | name = "Creative Labs Webcam 5"; | 1580 | name = "Creative Labs Webcam 5"; |
1804 | type_id = 730; | 1581 | type_id = 730; |
1805 | break; | 1582 | break; |
1806 | case 0x4011: | 1583 | case 0x4011: |
1807 | Info("Creative Labs Webcam Pro Ex detected.\n"); | 1584 | PWC_INFO("Creative Labs Webcam Pro Ex detected.\n"); |
1808 | name = "Creative Labs Webcam Pro Ex"; | 1585 | name = "Creative Labs Webcam Pro Ex"; |
1809 | type_id = 740; | 1586 | type_id = 740; |
1810 | break; | 1587 | break; |
@@ -1816,7 +1593,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1816 | else if (vendor_id == 0x04cc) { | 1593 | else if (vendor_id == 0x04cc) { |
1817 | switch(product_id) { | 1594 | switch(product_id) { |
1818 | case 0x8116: | 1595 | case 0x8116: |
1819 | Info("Sotec Afina Eye USB webcam detected.\n"); | 1596 | PWC_INFO("Sotec Afina Eye USB webcam detected.\n"); |
1820 | name = "Sotec Afina Eye"; | 1597 | name = "Sotec Afina Eye"; |
1821 | type_id = 730; | 1598 | type_id = 730; |
1822 | break; | 1599 | break; |
@@ -1829,7 +1606,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1829 | switch(product_id) { | 1606 | switch(product_id) { |
1830 | case 0x8116: | 1607 | case 0x8116: |
1831 | /* This is essentially the same cam as the Sotec Afina Eye */ | 1608 | /* This is essentially the same cam as the Sotec Afina Eye */ |
1832 | Info("AME Co. Afina Eye USB webcam detected.\n"); | 1609 | PWC_INFO("AME Co. Afina Eye USB webcam detected.\n"); |
1833 | name = "AME Co. Afina Eye"; | 1610 | name = "AME Co. Afina Eye"; |
1834 | type_id = 750; | 1611 | type_id = 750; |
1835 | break; | 1612 | break; |
@@ -1842,12 +1619,12 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1842 | else if (vendor_id == 0x0d81) { | 1619 | else if (vendor_id == 0x0d81) { |
1843 | switch(product_id) { | 1620 | switch(product_id) { |
1844 | case 0x1900: | 1621 | case 0x1900: |
1845 | Info("Visionite VCS-UC300 USB webcam detected.\n"); | 1622 | PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n"); |
1846 | name = "Visionite VCS-UC300"; | 1623 | name = "Visionite VCS-UC300"; |
1847 | type_id = 740; /* CCD sensor */ | 1624 | type_id = 740; /* CCD sensor */ |
1848 | break; | 1625 | break; |
1849 | case 0x1910: | 1626 | case 0x1910: |
1850 | Info("Visionite VCS-UM100 USB webcam detected.\n"); | 1627 | PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n"); |
1851 | name = "Visionite VCS-UM100"; | 1628 | name = "Visionite VCS-UM100"; |
1852 | type_id = 730; /* CMOS sensor */ | 1629 | type_id = 730; /* CMOS sensor */ |
1853 | break; | 1630 | break; |
@@ -1861,15 +1638,15 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1861 | 1638 | ||
1862 | memset(serial_number, 0, 30); | 1639 | memset(serial_number, 0, 30); |
1863 | usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29); | 1640 | usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29); |
1864 | Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number); | 1641 | PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number); |
1865 | 1642 | ||
1866 | if (udev->descriptor.bNumConfigurations > 1) | 1643 | if (udev->descriptor.bNumConfigurations > 1) |
1867 | Info("Warning: more than 1 configuration available.\n"); | 1644 | PWC_WARNING("Warning: more than 1 configuration available.\n"); |
1868 | 1645 | ||
1869 | /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */ | 1646 | /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */ |
1870 | pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL); | 1647 | pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL); |
1871 | if (pdev == NULL) { | 1648 | if (pdev == NULL) { |
1872 | Err("Oops, could not allocate memory for pwc_device.\n"); | 1649 | PWC_ERROR("Oops, could not allocate memory for pwc_device.\n"); |
1873 | return -ENOMEM; | 1650 | return -ENOMEM; |
1874 | } | 1651 | } |
1875 | pdev->type = type_id; | 1652 | pdev->type = type_id; |
@@ -1900,17 +1677,18 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1900 | pdev->vdev = video_device_alloc(); | 1677 | pdev->vdev = video_device_alloc(); |
1901 | if (pdev->vdev == 0) | 1678 | if (pdev->vdev == 0) |
1902 | { | 1679 | { |
1903 | Err("Err, cannot allocate video_device struture. Failing probe."); | 1680 | PWC_ERROR("Err, cannot allocate video_device struture. Failing probe."); |
1904 | kfree(pdev); | 1681 | kfree(pdev); |
1905 | return -ENOMEM; | 1682 | return -ENOMEM; |
1906 | } | 1683 | } |
1907 | memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template)); | 1684 | memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template)); |
1685 | pdev->vdev->dev = &(udev->dev); | ||
1908 | strcpy(pdev->vdev->name, name); | 1686 | strcpy(pdev->vdev->name, name); |
1909 | pdev->vdev->owner = THIS_MODULE; | 1687 | pdev->vdev->owner = THIS_MODULE; |
1910 | video_set_drvdata(pdev->vdev, pdev); | 1688 | video_set_drvdata(pdev->vdev, pdev); |
1911 | 1689 | ||
1912 | pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); | 1690 | pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); |
1913 | Trace(TRACE_PROBE, "Release: %04x\n", pdev->release); | 1691 | PWC_DEBUG_PROBE("Release: %04x\n", pdev->release); |
1914 | 1692 | ||
1915 | /* Now search device_hint[] table for a match, so we can hint a node number. */ | 1693 | /* Now search device_hint[] table for a match, so we can hint a node number. */ |
1916 | for (hint = 0; hint < MAX_DEV_HINTS; hint++) { | 1694 | for (hint = 0; hint < MAX_DEV_HINTS; hint++) { |
@@ -1918,10 +1696,10 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1918 | (device_hint[hint].pdev == NULL)) { | 1696 | (device_hint[hint].pdev == NULL)) { |
1919 | /* so far, so good... try serial number */ | 1697 | /* so far, so good... try serial number */ |
1920 | if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) { | 1698 | if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) { |
1921 | /* match! */ | 1699 | /* match! */ |
1922 | video_nr = device_hint[hint].device_node; | 1700 | video_nr = device_hint[hint].device_node; |
1923 | Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr); | 1701 | PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr); |
1924 | break; | 1702 | break; |
1925 | } | 1703 | } |
1926 | } | 1704 | } |
1927 | } | 1705 | } |
@@ -1929,21 +1707,27 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1929 | pdev->vdev->release = video_device_release; | 1707 | pdev->vdev->release = video_device_release; |
1930 | i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr); | 1708 | i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr); |
1931 | if (i < 0) { | 1709 | if (i < 0) { |
1932 | Err("Failed to register as video device (%d).\n", i); | 1710 | PWC_ERROR("Failed to register as video device (%d).\n", i); |
1933 | video_device_release(pdev->vdev); /* Drip... drip... drip... */ | 1711 | video_device_release(pdev->vdev); /* Drip... drip... drip... */ |
1934 | kfree(pdev); /* Oops, no memory leaks please */ | 1712 | kfree(pdev); /* Oops, no memory leaks please */ |
1935 | return -EIO; | 1713 | return -EIO; |
1936 | } | 1714 | } |
1937 | else { | 1715 | else { |
1938 | Info("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F); | 1716 | PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F); |
1939 | } | 1717 | } |
1940 | 1718 | ||
1941 | /* occupy slot */ | 1719 | /* occupy slot */ |
1942 | if (hint < MAX_DEV_HINTS) | 1720 | if (hint < MAX_DEV_HINTS) |
1943 | device_hint[hint].pdev = pdev; | 1721 | device_hint[hint].pdev = pdev; |
1944 | 1722 | ||
1945 | Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev); | 1723 | PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev); |
1946 | usb_set_intfdata (intf, pdev); | 1724 | usb_set_intfdata (intf, pdev); |
1725 | pwc_create_sysfs_files(pdev->vdev); | ||
1726 | |||
1727 | /* Set the leds off */ | ||
1728 | pwc_set_leds(pdev, 0, 0); | ||
1729 | pwc_camera_power(pdev, 0); | ||
1730 | |||
1947 | return 0; | 1731 | return 0; |
1948 | } | 1732 | } |
1949 | 1733 | ||
@@ -1957,27 +1741,21 @@ static void usb_pwc_disconnect(struct usb_interface *intf) | |||
1957 | pdev = usb_get_intfdata (intf); | 1741 | pdev = usb_get_intfdata (intf); |
1958 | usb_set_intfdata (intf, NULL); | 1742 | usb_set_intfdata (intf, NULL); |
1959 | if (pdev == NULL) { | 1743 | if (pdev == NULL) { |
1960 | Err("pwc_disconnect() Called without private pointer.\n"); | 1744 | PWC_ERROR("pwc_disconnect() Called without private pointer.\n"); |
1961 | goto disconnect_out; | 1745 | goto disconnect_out; |
1962 | } | 1746 | } |
1963 | if (pdev->udev == NULL) { | 1747 | if (pdev->udev == NULL) { |
1964 | Err("pwc_disconnect() already called for %p\n", pdev); | 1748 | PWC_ERROR("pwc_disconnect() already called for %p\n", pdev); |
1965 | goto disconnect_out; | 1749 | goto disconnect_out; |
1966 | } | 1750 | } |
1967 | if (pdev->udev != interface_to_usbdev(intf)) { | 1751 | if (pdev->udev != interface_to_usbdev(intf)) { |
1968 | Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n"); | 1752 | PWC_ERROR("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n"); |
1969 | goto disconnect_out; | ||
1970 | } | ||
1971 | #ifdef PWC_MAGIC | ||
1972 | if (pdev->magic != PWC_MAGIC) { | ||
1973 | Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n"); | ||
1974 | goto disconnect_out; | 1753 | goto disconnect_out; |
1975 | } | 1754 | } |
1976 | #endif | ||
1977 | 1755 | ||
1978 | /* We got unplugged; this is signalled by an EPIPE error code */ | 1756 | /* We got unplugged; this is signalled by an EPIPE error code */ |
1979 | if (pdev->vopen) { | 1757 | if (pdev->vopen) { |
1980 | Info("Disconnected while webcam is in use!\n"); | 1758 | PWC_INFO("Disconnected while webcam is in use!\n"); |
1981 | pdev->error_status = EPIPE; | 1759 | pdev->error_status = EPIPE; |
1982 | } | 1760 | } |
1983 | 1761 | ||
@@ -1987,7 +1765,8 @@ static void usb_pwc_disconnect(struct usb_interface *intf) | |||
1987 | while (pdev->vopen) | 1765 | while (pdev->vopen) |
1988 | schedule(); | 1766 | schedule(); |
1989 | /* Device is now closed, so we can safely unregister it */ | 1767 | /* Device is now closed, so we can safely unregister it */ |
1990 | Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n"); | 1768 | PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); |
1769 | pwc_remove_sysfs_files(pdev->vdev); | ||
1991 | video_unregister_device(pdev->vdev); | 1770 | video_unregister_device(pdev->vdev); |
1992 | 1771 | ||
1993 | /* Free memory (don't set pdev to 0 just yet) */ | 1772 | /* Free memory (don't set pdev to 0 just yet) */ |
@@ -2021,58 +1800,64 @@ static int pwc_atoi(const char *s) | |||
2021 | * Initialization code & module stuff | 1800 | * Initialization code & module stuff |
2022 | */ | 1801 | */ |
2023 | 1802 | ||
2024 | static char size[10]; | 1803 | static char *size; |
2025 | static int fps = 0; | 1804 | static int fps; |
2026 | static int fbufs = 0; | 1805 | static int fbufs; |
2027 | static int mbufs = 0; | 1806 | static int mbufs; |
2028 | static int trace = -1; | ||
2029 | static int compression = -1; | 1807 | static int compression = -1; |
2030 | static int leds[2] = { -1, -1 }; | 1808 | static int leds[2] = { -1, -1 }; |
2031 | static char *dev_hint[MAX_DEV_HINTS] = { }; | 1809 | static int leds_nargs; |
1810 | static char *dev_hint[MAX_DEV_HINTS]; | ||
1811 | static int dev_hint_nargs; | ||
1812 | |||
1813 | module_param(size, charp, 0444); | ||
1814 | module_param(fps, int, 0444); | ||
1815 | module_param(fbufs, int, 0444); | ||
1816 | module_param(mbufs, int, 0444); | ||
1817 | #if CONFIG_PWC_DEBUG | ||
1818 | module_param_named(trace, pwc_trace, int, 0644); | ||
1819 | #endif | ||
1820 | module_param(power_save, int, 0444); | ||
1821 | module_param(compression, int, 0444); | ||
1822 | module_param_array(leds, int, &leds_nargs, 0444); | ||
1823 | module_param_array(dev_hint, charp, &dev_hint_nargs, 0444); | ||
2032 | 1824 | ||
2033 | module_param_string(size, size, sizeof(size), 0); | ||
2034 | MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga"); | 1825 | MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga"); |
2035 | module_param(fps, int, 0000); | ||
2036 | MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30"); | 1826 | MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30"); |
2037 | module_param(fbufs, int, 0000); | ||
2038 | MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve"); | 1827 | MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve"); |
2039 | module_param(mbufs, int, 0000); | ||
2040 | MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers"); | 1828 | MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers"); |
2041 | module_param(trace, int, 0000); | ||
2042 | MODULE_PARM_DESC(trace, "For debugging purposes"); | 1829 | MODULE_PARM_DESC(trace, "For debugging purposes"); |
2043 | module_param(power_save, bool, 0000); | ||
2044 | MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off"); | 1830 | MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off"); |
2045 | module_param(compression, int, 0000); | ||
2046 | MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); | 1831 | MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); |
2047 | module_param_array(leds, int, NULL, 0000); | ||
2048 | MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); | 1832 | MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); |
2049 | module_param_array(dev_hint, charp, NULL, 0000); | ||
2050 | MODULE_PARM_DESC(dev_hint, "Device node hints"); | 1833 | MODULE_PARM_DESC(dev_hint, "Device node hints"); |
2051 | 1834 | ||
2052 | MODULE_DESCRIPTION("Philips & OEM USB webcam driver"); | 1835 | MODULE_DESCRIPTION("Philips & OEM USB webcam driver"); |
2053 | MODULE_AUTHOR("Luc Saillard <luc@saillard.org>"); | 1836 | MODULE_AUTHOR("Luc Saillard <luc@saillard.org>"); |
2054 | MODULE_LICENSE("GPL"); | 1837 | MODULE_LICENSE("GPL"); |
1838 | MODULE_ALIAS("pwcx"); | ||
1839 | MODULE_VERSION( PWC_VERSION ); | ||
2055 | 1840 | ||
2056 | static int __init usb_pwc_init(void) | 1841 | static int __init usb_pwc_init(void) |
2057 | { | 1842 | { |
2058 | int i, sz; | 1843 | int i, sz; |
2059 | char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" }; | 1844 | char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" }; |
2060 | 1845 | ||
2061 | Info("Philips webcam module version " PWC_VERSION " loaded.\n"); | 1846 | PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n"); |
2062 | Info("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n"); | 1847 | PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n"); |
2063 | Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n"); | 1848 | PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n"); |
2064 | Info("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n"); | 1849 | PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n"); |
2065 | 1850 | ||
2066 | if (fps) { | 1851 | if (fps) { |
2067 | if (fps < 4 || fps > 30) { | 1852 | if (fps < 4 || fps > 30) { |
2068 | Err("Framerate out of bounds (4-30).\n"); | 1853 | PWC_ERROR("Framerate out of bounds (4-30).\n"); |
2069 | return -EINVAL; | 1854 | return -EINVAL; |
2070 | } | 1855 | } |
2071 | default_fps = fps; | 1856 | default_fps = fps; |
2072 | Info("Default framerate set to %d.\n", default_fps); | 1857 | PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps); |
2073 | } | 1858 | } |
2074 | 1859 | ||
2075 | if (size[0]) { | 1860 | if (size) { |
2076 | /* string; try matching with array */ | 1861 | /* string; try matching with array */ |
2077 | for (sz = 0; sz < PSZ_MAX; sz++) { | 1862 | for (sz = 0; sz < PSZ_MAX; sz++) { |
2078 | if (!strcmp(sizenames[sz], size)) { /* Found! */ | 1863 | if (!strcmp(sizenames[sz], size)) { /* Found! */ |
@@ -2081,41 +1866,42 @@ static int __init usb_pwc_init(void) | |||
2081 | } | 1866 | } |
2082 | } | 1867 | } |
2083 | if (sz == PSZ_MAX) { | 1868 | if (sz == PSZ_MAX) { |
2084 | Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n"); | 1869 | PWC_ERROR("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n"); |
2085 | return -EINVAL; | 1870 | return -EINVAL; |
2086 | } | 1871 | } |
2087 | Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y); | 1872 | PWC_DEBUG_MODULE("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y); |
2088 | } | 1873 | } |
2089 | if (mbufs) { | 1874 | if (mbufs) { |
2090 | if (mbufs < 1 || mbufs > MAX_IMAGES) { | 1875 | if (mbufs < 1 || mbufs > MAX_IMAGES) { |
2091 | Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES); | 1876 | PWC_ERROR("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES); |
2092 | return -EINVAL; | 1877 | return -EINVAL; |
2093 | } | 1878 | } |
2094 | default_mbufs = mbufs; | 1879 | pwc_mbufs = mbufs; |
2095 | Info("Number of image buffers set to %d.\n", default_mbufs); | 1880 | PWC_DEBUG_MODULE("Number of image buffers set to %d.\n", pwc_mbufs); |
2096 | } | 1881 | } |
2097 | if (fbufs) { | 1882 | if (fbufs) { |
2098 | if (fbufs < 2 || fbufs > MAX_FRAMES) { | 1883 | if (fbufs < 2 || fbufs > MAX_FRAMES) { |
2099 | Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES); | 1884 | PWC_ERROR("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES); |
2100 | return -EINVAL; | 1885 | return -EINVAL; |
2101 | } | 1886 | } |
2102 | default_fbufs = fbufs; | 1887 | default_fbufs = fbufs; |
2103 | Info("Number of frame buffers set to %d.\n", default_fbufs); | 1888 | PWC_DEBUG_MODULE("Number of frame buffers set to %d.\n", default_fbufs); |
2104 | } | 1889 | } |
2105 | if (trace >= 0) { | 1890 | #if CONFIG_PWC_DEBUG |
2106 | Info("Trace options: 0x%04x\n", trace); | 1891 | if (pwc_trace >= 0) { |
2107 | pwc_trace = trace; | 1892 | PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace); |
2108 | } | 1893 | } |
1894 | #endif | ||
2109 | if (compression >= 0) { | 1895 | if (compression >= 0) { |
2110 | if (compression > 3) { | 1896 | if (compression > 3) { |
2111 | Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n"); | 1897 | PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n"); |
2112 | return -EINVAL; | 1898 | return -EINVAL; |
2113 | } | 1899 | } |
2114 | pwc_preferred_compression = compression; | 1900 | pwc_preferred_compression = compression; |
2115 | Info("Preferred compression set to %d.\n", pwc_preferred_compression); | 1901 | PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression); |
2116 | } | 1902 | } |
2117 | if (power_save) | 1903 | if (power_save) |
2118 | Info("Enabling power save on open/close.\n"); | 1904 | PWC_DEBUG_MODULE("Enabling power save on open/close.\n"); |
2119 | if (leds[0] >= 0) | 1905 | if (leds[0] >= 0) |
2120 | led_on = leds[0]; | 1906 | led_on = leds[0]; |
2121 | if (leds[1] >= 0) | 1907 | if (leds[1] >= 0) |
@@ -2146,14 +1932,14 @@ static int __init usb_pwc_init(void) | |||
2146 | dot++; | 1932 | dot++; |
2147 | /* Few sanity checks */ | 1933 | /* Few sanity checks */ |
2148 | if (*dot != '\0' && dot > colon) { | 1934 | if (*dot != '\0' && dot > colon) { |
2149 | Err("Malformed camera hint: the colon must be after the dot.\n"); | 1935 | PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n"); |
2150 | return -EINVAL; | 1936 | return -EINVAL; |
2151 | } | 1937 | } |
2152 | 1938 | ||
2153 | if (*colon == '\0') { | 1939 | if (*colon == '\0') { |
2154 | /* No colon */ | 1940 | /* No colon */ |
2155 | if (*dot != '\0') { | 1941 | if (*dot != '\0') { |
2156 | Err("Malformed camera hint: no colon + device node given.\n"); | 1942 | PWC_ERROR("Malformed camera hint: no colon + device node given.\n"); |
2157 | return -EINVAL; | 1943 | return -EINVAL; |
2158 | } | 1944 | } |
2159 | else { | 1945 | else { |
@@ -2178,28 +1964,27 @@ static int __init usb_pwc_init(void) | |||
2178 | device_hint[i].serial_number[k] = '\0'; | 1964 | device_hint[i].serial_number[k] = '\0'; |
2179 | } | 1965 | } |
2180 | } | 1966 | } |
2181 | #if PWC_DEBUG | 1967 | PWC_TRACE("device_hint[%d]:\n", i); |
2182 | Debug("device_hint[%d]:\n", i); | 1968 | PWC_TRACE(" type : %d\n", device_hint[i].type); |
2183 | Debug(" type : %d\n", device_hint[i].type); | 1969 | PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number); |
2184 | Debug(" serial# : %s\n", device_hint[i].serial_number); | 1970 | PWC_TRACE(" node : %d\n", device_hint[i].device_node); |
2185 | Debug(" node : %d\n", device_hint[i].device_node); | ||
2186 | #endif | ||
2187 | } | 1971 | } |
2188 | else | 1972 | else |
2189 | device_hint[i].type = 0; /* not filled */ | 1973 | device_hint[i].type = 0; /* not filled */ |
2190 | } /* ..for MAX_DEV_HINTS */ | 1974 | } /* ..for MAX_DEV_HINTS */ |
2191 | 1975 | ||
2192 | Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver); | 1976 | PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver); |
2193 | return usb_register(&pwc_driver); | 1977 | return usb_register(&pwc_driver); |
2194 | } | 1978 | } |
2195 | 1979 | ||
2196 | static void __exit usb_pwc_exit(void) | 1980 | static void __exit usb_pwc_exit(void) |
2197 | { | 1981 | { |
2198 | Trace(TRACE_MODULE, "Deregistering driver.\n"); | 1982 | PWC_DEBUG_MODULE("Deregistering driver.\n"); |
2199 | usb_deregister(&pwc_driver); | 1983 | usb_deregister(&pwc_driver); |
2200 | Info("Philips webcam module removed.\n"); | 1984 | PWC_INFO("Philips webcam module removed.\n"); |
2201 | } | 1985 | } |
2202 | 1986 | ||
2203 | module_init(usb_pwc_init); | 1987 | module_init(usb_pwc_init); |
2204 | module_exit(usb_pwc_exit); | 1988 | module_exit(usb_pwc_exit); |
2205 | 1989 | ||
1990 | /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | ||
diff --git a/drivers/media/video/pwc/pwc-kiara.c b/drivers/media/video/pwc/pwc-kiara.c index 4c96037f7be5..fec39cc5a9f1 100644 --- a/drivers/media/video/pwc/pwc-kiara.c +++ b/drivers/media/video/pwc/pwc-kiara.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Linux driver for Philips webcam | 1 | /* Linux driver for Philips webcam |
2 | (C) 2004 Luc Saillard (luc@saillard.org) | 2 | (C) 2004-2006 Luc Saillard (luc@saillard.org) |
3 | 3 | ||
4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx |
5 | driver and thus may have bugs that are not present in the original version. | 5 | driver and thus may have bugs that are not present in the original version. |
@@ -316,3 +316,576 @@ const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] = | |||
316 | }, | 316 | }, |
317 | }; | 317 | }; |
318 | 318 | ||
319 | |||
320 | /* | ||
321 | * Rom table for kiara chips | ||
322 | * | ||
323 | * 32 roms tables (one for each resolution ?) | ||
324 | * 2 tables per roms (one for each passes) (Y, and U&V) | ||
325 | * 128 bytes per passes | ||
326 | */ | ||
327 | |||
328 | const unsigned int KiaraRomTable [8][2][16][8] = | ||
329 | { | ||
330 | { /* version 0 */ | ||
331 | { /* version 0, passes 0 */ | ||
332 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
333 | 0x00000000,0x00000000,0x00000001,0x00000001}, | ||
334 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
335 | 0x00000009,0x00000009,0x00000009,0x00000009}, | ||
336 | {0x00000000,0x00000000,0x00000009,0x00000049, | ||
337 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
338 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
339 | 0x00000049,0x00000249,0x0000024a,0x00000049}, | ||
340 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
341 | 0x00000249,0x00000249,0x0000024a,0x0000024a}, | ||
342 | {0x00000000,0x00000000,0x00000049,0x00000249, | ||
343 | 0x00000249,0x0000124a,0x0000024a,0x0000024a}, | ||
344 | {0x00000000,0x00000000,0x00000049,0x00000249, | ||
345 | 0x0000124a,0x00009252,0x00001252,0x00001252}, | ||
346 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
347 | 0x00009252,0x00009292,0x00009292,0x00009292}, | ||
348 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
349 | 0x00009292,0x00009292,0x00009493,0x000124db}, | ||
350 | {0x00000000,0x00000000,0x00000249,0x0000924a, | ||
351 | 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, | ||
352 | {0x00000000,0x00000000,0x00001249,0x00009252, | ||
353 | 0x0000a493,0x000124db,0x000124db,0x000126dc}, | ||
354 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
355 | 0x000124db,0x000126dc,0x000136e4,0x000126dc}, | ||
356 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
357 | 0x000124db,0x000136e4,0x000136e4,0x000136e4}, | ||
358 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
359 | 0x000126dc,0x0001b724,0x0001b92d,0x0001b925}, | ||
360 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
361 | 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d}, | ||
362 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
363 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
364 | }, | ||
365 | { /* version 0, passes 1 */ | ||
366 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
367 | 0x00000000,0x00000000,0x00000000,0x00000000}, | ||
368 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
369 | 0x00000000,0x00000000,0x00000000,0x00000000}, | ||
370 | {0x00000000,0x00000000,0x00000001,0x00000009, | ||
371 | 0x00000009,0x00000009,0x00000009,0x00000001}, | ||
372 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
373 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
374 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
375 | 0x00000049,0x00000049,0x0000024a,0x0000024a}, | ||
376 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
377 | 0x00000249,0x00000249,0x0000024a,0x0000024a}, | ||
378 | {0x00000000,0x00000000,0x00000049,0x00000249, | ||
379 | 0x00000249,0x00000249,0x0000024a,0x00001252}, | ||
380 | {0x00000000,0x00000000,0x00000049,0x00001249, | ||
381 | 0x0000124a,0x0000124a,0x00001252,0x00009292}, | ||
382 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
383 | 0x00009252,0x00009252,0x00009292,0x00009493}, | ||
384 | {0x00000000,0x00000000,0x00000249,0x0000924a, | ||
385 | 0x00009292,0x00009292,0x00009292,0x00009493}, | ||
386 | {0x00000000,0x00000000,0x00000249,0x00009292, | ||
387 | 0x00009492,0x00009493,0x0000a49b,0x00009493}, | ||
388 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
389 | 0x0000a493,0x000124db,0x000126dc,0x000126dc}, | ||
390 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
391 | 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, | ||
392 | {0x00000000,0x00000000,0x00009252,0x00009493, | ||
393 | 0x000126dc,0x000126dc,0x000136e4,0x000136e4}, | ||
394 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
395 | 0x000136e4,0x000136e4,0x0001b725,0x0001b724}, | ||
396 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
397 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
398 | } | ||
399 | }, | ||
400 | { /* version 1 */ | ||
401 | { /* version 1, passes 0 */ | ||
402 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
403 | 0x00000000,0x00000000,0x00000000,0x00000001}, | ||
404 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
405 | 0x00000009,0x00000009,0x00000009,0x00000009}, | ||
406 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
407 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
408 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
409 | 0x00000049,0x00000249,0x0000024a,0x0000024a}, | ||
410 | {0x00000000,0x00000000,0x00000049,0x00000249, | ||
411 | 0x00000249,0x00000249,0x0000024a,0x00001252}, | ||
412 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
413 | 0x00000249,0x0000124a,0x00001252,0x00001252}, | ||
414 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
415 | 0x0000124a,0x0000124a,0x00009292,0x00009292}, | ||
416 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
417 | 0x0000124a,0x00009252,0x00009292,0x00009292}, | ||
418 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
419 | 0x00009252,0x00009292,0x00009292,0x00009292}, | ||
420 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
421 | 0x00009252,0x00009292,0x00009493,0x00009493}, | ||
422 | {0x00000000,0x00000000,0x00000249,0x0000924a, | ||
423 | 0x00009252,0x00009493,0x00009493,0x00009493}, | ||
424 | {0x00000000,0x00000000,0x00000249,0x0000924a, | ||
425 | 0x00009292,0x00009493,0x00009493,0x00009493}, | ||
426 | {0x00000000,0x00000000,0x00000249,0x00009252, | ||
427 | 0x00009492,0x00009493,0x0000a49b,0x0000a49b}, | ||
428 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
429 | 0x00009492,0x000124db,0x000124db,0x000124db}, | ||
430 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
431 | 0x0000a493,0x000126dc,0x000126dc,0x000126dc}, | ||
432 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
433 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
434 | }, | ||
435 | { /* version 1, passes 1 */ | ||
436 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
437 | 0x00000000,0x00000000,0x00000000,0x00000000}, | ||
438 | {0x00000000,0x00000000,0x00000049,0x00000009, | ||
439 | 0x00000049,0x00000009,0x00000001,0x00000000}, | ||
440 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
441 | 0x00000049,0x00000049,0x00000049,0x00000000}, | ||
442 | {0x00000000,0x00000000,0x00000249,0x00000049, | ||
443 | 0x00000249,0x00000049,0x0000024a,0x00000001}, | ||
444 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
445 | 0x00000249,0x00000249,0x0000024a,0x00000001}, | ||
446 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
447 | 0x00000249,0x00000249,0x0000024a,0x00000001}, | ||
448 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
449 | 0x00000249,0x00000249,0x0000024a,0x00000009}, | ||
450 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
451 | 0x0000124a,0x0000124a,0x0000024a,0x00000009}, | ||
452 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
453 | 0x0000124a,0x0000124a,0x0000024a,0x00000009}, | ||
454 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
455 | 0x0000124a,0x00009252,0x00001252,0x00000049}, | ||
456 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
457 | 0x0000124a,0x00009292,0x00001252,0x00000049}, | ||
458 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
459 | 0x0000124a,0x00009292,0x00001252,0x00000049}, | ||
460 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
461 | 0x00009252,0x00009292,0x00001252,0x0000024a}, | ||
462 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
463 | 0x00009292,0x00009292,0x00001252,0x0000024a}, | ||
464 | {0x00000000,0x00000000,0x0000924a,0x0000924a, | ||
465 | 0x00009492,0x00009493,0x00009292,0x00001252}, | ||
466 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
467 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
468 | } | ||
469 | }, | ||
470 | { /* version 2 */ | ||
471 | { /* version 2, passes 0 */ | ||
472 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
473 | 0x00000049,0x00000049,0x0000024a,0x0000024a}, | ||
474 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
475 | 0x00000249,0x0000124a,0x00001252,0x00009292}, | ||
476 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
477 | 0x0000124a,0x00009252,0x00009292,0x00009292}, | ||
478 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
479 | 0x0000124a,0x00009292,0x00009493,0x00009493}, | ||
480 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
481 | 0x00009252,0x00009493,0x00009493,0x0000a49b}, | ||
482 | {0x00000000,0x00000000,0x00000249,0x0000924a, | ||
483 | 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, | ||
484 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
485 | 0x00009292,0x00009493,0x0000a49b,0x000124db}, | ||
486 | {0x00000000,0x00000000,0x00001249,0x00009252, | ||
487 | 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, | ||
488 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
489 | 0x00009492,0x000124db,0x000124db,0x000126dc}, | ||
490 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
491 | 0x0000a493,0x000124db,0x000126dc,0x000126dc}, | ||
492 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
493 | 0x0000a493,0x000124db,0x000126dc,0x000136e4}, | ||
494 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
495 | 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, | ||
496 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
497 | 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, | ||
498 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
499 | 0x000124db,0x000136e4,0x000136e4,0x0001b724}, | ||
500 | {0x00000000,0x00000000,0x00009252,0x000124db, | ||
501 | 0x000126dc,0x0001b724,0x0001b725,0x0001b925}, | ||
502 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
503 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
504 | }, | ||
505 | { /* version 2, passes 1 */ | ||
506 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
507 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
508 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
509 | 0x00000249,0x00000249,0x0000024a,0x00000049}, | ||
510 | {0x00000000,0x00000000,0x00001249,0x00000249, | ||
511 | 0x0000124a,0x0000124a,0x00001252,0x00000049}, | ||
512 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
513 | 0x0000124a,0x0000124a,0x00009292,0x0000024a}, | ||
514 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
515 | 0x00009252,0x00009292,0x00009292,0x0000024a}, | ||
516 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
517 | 0x00009252,0x00009292,0x0000a49b,0x0000024a}, | ||
518 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
519 | 0x00009292,0x00009493,0x0000a49b,0x00001252}, | ||
520 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
521 | 0x00009292,0x00009493,0x0000a49b,0x00001252}, | ||
522 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
523 | 0x00009492,0x0000a49b,0x0000a49b,0x00001252}, | ||
524 | {0x00000000,0x00000000,0x00001249,0x00009252, | ||
525 | 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, | ||
526 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
527 | 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, | ||
528 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
529 | 0x0000a493,0x0000a49b,0x0000a49b,0x00009292}, | ||
530 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
531 | 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, | ||
532 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
533 | 0x0000a493,0x000124db,0x0000a49b,0x00009493}, | ||
534 | {0x00000000,0x00000000,0x00009252,0x0000a49b, | ||
535 | 0x0001249b,0x000126dc,0x000124db,0x0000a49b}, | ||
536 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
537 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
538 | } | ||
539 | }, | ||
540 | { /* version 3 */ | ||
541 | { /* version 3, passes 0 */ | ||
542 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
543 | 0x0000124a,0x0000124a,0x00009292,0x00009292}, | ||
544 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
545 | 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, | ||
546 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
547 | 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, | ||
548 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
549 | 0x00009492,0x000124db,0x000126dc,0x000126dc}, | ||
550 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
551 | 0x0000a493,0x000124db,0x000126dc,0x000126dc}, | ||
552 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
553 | 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, | ||
554 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
555 | 0x0000a493,0x000126dc,0x000136e4,0x0001b724}, | ||
556 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
557 | 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, | ||
558 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
559 | 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, | ||
560 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
561 | 0x0001249b,0x000136e4,0x0001b725,0x0001b724}, | ||
562 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
563 | 0x000124db,0x000136e4,0x0001b725,0x0001b925}, | ||
564 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
565 | 0x000126dc,0x000136e4,0x0001b92d,0x0001b925}, | ||
566 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
567 | 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, | ||
568 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
569 | 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, | ||
570 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
571 | 0x000136e4,0x0001b925,0x00025bb6,0x00024b77}, | ||
572 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
573 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
574 | }, | ||
575 | { /* version 3, passes 1 */ | ||
576 | {0x00000000,0x00000000,0x00001249,0x00000249, | ||
577 | 0x0000124a,0x0000124a,0x00001252,0x00001252}, | ||
578 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
579 | 0x00009252,0x00009292,0x00009292,0x00001252}, | ||
580 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
581 | 0x00009492,0x00009493,0x0000a49b,0x00001252}, | ||
582 | {0x00000000,0x00000000,0x00001249,0x00009252, | ||
583 | 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, | ||
584 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
585 | 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, | ||
586 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
587 | 0x0000a493,0x0000a49b,0x000126dc,0x00009292}, | ||
588 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
589 | 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, | ||
590 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
591 | 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, | ||
592 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
593 | 0x0000a493,0x000124db,0x000126dc,0x00009493}, | ||
594 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
595 | 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, | ||
596 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
597 | 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, | ||
598 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
599 | 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, | ||
600 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
601 | 0x000124db,0x000136e4,0x000126dc,0x000124db}, | ||
602 | {0x00000000,0x00000000,0x00009492,0x0000a49b, | ||
603 | 0x000136e4,0x000136e4,0x000126dc,0x000124db}, | ||
604 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
605 | 0x0001b724,0x0001b724,0x000136e4,0x000126dc}, | ||
606 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
607 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
608 | } | ||
609 | }, | ||
610 | { /* version 4 */ | ||
611 | { /* version 4, passes 0 */ | ||
612 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
613 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
614 | {0x00000000,0x00000000,0x00000249,0x00000049, | ||
615 | 0x00000249,0x00000249,0x0000024a,0x00000049}, | ||
616 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
617 | 0x0000124a,0x00009252,0x00001252,0x0000024a}, | ||
618 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
619 | 0x00009252,0x00009292,0x00009493,0x00001252}, | ||
620 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
621 | 0x00009292,0x00009493,0x00009493,0x00001252}, | ||
622 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
623 | 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, | ||
624 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
625 | 0x0000a493,0x000124db,0x000124db,0x00009493}, | ||
626 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
627 | 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, | ||
628 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
629 | 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, | ||
630 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
631 | 0x0001249b,0x000126dc,0x000126dc,0x000124db}, | ||
632 | {0x00000000,0x00000000,0x00009252,0x00009493, | ||
633 | 0x000124db,0x000136e4,0x000136e4,0x000126dc}, | ||
634 | {0x00000000,0x00000000,0x00009252,0x0000a49b, | ||
635 | 0x000124db,0x000136e4,0x000136e4,0x000126dc}, | ||
636 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
637 | 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, | ||
638 | {0x00000000,0x00000000,0x00009492,0x0000a49b, | ||
639 | 0x000126dc,0x0001b724,0x0001b725,0x0001b724}, | ||
640 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
641 | 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, | ||
642 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
643 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
644 | }, | ||
645 | { /* version 4, passes 1 */ | ||
646 | {0x00000000,0x00000000,0x00000249,0x00000049, | ||
647 | 0x00000009,0x00000009,0x00000009,0x00000009}, | ||
648 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
649 | 0x00000049,0x00000049,0x00000009,0x00000009}, | ||
650 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
651 | 0x0000124a,0x00000249,0x00000049,0x00000049}, | ||
652 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
653 | 0x0000124a,0x0000124a,0x00000049,0x00000049}, | ||
654 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
655 | 0x00009252,0x0000124a,0x0000024a,0x0000024a}, | ||
656 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
657 | 0x00009252,0x0000124a,0x0000024a,0x0000024a}, | ||
658 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
659 | 0x00009492,0x00009252,0x00001252,0x00001252}, | ||
660 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
661 | 0x0000a493,0x00009292,0x00009292,0x00001252}, | ||
662 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
663 | 0x0000a493,0x00009292,0x00009292,0x00009292}, | ||
664 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
665 | 0x0000a493,0x00009493,0x00009493,0x00009292}, | ||
666 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
667 | 0x0000a493,0x0000a49b,0x00009493,0x00009493}, | ||
668 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
669 | 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, | ||
670 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
671 | 0x0001249b,0x000124db,0x0000a49b,0x0000a49b}, | ||
672 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
673 | 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, | ||
674 | {0x00000000,0x00000000,0x00009252,0x000124db, | ||
675 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
676 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
677 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
678 | } | ||
679 | }, | ||
680 | { /* version 5 */ | ||
681 | { /* version 5, passes 0 */ | ||
682 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
683 | 0x00000249,0x00000249,0x00001252,0x00001252}, | ||
684 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
685 | 0x00009252,0x00009292,0x00009292,0x00001252}, | ||
686 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
687 | 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, | ||
688 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
689 | 0x0000a493,0x0000a49b,0x000124db,0x00009493}, | ||
690 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
691 | 0x0000a493,0x000124db,0x000126dc,0x00009493}, | ||
692 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
693 | 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, | ||
694 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
695 | 0x0001249b,0x000126dc,0x000136e4,0x000124db}, | ||
696 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
697 | 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, | ||
698 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
699 | 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, | ||
700 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
701 | 0x000126dc,0x0001b724,0x0001b725,0x000136e4}, | ||
702 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
703 | 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, | ||
704 | {0x00000000,0x00000000,0x00009492,0x0000a49b, | ||
705 | 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, | ||
706 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
707 | 0x000136e4,0x0001b925,0x0001c96e,0x0001b925}, | ||
708 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
709 | 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, | ||
710 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
711 | 0x0001c924,0x0002496d,0x00025bb6,0x00024b77}, | ||
712 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
713 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
714 | }, | ||
715 | { /* version 5, passes 1 */ | ||
716 | {0x00000000,0x00000000,0x00001249,0x00000249, | ||
717 | 0x00000249,0x00000249,0x0000024a,0x0000024a}, | ||
718 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
719 | 0x0000124a,0x0000124a,0x0000024a,0x0000024a}, | ||
720 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
721 | 0x00009252,0x00009252,0x0000024a,0x0000024a}, | ||
722 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
723 | 0x00009492,0x0000a49b,0x00001252,0x00001252}, | ||
724 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
725 | 0x0000a493,0x0000a49b,0x00001252,0x00001252}, | ||
726 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
727 | 0x0000a493,0x0000a49b,0x00009292,0x00001252}, | ||
728 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
729 | 0x0000a493,0x0000a49b,0x00009292,0x00009292}, | ||
730 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
731 | 0x0000a493,0x0000a49b,0x00009493,0x00009292}, | ||
732 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
733 | 0x0001249b,0x000124db,0x00009493,0x00009292}, | ||
734 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
735 | 0x0001249b,0x000124db,0x00009493,0x00009493}, | ||
736 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
737 | 0x000124db,0x000124db,0x0000a49b,0x00009493}, | ||
738 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
739 | 0x000126dc,0x000126dc,0x0000a49b,0x00009493}, | ||
740 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
741 | 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, | ||
742 | {0x00000000,0x00000000,0x00009292,0x000124db, | ||
743 | 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, | ||
744 | {0x00000000,0x00000000,0x00009492,0x000126db, | ||
745 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
746 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
747 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
748 | } | ||
749 | }, | ||
750 | { /* version 6 */ | ||
751 | { /* version 6, passes 0 */ | ||
752 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
753 | 0x00009252,0x00009292,0x00009493,0x00009493}, | ||
754 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
755 | 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, | ||
756 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
757 | 0x0000a493,0x000124db,0x000124db,0x0000a49b}, | ||
758 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
759 | 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, | ||
760 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
761 | 0x0001249b,0x000126dc,0x000136e4,0x000124db}, | ||
762 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
763 | 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, | ||
764 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
765 | 0x000126dc,0x0001b724,0x0001b725,0x000126dc}, | ||
766 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
767 | 0x000136e4,0x0001b724,0x0001b92d,0x000136e4}, | ||
768 | {0x00000000,0x00000000,0x00009492,0x0000a49b, | ||
769 | 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, | ||
770 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
771 | 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, | ||
772 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
773 | 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, | ||
774 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
775 | 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, | ||
776 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
777 | 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d}, | ||
778 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
779 | 0x0001b724,0x0001c92d,0x00024b76,0x0002496e}, | ||
780 | {0x00000000,0x00000000,0x00012492,0x000126db, | ||
781 | 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf}, | ||
782 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
783 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
784 | }, | ||
785 | { /* version 6, passes 1 */ | ||
786 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
787 | 0x0000124a,0x0000124a,0x00001252,0x00001252}, | ||
788 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
789 | 0x00009492,0x00009252,0x00001252,0x00001252}, | ||
790 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
791 | 0x0000a493,0x00009292,0x00001252,0x00001252}, | ||
792 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
793 | 0x0000a493,0x0000a49b,0x00009292,0x00009292}, | ||
794 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
795 | 0x0000a493,0x0000a49b,0x00009292,0x00009292}, | ||
796 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
797 | 0x0001249b,0x0000a49b,0x00009493,0x00009292}, | ||
798 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
799 | 0x000124db,0x000124db,0x00009493,0x00009493}, | ||
800 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
801 | 0x000124db,0x000124db,0x0000a49b,0x00009493}, | ||
802 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
803 | 0x000126dc,0x000124db,0x0000a49b,0x00009493}, | ||
804 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
805 | 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b}, | ||
806 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
807 | 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, | ||
808 | {0x00000000,0x00000000,0x00009492,0x000126db, | ||
809 | 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, | ||
810 | {0x00000000,0x00000000,0x00009492,0x000126db, | ||
811 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
812 | {0x00000000,0x00000000,0x00009492,0x000126db, | ||
813 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
814 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
815 | 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, | ||
816 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
817 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
818 | } | ||
819 | }, | ||
820 | { /* version 7 */ | ||
821 | { /* version 7, passes 0 */ | ||
822 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
823 | 0x00009252,0x00009292,0x00009493,0x00009493}, | ||
824 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
825 | 0x0000a493,0x000124db,0x000126dc,0x00009493}, | ||
826 | {0x00000000,0x00000000,0x00001249,0x0000a49b, | ||
827 | 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, | ||
828 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
829 | 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, | ||
830 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
831 | 0x000126dc,0x000136e4,0x0001b725,0x000124db}, | ||
832 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
833 | 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, | ||
834 | {0x00000000,0x00000000,0x00009292,0x000124db, | ||
835 | 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, | ||
836 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
837 | 0x000136e4,0x0001b724,0x0001c96e,0x000136e4}, | ||
838 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
839 | 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, | ||
840 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
841 | 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, | ||
842 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
843 | 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925}, | ||
844 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
845 | 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, | ||
846 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
847 | 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, | ||
848 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
849 | 0x0001b924,0x0001c92d,0x00024b76,0x0002496e}, | ||
850 | {0x00000000,0x00000000,0x00012492,0x000136db, | ||
851 | 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf}, | ||
852 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
853 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
854 | }, | ||
855 | { /* version 7, passes 1 */ | ||
856 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
857 | 0x0000124a,0x0000124a,0x00001252,0x00001252}, | ||
858 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
859 | 0x00009492,0x00009292,0x00001252,0x00001252}, | ||
860 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
861 | 0x0000a493,0x0000a49b,0x00001252,0x00001252}, | ||
862 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
863 | 0x0000a493,0x0000a49b,0x00009292,0x00009292}, | ||
864 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
865 | 0x0000a493,0x0000a49b,0x00009292,0x00009292}, | ||
866 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
867 | 0x000126dc,0x0000a49b,0x00009493,0x00009292}, | ||
868 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
869 | 0x000126dc,0x000124db,0x00009493,0x00009493}, | ||
870 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
871 | 0x000136e4,0x000124db,0x0000a49b,0x00009493}, | ||
872 | {0x00000000,0x00000000,0x0000924a,0x000136db, | ||
873 | 0x0001b724,0x000124db,0x0000a49b,0x00009493}, | ||
874 | {0x00000000,0x00000000,0x0000924a,0x000136db, | ||
875 | 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b}, | ||
876 | {0x00000000,0x00000000,0x00009292,0x000136db, | ||
877 | 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, | ||
878 | {0x00000000,0x00000000,0x00009492,0x000136db, | ||
879 | 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, | ||
880 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
881 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
882 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
883 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
884 | {0x00000000,0x00000000,0x00012492,0x0001b6db, | ||
885 | 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, | ||
886 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
887 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
888 | } | ||
889 | } | ||
890 | }; | ||
891 | |||
diff --git a/drivers/media/video/pwc/pwc-kiara.h b/drivers/media/video/pwc/pwc-kiara.h index 12929abbb1f0..0bdb22547d86 100644 --- a/drivers/media/video/pwc/pwc-kiara.h +++ b/drivers/media/video/pwc/pwc-kiara.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Linux driver for Philips webcam | 1 | /* Linux driver for Philips webcam |
2 | (C) 2004 Luc Saillard (luc@saillard.org) | 2 | (C) 2004-2006 Luc Saillard (luc@saillard.org) |
3 | 3 | ||
4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx |
5 | driver and thus may have bugs that are not present in the original version. | 5 | driver and thus may have bugs that are not present in the original version. |
@@ -27,7 +27,7 @@ | |||
27 | #ifndef PWC_KIARA_H | 27 | #ifndef PWC_KIARA_H |
28 | #define PWC_KIARA_H | 28 | #define PWC_KIARA_H |
29 | 29 | ||
30 | #include "pwc-ioctl.h" | 30 | #include <media/pwc-ioctl.h> |
31 | 31 | ||
32 | struct Kiara_table_entry | 32 | struct Kiara_table_entry |
33 | { | 33 | { |
@@ -37,8 +37,8 @@ struct Kiara_table_entry | |||
37 | unsigned char mode[12]; /* precomputed mode settings for cam */ | 37 | unsigned char mode[12]; /* precomputed mode settings for cam */ |
38 | }; | 38 | }; |
39 | 39 | ||
40 | const extern struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4]; | 40 | extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4]; |
41 | const extern unsigned int KiaraRomTable[8][2][16][8]; | 41 | extern const unsigned int KiaraRomTable[8][2][16][8]; |
42 | 42 | ||
43 | #endif | 43 | #endif |
44 | 44 | ||
diff --git a/drivers/media/video/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c index 58fe79747992..589c687439da 100644 --- a/drivers/media/video/pwc/pwc-misc.c +++ b/drivers/media/video/pwc/pwc-misc.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* Linux driver for Philips webcam | 1 | /* Linux driver for Philips webcam |
2 | Various miscellaneous functions and tables. | 2 | Various miscellaneous functions and tables. |
3 | (C) 1999-2003 Nemosoft Unv. | 3 | (C) 1999-2003 Nemosoft Unv. |
4 | (C) 2004 Luc Saillard (luc@saillard.org) | 4 | (C) 2004-2006 Luc Saillard (luc@saillard.org) |
5 | 5 | ||
6 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 6 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx |
7 | driver and thus may have bugs that are not present in the original version. | 7 | driver and thus may have bugs that are not present in the original version. |
@@ -24,18 +24,17 @@ | |||
24 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 24 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/slab.h> | ||
28 | 27 | ||
29 | #include "pwc.h" | 28 | #include "pwc.h" |
30 | 29 | ||
31 | struct pwc_coord pwc_image_sizes[PSZ_MAX] = | 30 | const struct pwc_coord pwc_image_sizes[PSZ_MAX] = |
32 | { | 31 | { |
33 | { 128, 96, 0 }, | 32 | { 128, 96, 0 }, /* sqcif */ |
34 | { 160, 120, 0 }, | 33 | { 160, 120, 0 }, /* qsif */ |
35 | { 176, 144, 0 }, | 34 | { 176, 144, 0 }, /* qcif */ |
36 | { 320, 240, 0 }, | 35 | { 320, 240, 0 }, /* sif */ |
37 | { 352, 288, 0 }, | 36 | { 352, 288, 0 }, /* cif */ |
38 | { 640, 480, 0 }, | 37 | { 640, 480, 0 }, /* vga */ |
39 | }; | 38 | }; |
40 | 39 | ||
41 | /* x,y -> PSZ_ */ | 40 | /* x,y -> PSZ_ */ |
@@ -52,7 +51,7 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height) | |||
52 | { | 51 | { |
53 | if (width > pdev->abs_max.x || height > pdev->abs_max.y) | 52 | if (width > pdev->abs_max.x || height > pdev->abs_max.y) |
54 | { | 53 | { |
55 | Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n"); | 54 | PWC_DEBUG_SIZE("VIDEO_PALETTE_RAW: going beyond abs_max.\n"); |
56 | return -1; | 55 | return -1; |
57 | } | 56 | } |
58 | } | 57 | } |
@@ -60,7 +59,7 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height) | |||
60 | { | 59 | { |
61 | if (width > pdev->view_max.x || height > pdev->view_max.y) | 60 | if (width > pdev->view_max.x || height > pdev->view_max.y) |
62 | { | 61 | { |
63 | Debug("VIDEO_PALETTE_ not RAW: going beyond view_max.\n"); | 62 | PWC_DEBUG_SIZE("VIDEO_PALETTE_not RAW: going beyond view_max.\n"); |
64 | return -1; | 63 | return -1; |
65 | } | 64 | } |
66 | } | 65 | } |
@@ -81,9 +80,8 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height) | |||
81 | /* initialize variables depending on type and decompressor*/ | 80 | /* initialize variables depending on type and decompressor*/ |
82 | void pwc_construct(struct pwc_device *pdev) | 81 | void pwc_construct(struct pwc_device *pdev) |
83 | { | 82 | { |
84 | switch(pdev->type) { | 83 | if (DEVICE_USE_CODEC1(pdev->type)) { |
85 | case 645: | 84 | |
86 | case 646: | ||
87 | pdev->view_min.x = 128; | 85 | pdev->view_min.x = 128; |
88 | pdev->view_min.y = 96; | 86 | pdev->view_min.y = 96; |
89 | pdev->view_max.x = 352; | 87 | pdev->view_max.x = 352; |
@@ -95,10 +93,23 @@ void pwc_construct(struct pwc_device *pdev) | |||
95 | pdev->vendpoint = 4; | 93 | pdev->vendpoint = 4; |
96 | pdev->frame_header_size = 0; | 94 | pdev->frame_header_size = 0; |
97 | pdev->frame_trailer_size = 0; | 95 | pdev->frame_trailer_size = 0; |
98 | break; | 96 | |
99 | case 675: | 97 | } else if (DEVICE_USE_CODEC3(pdev->type)) { |
100 | case 680: | 98 | |
101 | case 690: | 99 | pdev->view_min.x = 160; |
100 | pdev->view_min.y = 120; | ||
101 | pdev->view_max.x = 640; | ||
102 | pdev->view_max.y = 480; | ||
103 | pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; | ||
104 | pdev->abs_max.x = 640; | ||
105 | pdev->abs_max.y = 480; | ||
106 | pdev->vcinterface = 3; | ||
107 | pdev->vendpoint = 5; | ||
108 | pdev->frame_header_size = TOUCAM_HEADER_SIZE; | ||
109 | pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE; | ||
110 | |||
111 | } else /* if (DEVICE_USE_CODEC2(pdev->type)) */ { | ||
112 | |||
102 | pdev->view_min.x = 128; | 113 | pdev->view_min.x = 128; |
103 | pdev->view_min.y = 96; | 114 | pdev->view_min.y = 96; |
104 | /* Anthill bug #38: PWC always reports max size, even without PWCX */ | 115 | /* Anthill bug #38: PWC always reports max size, even without PWCX */ |
@@ -111,30 +122,12 @@ void pwc_construct(struct pwc_device *pdev) | |||
111 | pdev->vendpoint = 4; | 122 | pdev->vendpoint = 4; |
112 | pdev->frame_header_size = 0; | 123 | pdev->frame_header_size = 0; |
113 | pdev->frame_trailer_size = 0; | 124 | pdev->frame_trailer_size = 0; |
114 | break; | ||
115 | case 720: | ||
116 | case 730: | ||
117 | case 740: | ||
118 | case 750: | ||
119 | pdev->view_min.x = 160; | ||
120 | pdev->view_min.y = 120; | ||
121 | pdev->view_max.x = 640; | ||
122 | pdev->view_max.y = 480; | ||
123 | pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; | ||
124 | pdev->abs_max.x = 640; | ||
125 | pdev->abs_max.y = 480; | ||
126 | pdev->vcinterface = 3; | ||
127 | pdev->vendpoint = 5; | ||
128 | pdev->frame_header_size = TOUCAM_HEADER_SIZE; | ||
129 | pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE; | ||
130 | break; | ||
131 | } | 125 | } |
132 | Debug("type = %d\n",pdev->type); | ||
133 | pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */ | 126 | pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */ |
134 | pdev->view_min.size = pdev->view_min.x * pdev->view_min.y; | 127 | pdev->view_min.size = pdev->view_min.x * pdev->view_min.y; |
135 | pdev->view_max.size = pdev->view_max.x * pdev->view_max.y; | 128 | pdev->view_max.size = pdev->view_max.x * pdev->view_max.y; |
136 | /* length of image, in YUV format; always allocate enough memory. */ | 129 | /* length of image, in YUV format; always allocate enough memory. */ |
137 | pdev->len_per_image = (pdev->abs_max.x * pdev->abs_max.y * 3) / 2; | 130 | pdev->len_per_image = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2); |
138 | } | 131 | } |
139 | 132 | ||
140 | 133 | ||
diff --git a/drivers/media/video/pwc/pwc-timon.c b/drivers/media/video/pwc/pwc-timon.c index 175250d089cf..be65bdcd195b 100644 --- a/drivers/media/video/pwc/pwc-timon.c +++ b/drivers/media/video/pwc/pwc-timon.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Linux driver for Philips webcam | 1 | /* Linux driver for Philips webcam |
2 | (C) 2004 Luc Saillard (luc@saillard.org) | 2 | (C) 2004-2006 Luc Saillard (luc@saillard.org) |
3 | 3 | ||
4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx |
5 | driver and thus may have bugs that are not present in the original version. | 5 | driver and thus may have bugs that are not present in the original version. |
@@ -314,3 +314,1133 @@ const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] = | |||
314 | }, | 314 | }, |
315 | }; | 315 | }; |
316 | 316 | ||
317 | /* | ||
318 | * 16 versions: | ||
319 | * 2 tables (one for Y, and one for U&V) | ||
320 | * 16 levels of details per tables | ||
321 | * 8 blocs | ||
322 | */ | ||
323 | |||
324 | const unsigned int TimonRomTable [16][2][16][8] = | ||
325 | { | ||
326 | { /* version 0 */ | ||
327 | { /* version 0, passes 0 */ | ||
328 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
329 | 0x00000000,0x00000000,0x00000000,0x00000001}, | ||
330 | {0x00000000,0x00000000,0x00000001,0x00000001, | ||
331 | 0x00000001,0x00000001,0x00000001,0x00000001}, | ||
332 | {0x00000000,0x00000000,0x00000001,0x00000001, | ||
333 | 0x00000001,0x00000009,0x00000009,0x00000009}, | ||
334 | {0x00000000,0x00000000,0x00000009,0x00000001, | ||
335 | 0x00000009,0x00000009,0x00000009,0x00000009}, | ||
336 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
337 | 0x00000009,0x00000009,0x00000049,0x00000009}, | ||
338 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
339 | 0x00000009,0x00000049,0x00000049,0x00000049}, | ||
340 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
341 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
342 | {0x00000000,0x00000000,0x00000009,0x00000049, | ||
343 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
344 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
345 | 0x00000049,0x00000049,0x0000024a,0x0000024a}, | ||
346 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
347 | 0x00000049,0x00000249,0x0000024a,0x0000024a}, | ||
348 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
349 | 0x00000249,0x00000249,0x0000024a,0x0000024a}, | ||
350 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
351 | 0x00000249,0x00000249,0x00001252,0x0000024a}, | ||
352 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
353 | 0x00000249,0x0000124a,0x00001252,0x0000024a}, | ||
354 | {0x00000000,0x00000000,0x00000049,0x00000249, | ||
355 | 0x00000249,0x0000124a,0x00001252,0x0000024a}, | ||
356 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
357 | 0x0000124a,0x00009252,0x00009292,0x00001252}, | ||
358 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
359 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
360 | }, | ||
361 | { /* version 0, passes 1 */ | ||
362 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
363 | 0x00000000,0x00000000,0x00000000,0x00000000}, | ||
364 | {0x00000000,0x00000000,0x00000001,0x00000001, | ||
365 | 0x00000001,0x00000001,0x00000000,0x00000000}, | ||
366 | {0x00000000,0x00000000,0x00000009,0x00000001, | ||
367 | 0x00000001,0x00000009,0x00000000,0x00000000}, | ||
368 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
369 | 0x00000009,0x00000009,0x00000000,0x00000000}, | ||
370 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
371 | 0x00000009,0x00000009,0x00000001,0x00000000}, | ||
372 | {0x00000000,0x00000000,0x00000049,0x00000009, | ||
373 | 0x00000009,0x00000049,0x00000001,0x00000001}, | ||
374 | {0x00000000,0x00000000,0x00000049,0x00000009, | ||
375 | 0x00000009,0x00000049,0x00000001,0x00000001}, | ||
376 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
377 | 0x00000049,0x00000049,0x00000009,0x00000001}, | ||
378 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
379 | 0x00000049,0x00000049,0x00000009,0x00000001}, | ||
380 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
381 | 0x00000049,0x00000049,0x00000009,0x00000001}, | ||
382 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
383 | 0x00000049,0x00000049,0x00000009,0x00000009}, | ||
384 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
385 | 0x00000049,0x00000249,0x00000049,0x00000009}, | ||
386 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
387 | 0x00000049,0x00000249,0x00000049,0x00000009}, | ||
388 | {0x00000000,0x00000000,0x00000249,0x00000049, | ||
389 | 0x00000249,0x00000249,0x00000049,0x00000009}, | ||
390 | {0x00000000,0x00000000,0x00001249,0x00000249, | ||
391 | 0x0000124a,0x0000124a,0x0000024a,0x00000049}, | ||
392 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
393 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
394 | } | ||
395 | }, | ||
396 | { /* version 1 */ | ||
397 | { /* version 1, passes 0 */ | ||
398 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
399 | 0x00000000,0x00000000,0x00000000,0x00000001}, | ||
400 | {0x00000000,0x00000000,0x00000001,0x00000001, | ||
401 | 0x00000001,0x00000009,0x00000009,0x00000009}, | ||
402 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
403 | 0x00000009,0x00000009,0x00000009,0x00000009}, | ||
404 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
405 | 0x00000009,0x00000049,0x00000049,0x00000049}, | ||
406 | {0x00000000,0x00000000,0x00000009,0x00000049, | ||
407 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
408 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
409 | 0x00000049,0x00000249,0x0000024a,0x0000024a}, | ||
410 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
411 | 0x00000249,0x00000249,0x0000024a,0x0000024a}, | ||
412 | {0x00000000,0x00000000,0x00000049,0x00000249, | ||
413 | 0x00000249,0x00000249,0x0000024a,0x00001252}, | ||
414 | {0x00000000,0x00000000,0x00000049,0x00000249, | ||
415 | 0x00000249,0x0000124a,0x00001252,0x00001252}, | ||
416 | {0x00000000,0x00000000,0x00000049,0x00000249, | ||
417 | 0x0000124a,0x0000124a,0x00001252,0x00001252}, | ||
418 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
419 | 0x0000124a,0x0000124a,0x00009292,0x00009292}, | ||
420 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
421 | 0x0000124a,0x00009252,0x00009292,0x00009292}, | ||
422 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
423 | 0x00009252,0x00009252,0x00009292,0x00009292}, | ||
424 | {0x00000000,0x00000000,0x00000249,0x0000924a, | ||
425 | 0x00009292,0x00009493,0x00009493,0x00009493}, | ||
426 | {0x00000000,0x00000000,0x00001249,0x00009252, | ||
427 | 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b}, | ||
428 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
429 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
430 | }, | ||
431 | { /* version 1, passes 1 */ | ||
432 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
433 | 0x00000000,0x00000000,0x00000000,0x00000000}, | ||
434 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
435 | 0x00000009,0x00000001,0x00000001,0x00000000}, | ||
436 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
437 | 0x00000009,0x00000009,0x00000001,0x00000000}, | ||
438 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
439 | 0x00000049,0x00000009,0x00000001,0x00000000}, | ||
440 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
441 | 0x00000049,0x00000049,0x00000001,0x00000001}, | ||
442 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
443 | 0x00000049,0x00000049,0x00000009,0x00000001}, | ||
444 | {0x00000000,0x00000000,0x00000249,0x00000049, | ||
445 | 0x00000049,0x00000249,0x00000009,0x00000001}, | ||
446 | {0x00000000,0x00000000,0x00000249,0x00000049, | ||
447 | 0x00000249,0x00000249,0x00000009,0x00000009}, | ||
448 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
449 | 0x00000249,0x00000249,0x00000049,0x00000009}, | ||
450 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
451 | 0x00000249,0x0000124a,0x00000049,0x00000009}, | ||
452 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
453 | 0x00000249,0x0000124a,0x00000049,0x00000009}, | ||
454 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
455 | 0x00000249,0x0000124a,0x0000024a,0x00000049}, | ||
456 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
457 | 0x0000124a,0x0000124a,0x0000024a,0x00000049}, | ||
458 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
459 | 0x0000124a,0x0000124a,0x0000024a,0x00000049}, | ||
460 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
461 | 0x00009252,0x00009252,0x00001252,0x0000024a}, | ||
462 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
463 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
464 | } | ||
465 | }, | ||
466 | { /* version 2 */ | ||
467 | { /* version 2, passes 0 */ | ||
468 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
469 | 0x00000000,0x00000000,0x00000000,0x00000001}, | ||
470 | {0x00000000,0x00000000,0x00000009,0x00000009, | ||
471 | 0x00000009,0x00000009,0x00000009,0x00000009}, | ||
472 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
473 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
474 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
475 | 0x00000049,0x00000249,0x0000024a,0x0000024a}, | ||
476 | {0x00000000,0x00000000,0x00000049,0x00000249, | ||
477 | 0x00000249,0x00000249,0x0000024a,0x00001252}, | ||
478 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
479 | 0x00000249,0x0000124a,0x00001252,0x00001252}, | ||
480 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
481 | 0x0000124a,0x0000124a,0x00009292,0x00009292}, | ||
482 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
483 | 0x0000124a,0x00009252,0x00009292,0x00009292}, | ||
484 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
485 | 0x00009252,0x00009292,0x00009292,0x00009292}, | ||
486 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
487 | 0x00009252,0x00009292,0x00009493,0x00009493}, | ||
488 | {0x00000000,0x00000000,0x00000249,0x0000924a, | ||
489 | 0x00009252,0x00009493,0x00009493,0x00009493}, | ||
490 | {0x00000000,0x00000000,0x00000249,0x0000924a, | ||
491 | 0x00009292,0x00009493,0x00009493,0x00009493}, | ||
492 | {0x00000000,0x00000000,0x00000249,0x00009252, | ||
493 | 0x00009492,0x00009493,0x0000a49b,0x0000a49b}, | ||
494 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
495 | 0x00009492,0x000124db,0x000124db,0x000124db}, | ||
496 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
497 | 0x0000a493,0x000126dc,0x000126dc,0x000126dc}, | ||
498 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
499 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
500 | }, | ||
501 | { /* version 2, passes 1 */ | ||
502 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
503 | 0x00000000,0x00000000,0x00000000,0x00000000}, | ||
504 | {0x00000000,0x00000000,0x00000049,0x00000009, | ||
505 | 0x00000049,0x00000009,0x00000001,0x00000000}, | ||
506 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
507 | 0x00000049,0x00000049,0x00000049,0x00000000}, | ||
508 | {0x00000000,0x00000000,0x00000249,0x00000049, | ||
509 | 0x00000249,0x00000049,0x0000024a,0x00000001}, | ||
510 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
511 | 0x00000249,0x00000249,0x0000024a,0x00000001}, | ||
512 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
513 | 0x00000249,0x00000249,0x0000024a,0x00000001}, | ||
514 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
515 | 0x00000249,0x00000249,0x0000024a,0x00000009}, | ||
516 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
517 | 0x0000124a,0x0000124a,0x0000024a,0x00000009}, | ||
518 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
519 | 0x0000124a,0x0000124a,0x0000024a,0x00000009}, | ||
520 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
521 | 0x0000124a,0x00009252,0x00001252,0x00000049}, | ||
522 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
523 | 0x0000124a,0x00009292,0x00001252,0x00000049}, | ||
524 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
525 | 0x0000124a,0x00009292,0x00001252,0x00000049}, | ||
526 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
527 | 0x00009252,0x00009292,0x00001252,0x0000024a}, | ||
528 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
529 | 0x00009292,0x00009292,0x00001252,0x0000024a}, | ||
530 | {0x00000000,0x00000000,0x0000924a,0x0000924a, | ||
531 | 0x00009492,0x00009493,0x00009292,0x00001252}, | ||
532 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
533 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
534 | } | ||
535 | }, | ||
536 | { /* version 3 */ | ||
537 | { /* version 3, passes 0 */ | ||
538 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
539 | 0x00000000,0x00000000,0x00000000,0x00000001}, | ||
540 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
541 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
542 | {0x00000000,0x00000000,0x00000049,0x00000249, | ||
543 | 0x00000249,0x00000249,0x00001252,0x0000024a}, | ||
544 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
545 | 0x00000249,0x0000124a,0x00001252,0x00001252}, | ||
546 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
547 | 0x0000124a,0x00009252,0x00009292,0x00009292}, | ||
548 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
549 | 0x0000124a,0x00009292,0x00009292,0x00009493}, | ||
550 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
551 | 0x00009252,0x00009292,0x00009493,0x00009493}, | ||
552 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
553 | 0x00009292,0x00009493,0x00009493,0x00009493}, | ||
554 | {0x00000000,0x00000000,0x00000249,0x00009252, | ||
555 | 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, | ||
556 | {0x00000000,0x00000000,0x00001249,0x00009252, | ||
557 | 0x00009292,0x0000a49b,0x0000a49b,0x0000a49b}, | ||
558 | {0x00000000,0x00000000,0x00001249,0x00009252, | ||
559 | 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b}, | ||
560 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
561 | 0x00009492,0x0000a49b,0x000124db,0x000124db}, | ||
562 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
563 | 0x0000a493,0x0000a49b,0x000124db,0x000124db}, | ||
564 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
565 | 0x0001249b,0x000126dc,0x000136e4,0x000126dc}, | ||
566 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
567 | 0x000124db,0x000136e4,0x0001b725,0x000136e4}, | ||
568 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
569 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
570 | }, | ||
571 | { /* version 3, passes 1 */ | ||
572 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
573 | 0x00000000,0x00000000,0x00000000,0x00000000}, | ||
574 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
575 | 0x00000049,0x00000049,0x00000001,0x00000000}, | ||
576 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
577 | 0x00000249,0x00000249,0x00000049,0x00000001}, | ||
578 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
579 | 0x00000249,0x0000124a,0x00001252,0x00000001}, | ||
580 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
581 | 0x0000124a,0x0000124a,0x00001252,0x00000009}, | ||
582 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
583 | 0x0000124a,0x00009252,0x00009292,0x00000009}, | ||
584 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
585 | 0x0000124a,0x00009252,0x00009292,0x00000049}, | ||
586 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
587 | 0x00009252,0x00009252,0x00009292,0x00000049}, | ||
588 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
589 | 0x00009252,0x00009493,0x00009292,0x0000024a}, | ||
590 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
591 | 0x00009252,0x00009493,0x00009292,0x0000024a}, | ||
592 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
593 | 0x00009252,0x00009493,0x00009493,0x00001252}, | ||
594 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
595 | 0x00009292,0x00009493,0x00009493,0x00001252}, | ||
596 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
597 | 0x00009492,0x00009493,0x00009493,0x00009292}, | ||
598 | {0x00000000,0x00000000,0x00001249,0x00009252, | ||
599 | 0x00009492,0x0000a49b,0x00009493,0x00009292}, | ||
600 | {0x00000000,0x00000000,0x0000924a,0x00009292, | ||
601 | 0x0000a493,0x000124db,0x0000a49b,0x00009493}, | ||
602 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
603 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
604 | } | ||
605 | }, | ||
606 | { /* version 4 */ | ||
607 | { /* version 4, passes 0 */ | ||
608 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
609 | 0x00000049,0x00000049,0x0000024a,0x0000024a}, | ||
610 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
611 | 0x00000249,0x0000124a,0x00001252,0x00009292}, | ||
612 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
613 | 0x0000124a,0x00009252,0x00009292,0x00009292}, | ||
614 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
615 | 0x0000124a,0x00009292,0x00009493,0x00009493}, | ||
616 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
617 | 0x00009252,0x00009493,0x00009493,0x0000a49b}, | ||
618 | {0x00000000,0x00000000,0x00000249,0x0000924a, | ||
619 | 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, | ||
620 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
621 | 0x00009292,0x00009493,0x0000a49b,0x000124db}, | ||
622 | {0x00000000,0x00000000,0x00001249,0x00009252, | ||
623 | 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, | ||
624 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
625 | 0x00009492,0x000124db,0x000124db,0x000126dc}, | ||
626 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
627 | 0x0000a493,0x000124db,0x000126dc,0x000126dc}, | ||
628 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
629 | 0x0000a493,0x000124db,0x000126dc,0x000136e4}, | ||
630 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
631 | 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, | ||
632 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
633 | 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, | ||
634 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
635 | 0x000124db,0x000136e4,0x000136e4,0x0001b724}, | ||
636 | {0x00000000,0x00000000,0x00009252,0x000124db, | ||
637 | 0x000126dc,0x0001b724,0x0001b725,0x0001b925}, | ||
638 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
639 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
640 | }, | ||
641 | { /* version 4, passes 1 */ | ||
642 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
643 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
644 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
645 | 0x00000249,0x00000249,0x0000024a,0x00000049}, | ||
646 | {0x00000000,0x00000000,0x00001249,0x00000249, | ||
647 | 0x0000124a,0x0000124a,0x00001252,0x00000049}, | ||
648 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
649 | 0x0000124a,0x0000124a,0x00009292,0x0000024a}, | ||
650 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
651 | 0x00009252,0x00009292,0x00009292,0x0000024a}, | ||
652 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
653 | 0x00009252,0x00009292,0x0000a49b,0x0000024a}, | ||
654 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
655 | 0x00009292,0x00009493,0x0000a49b,0x00001252}, | ||
656 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
657 | 0x00009292,0x00009493,0x0000a49b,0x00001252}, | ||
658 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
659 | 0x00009492,0x0000a49b,0x0000a49b,0x00001252}, | ||
660 | {0x00000000,0x00000000,0x00001249,0x00009252, | ||
661 | 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, | ||
662 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
663 | 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, | ||
664 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
665 | 0x0000a493,0x0000a49b,0x0000a49b,0x00009292}, | ||
666 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
667 | 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, | ||
668 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
669 | 0x0000a493,0x000124db,0x0000a49b,0x00009493}, | ||
670 | {0x00000000,0x00000000,0x00009252,0x0000a49b, | ||
671 | 0x0001249b,0x000126dc,0x000124db,0x0000a49b}, | ||
672 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
673 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
674 | } | ||
675 | }, | ||
676 | { /* version 5 */ | ||
677 | { /* version 5, passes 0 */ | ||
678 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
679 | 0x00000249,0x0000124a,0x00001252,0x00009292}, | ||
680 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
681 | 0x0000124a,0x00009292,0x00009292,0x00009493}, | ||
682 | {0x00000000,0x00000000,0x00000249,0x0000924a, | ||
683 | 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, | ||
684 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
685 | 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, | ||
686 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
687 | 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, | ||
688 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
689 | 0x00009492,0x0000a49b,0x000124db,0x000124db}, | ||
690 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
691 | 0x0000a493,0x000124db,0x000124db,0x000126dc}, | ||
692 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
693 | 0x0000a493,0x000124db,0x000126dc,0x000126dc}, | ||
694 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
695 | 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, | ||
696 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
697 | 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, | ||
698 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
699 | 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, | ||
700 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
701 | 0x0001249b,0x000126dc,0x0001b725,0x0001b724}, | ||
702 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
703 | 0x000124db,0x000126dc,0x0001b725,0x0001b724}, | ||
704 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
705 | 0x000126dc,0x000136e4,0x0001b92d,0x0001b925}, | ||
706 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
707 | 0x000136e4,0x0001b724,0x0001c96e,0x0001c92d}, | ||
708 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
709 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
710 | }, | ||
711 | { /* version 5, passes 1 */ | ||
712 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
713 | 0x0000124a,0x00000249,0x0000024a,0x0000024a}, | ||
714 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
715 | 0x0000124a,0x0000124a,0x00001252,0x0000024a}, | ||
716 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
717 | 0x00009292,0x00009493,0x00009493,0x0000024a}, | ||
718 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
719 | 0x00009292,0x00009493,0x00009493,0x00001252}, | ||
720 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
721 | 0x00009292,0x00009493,0x0000a49b,0x00001252}, | ||
722 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
723 | 0x00009492,0x00009493,0x000124db,0x00001252}, | ||
724 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
725 | 0x00009492,0x00009493,0x000124db,0x00009292}, | ||
726 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
727 | 0x00009492,0x0000a49b,0x000124db,0x00009292}, | ||
728 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
729 | 0x0000a493,0x0000a49b,0x000124db,0x00009292}, | ||
730 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
731 | 0x0000a493,0x000124db,0x000124db,0x00009493}, | ||
732 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
733 | 0x0000a493,0x000124db,0x000124db,0x00009493}, | ||
734 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
735 | 0x0000a493,0x000124db,0x000124db,0x00009493}, | ||
736 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
737 | 0x0000a493,0x000124db,0x000124db,0x0000a49b}, | ||
738 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
739 | 0x000124db,0x000126dc,0x000124db,0x0000a49b}, | ||
740 | {0x00000000,0x00000000,0x00009252,0x000124db, | ||
741 | 0x000126dc,0x000136e4,0x000126dc,0x000124db}, | ||
742 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
743 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
744 | } | ||
745 | }, | ||
746 | { /* version 6 */ | ||
747 | { /* version 6, passes 0 */ | ||
748 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
749 | 0x0000124a,0x0000124a,0x00009292,0x00009292}, | ||
750 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
751 | 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, | ||
752 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
753 | 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, | ||
754 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
755 | 0x00009492,0x000124db,0x000126dc,0x000126dc}, | ||
756 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
757 | 0x0000a493,0x000124db,0x000126dc,0x000126dc}, | ||
758 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
759 | 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, | ||
760 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
761 | 0x0000a493,0x000126dc,0x000136e4,0x0001b724}, | ||
762 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
763 | 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, | ||
764 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
765 | 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, | ||
766 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
767 | 0x0001249b,0x000136e4,0x0001b725,0x0001b724}, | ||
768 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
769 | 0x000124db,0x000136e4,0x0001b725,0x0001b925}, | ||
770 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
771 | 0x000126dc,0x000136e4,0x0001b92d,0x0001b925}, | ||
772 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
773 | 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, | ||
774 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
775 | 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, | ||
776 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
777 | 0x000136e4,0x0001b925,0x00025bb6,0x00024b77}, | ||
778 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
779 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
780 | }, | ||
781 | { /* version 6, passes 1 */ | ||
782 | {0x00000000,0x00000000,0x00001249,0x00000249, | ||
783 | 0x0000124a,0x0000124a,0x00001252,0x00001252}, | ||
784 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
785 | 0x00009252,0x00009292,0x00009292,0x00001252}, | ||
786 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
787 | 0x00009492,0x00009493,0x0000a49b,0x00001252}, | ||
788 | {0x00000000,0x00000000,0x00001249,0x00009252, | ||
789 | 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, | ||
790 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
791 | 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, | ||
792 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
793 | 0x0000a493,0x0000a49b,0x000126dc,0x00009292}, | ||
794 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
795 | 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, | ||
796 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
797 | 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, | ||
798 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
799 | 0x0000a493,0x000124db,0x000126dc,0x00009493}, | ||
800 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
801 | 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, | ||
802 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
803 | 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, | ||
804 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
805 | 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, | ||
806 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
807 | 0x000124db,0x000136e4,0x000126dc,0x000124db}, | ||
808 | {0x00000000,0x00000000,0x00009492,0x0000a49b, | ||
809 | 0x000136e4,0x000136e4,0x000126dc,0x000124db}, | ||
810 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
811 | 0x0001b724,0x0001b724,0x000136e4,0x000126dc}, | ||
812 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
813 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
814 | } | ||
815 | }, | ||
816 | { /* version 7 */ | ||
817 | { /* version 7, passes 0 */ | ||
818 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
819 | 0x00009292,0x00009493,0x0000a49b,0x000124db}, | ||
820 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
821 | 0x0000a493,0x0000a49b,0x000124db,0x000126dc}, | ||
822 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
823 | 0x0000a493,0x000124db,0x000126dc,0x000136e4}, | ||
824 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
825 | 0x0000a493,0x000124db,0x000136e4,0x000136e4}, | ||
826 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
827 | 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, | ||
828 | {0x00000000,0x00000000,0x00001249,0x0000a49b, | ||
829 | 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, | ||
830 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
831 | 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, | ||
832 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
833 | 0x000124db,0x000136e4,0x0001b725,0x0001b724}, | ||
834 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
835 | 0x000126dc,0x000136e4,0x0001b725,0x0001b925}, | ||
836 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
837 | 0x000126dc,0x0001b724,0x0001b92d,0x0001b925}, | ||
838 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
839 | 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, | ||
840 | {0x00000000,0x00000000,0x00009292,0x000124db, | ||
841 | 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, | ||
842 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
843 | 0x000136e4,0x0001b724,0x0001c96e,0x0002496e}, | ||
844 | {0x00000000,0x00000000,0x00009492,0x000126db, | ||
845 | 0x000136e4,0x0001b925,0x0001c96e,0x0002496e}, | ||
846 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
847 | 0x0001b724,0x0002496d,0x00025bb6,0x00025bbf}, | ||
848 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
849 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
850 | }, | ||
851 | { /* version 7, passes 1 */ | ||
852 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
853 | 0x00009252,0x00009292,0x00009292,0x00009292}, | ||
854 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
855 | 0x00009492,0x00009493,0x00009493,0x00009292}, | ||
856 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
857 | 0x0000a493,0x0000a49b,0x0000a49b,0x00009292}, | ||
858 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
859 | 0x0000a493,0x0000a49b,0x000124db,0x00009493}, | ||
860 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
861 | 0x0000a493,0x000124db,0x000124db,0x00009493}, | ||
862 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
863 | 0x0000a493,0x000124db,0x000136e4,0x00009493}, | ||
864 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
865 | 0x0000a493,0x000124db,0x000136e4,0x0000a49b}, | ||
866 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
867 | 0x0001249b,0x000124db,0x000136e4,0x0000a49b}, | ||
868 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
869 | 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, | ||
870 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
871 | 0x0001249b,0x000126dc,0x000136e4,0x000124db}, | ||
872 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
873 | 0x000126dc,0x000136e4,0x000136e4,0x000124db}, | ||
874 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
875 | 0x000126dc,0x000136e4,0x000136e4,0x000124db}, | ||
876 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
877 | 0x000136e4,0x000136e4,0x000136e4,0x000126dc}, | ||
878 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
879 | 0x000136e4,0x0001b724,0x000136e4,0x000126dc}, | ||
880 | {0x00000000,0x00000000,0x00012492,0x000126db, | ||
881 | 0x0001b724,0x0001b925,0x0001b725,0x000136e4}, | ||
882 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
883 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
884 | } | ||
885 | }, | ||
886 | { /* version 8 */ | ||
887 | { /* version 8, passes 0 */ | ||
888 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
889 | 0x00009292,0x00009493,0x0000a49b,0x000124db}, | ||
890 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
891 | 0x0000a493,0x000124db,0x000126dc,0x000126dc}, | ||
892 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
893 | 0x0000a493,0x000124db,0x000126dc,0x000136e4}, | ||
894 | {0x00000000,0x00000000,0x00001249,0x0000a49b, | ||
895 | 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, | ||
896 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
897 | 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, | ||
898 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
899 | 0x000124db,0x000136e4,0x0001b725,0x0001b724}, | ||
900 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
901 | 0x000126dc,0x000136e4,0x0001b725,0x0001b925}, | ||
902 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
903 | 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, | ||
904 | {0x00000000,0x00000000,0x00009252,0x000124db, | ||
905 | 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, | ||
906 | {0x00000000,0x00000000,0x00009292,0x000124db, | ||
907 | 0x000126dc,0x0001b925,0x0001c96e,0x0001c92d}, | ||
908 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
909 | 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d}, | ||
910 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
911 | 0x000136e4,0x0001b925,0x00024b76,0x00024b77}, | ||
912 | {0x00000000,0x00000000,0x00009492,0x000126db, | ||
913 | 0x000136e4,0x0001b925,0x00024b76,0x00025bbf}, | ||
914 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
915 | 0x000136e4,0x0001c92d,0x00024b76,0x00025bbf}, | ||
916 | {0x00000000,0x00000000,0x00012492,0x000136db, | ||
917 | 0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff}, | ||
918 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
919 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
920 | }, | ||
921 | { /* version 8, passes 1 */ | ||
922 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
923 | 0x00009252,0x00009493,0x00009493,0x00009493}, | ||
924 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
925 | 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, | ||
926 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
927 | 0x0000a493,0x0000a49b,0x000124db,0x00009493}, | ||
928 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
929 | 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, | ||
930 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
931 | 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, | ||
932 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
933 | 0x0000a493,0x000124db,0x000136e4,0x000124db}, | ||
934 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
935 | 0x0001249b,0x000126dc,0x000136e4,0x000124db}, | ||
936 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
937 | 0x000126dc,0x000126dc,0x000136e4,0x000126dc}, | ||
938 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
939 | 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, | ||
940 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
941 | 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, | ||
942 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
943 | 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, | ||
944 | {0x00000000,0x00000000,0x00009292,0x000124db, | ||
945 | 0x000136e4,0x0001b724,0x0001b725,0x000136e4}, | ||
946 | {0x00000000,0x00000000,0x00009492,0x000126db, | ||
947 | 0x000136e4,0x0001b925,0x0001b725,0x0001b724}, | ||
948 | {0x00000000,0x00000000,0x00009492,0x000126db, | ||
949 | 0x000136e4,0x0001b925,0x0001b725,0x0001b724}, | ||
950 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
951 | 0x0001b724,0x0002496d,0x0001b92d,0x0001b925}, | ||
952 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
953 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
954 | } | ||
955 | }, | ||
956 | { /* version 9 */ | ||
957 | { /* version 9, passes 0 */ | ||
958 | {0x00000000,0x00000000,0x00000049,0x00000049, | ||
959 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
960 | {0x00000000,0x00000000,0x00000249,0x00000049, | ||
961 | 0x00000249,0x00000249,0x0000024a,0x00000049}, | ||
962 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
963 | 0x0000124a,0x00009252,0x00001252,0x0000024a}, | ||
964 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
965 | 0x00009252,0x00009292,0x00009493,0x00001252}, | ||
966 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
967 | 0x00009292,0x00009493,0x00009493,0x00001252}, | ||
968 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
969 | 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, | ||
970 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
971 | 0x0000a493,0x000124db,0x000124db,0x00009493}, | ||
972 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
973 | 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, | ||
974 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
975 | 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, | ||
976 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
977 | 0x0001249b,0x000126dc,0x000126dc,0x000124db}, | ||
978 | {0x00000000,0x00000000,0x00009252,0x00009493, | ||
979 | 0x000124db,0x000136e4,0x000136e4,0x000126dc}, | ||
980 | {0x00000000,0x00000000,0x00009252,0x0000a49b, | ||
981 | 0x000124db,0x000136e4,0x000136e4,0x000126dc}, | ||
982 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
983 | 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, | ||
984 | {0x00000000,0x00000000,0x00009492,0x0000a49b, | ||
985 | 0x000126dc,0x0001b724,0x0001b725,0x0001b724}, | ||
986 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
987 | 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, | ||
988 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
989 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
990 | }, | ||
991 | { /* version 9, passes 1 */ | ||
992 | {0x00000000,0x00000000,0x00000249,0x00000049, | ||
993 | 0x00000009,0x00000009,0x00000009,0x00000009}, | ||
994 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
995 | 0x00000049,0x00000049,0x00000009,0x00000009}, | ||
996 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
997 | 0x0000124a,0x00000249,0x00000049,0x00000049}, | ||
998 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
999 | 0x0000124a,0x0000124a,0x00000049,0x00000049}, | ||
1000 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
1001 | 0x00009252,0x0000124a,0x0000024a,0x0000024a}, | ||
1002 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
1003 | 0x00009252,0x0000124a,0x0000024a,0x0000024a}, | ||
1004 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
1005 | 0x00009492,0x00009252,0x00001252,0x00001252}, | ||
1006 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
1007 | 0x0000a493,0x00009292,0x00009292,0x00001252}, | ||
1008 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1009 | 0x0000a493,0x00009292,0x00009292,0x00009292}, | ||
1010 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1011 | 0x0000a493,0x00009493,0x00009493,0x00009292}, | ||
1012 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1013 | 0x0000a493,0x0000a49b,0x00009493,0x00009493}, | ||
1014 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1015 | 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, | ||
1016 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1017 | 0x0001249b,0x000124db,0x0000a49b,0x0000a49b}, | ||
1018 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1019 | 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, | ||
1020 | {0x00000000,0x00000000,0x00009252,0x000124db, | ||
1021 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
1022 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1023 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1024 | } | ||
1025 | }, | ||
1026 | { /* version 10 */ | ||
1027 | { /* version 10, passes 0 */ | ||
1028 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
1029 | 0x00000249,0x00000249,0x0000024a,0x0000024a}, | ||
1030 | {0x00000000,0x00000000,0x00000249,0x00001249, | ||
1031 | 0x00009252,0x00009292,0x00009292,0x0000024a}, | ||
1032 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
1033 | 0x00009252,0x00009292,0x00009292,0x00001252}, | ||
1034 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
1035 | 0x00009492,0x00009493,0x0000a49b,0x00009292}, | ||
1036 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
1037 | 0x00009492,0x000124db,0x000124db,0x00009292}, | ||
1038 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
1039 | 0x0000a493,0x000124db,0x000124db,0x00009493}, | ||
1040 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
1041 | 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, | ||
1042 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1043 | 0x0000a493,0x000124db,0x000126dc,0x000124db}, | ||
1044 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1045 | 0x0001249b,0x000126dc,0x000126dc,0x000124db}, | ||
1046 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1047 | 0x000124db,0x000126dc,0x000136e4,0x000126dc}, | ||
1048 | {0x00000000,0x00000000,0x00009252,0x0000a49b, | ||
1049 | 0x000124db,0x000136e4,0x000136e4,0x000136e4}, | ||
1050 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
1051 | 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, | ||
1052 | {0x00000000,0x00000000,0x00009492,0x0000a49b, | ||
1053 | 0x000126dc,0x0001b724,0x0001b92d,0x0001b724}, | ||
1054 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1055 | 0x000126dc,0x0001b925,0x0001b92d,0x0001b925}, | ||
1056 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
1057 | 0x000136e4,0x0002496d,0x0001c96e,0x0001c92d}, | ||
1058 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1059 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1060 | }, | ||
1061 | { /* version 10, passes 1 */ | ||
1062 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
1063 | 0x00000049,0x00000049,0x00000049,0x00000049}, | ||
1064 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
1065 | 0x0000124a,0x00000249,0x00000049,0x00000049}, | ||
1066 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
1067 | 0x0000124a,0x00009252,0x0000024a,0x00000049}, | ||
1068 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
1069 | 0x00009252,0x00009493,0x0000024a,0x0000024a}, | ||
1070 | {0x00000000,0x00000000,0x00001249,0x00009252, | ||
1071 | 0x00009492,0x00009493,0x00001252,0x0000024a}, | ||
1072 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
1073 | 0x00009492,0x00009493,0x00001252,0x00001252}, | ||
1074 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1075 | 0x00009492,0x00009493,0x00009292,0x00001252}, | ||
1076 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1077 | 0x0000a493,0x00009493,0x00009292,0x00009292}, | ||
1078 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1079 | 0x0000a493,0x0000a49b,0x00009493,0x00009292}, | ||
1080 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1081 | 0x0000a493,0x0000a49b,0x00009493,0x00009292}, | ||
1082 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1083 | 0x0000a493,0x000124db,0x0000a49b,0x00009493}, | ||
1084 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1085 | 0x0000a493,0x000124db,0x0000a49b,0x00009493}, | ||
1086 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1087 | 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, | ||
1088 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1089 | 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, | ||
1090 | {0x00000000,0x00000000,0x00009252,0x000126db, | ||
1091 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
1092 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1093 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1094 | } | ||
1095 | }, | ||
1096 | { /* version 11 */ | ||
1097 | { /* version 11, passes 0 */ | ||
1098 | {0x00000000,0x00000000,0x00000249,0x00000249, | ||
1099 | 0x00000249,0x00000249,0x00001252,0x00001252}, | ||
1100 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
1101 | 0x00009252,0x00009292,0x00009292,0x00001252}, | ||
1102 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
1103 | 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, | ||
1104 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
1105 | 0x0000a493,0x0000a49b,0x000124db,0x00009493}, | ||
1106 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
1107 | 0x0000a493,0x000124db,0x000126dc,0x00009493}, | ||
1108 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1109 | 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, | ||
1110 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1111 | 0x0001249b,0x000126dc,0x000136e4,0x000124db}, | ||
1112 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1113 | 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, | ||
1114 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
1115 | 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, | ||
1116 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
1117 | 0x000126dc,0x0001b724,0x0001b725,0x000136e4}, | ||
1118 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
1119 | 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, | ||
1120 | {0x00000000,0x00000000,0x00009492,0x0000a49b, | ||
1121 | 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, | ||
1122 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1123 | 0x000136e4,0x0001b925,0x0001c96e,0x0001b925}, | ||
1124 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1125 | 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, | ||
1126 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
1127 | 0x0001c924,0x0002496d,0x00025bb6,0x00024b77}, | ||
1128 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1129 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1130 | }, | ||
1131 | { /* version 11, passes 1 */ | ||
1132 | {0x00000000,0x00000000,0x00001249,0x00000249, | ||
1133 | 0x00000249,0x00000249,0x0000024a,0x0000024a}, | ||
1134 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
1135 | 0x0000124a,0x0000124a,0x0000024a,0x0000024a}, | ||
1136 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
1137 | 0x00009252,0x00009252,0x0000024a,0x0000024a}, | ||
1138 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
1139 | 0x00009492,0x0000a49b,0x00001252,0x00001252}, | ||
1140 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1141 | 0x0000a493,0x0000a49b,0x00001252,0x00001252}, | ||
1142 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1143 | 0x0000a493,0x0000a49b,0x00009292,0x00001252}, | ||
1144 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1145 | 0x0000a493,0x0000a49b,0x00009292,0x00009292}, | ||
1146 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1147 | 0x0000a493,0x0000a49b,0x00009493,0x00009292}, | ||
1148 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1149 | 0x0001249b,0x000124db,0x00009493,0x00009292}, | ||
1150 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1151 | 0x0001249b,0x000124db,0x00009493,0x00009493}, | ||
1152 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1153 | 0x000124db,0x000124db,0x0000a49b,0x00009493}, | ||
1154 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1155 | 0x000126dc,0x000126dc,0x0000a49b,0x00009493}, | ||
1156 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1157 | 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, | ||
1158 | {0x00000000,0x00000000,0x00009292,0x000124db, | ||
1159 | 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, | ||
1160 | {0x00000000,0x00000000,0x00009492,0x000126db, | ||
1161 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
1162 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1163 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1164 | } | ||
1165 | }, | ||
1166 | { /* version 12 */ | ||
1167 | { /* version 12, passes 0 */ | ||
1168 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
1169 | 0x00009252,0x00009292,0x00009493,0x00009493}, | ||
1170 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
1171 | 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, | ||
1172 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
1173 | 0x0000a493,0x000124db,0x000124db,0x0000a49b}, | ||
1174 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1175 | 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, | ||
1176 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1177 | 0x0001249b,0x000126dc,0x000136e4,0x000124db}, | ||
1178 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1179 | 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, | ||
1180 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
1181 | 0x000126dc,0x0001b724,0x0001b725,0x000126dc}, | ||
1182 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
1183 | 0x000136e4,0x0001b724,0x0001b92d,0x000136e4}, | ||
1184 | {0x00000000,0x00000000,0x00009492,0x0000a49b, | ||
1185 | 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, | ||
1186 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1187 | 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, | ||
1188 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1189 | 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, | ||
1190 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1191 | 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, | ||
1192 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
1193 | 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d}, | ||
1194 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
1195 | 0x0001b724,0x0001c92d,0x00024b76,0x0002496e}, | ||
1196 | {0x00000000,0x00000000,0x00012492,0x000126db, | ||
1197 | 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf}, | ||
1198 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1199 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1200 | }, | ||
1201 | { /* version 12, passes 1 */ | ||
1202 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
1203 | 0x0000124a,0x0000124a,0x00001252,0x00001252}, | ||
1204 | {0x00000000,0x00000000,0x00001249,0x00009292, | ||
1205 | 0x00009492,0x00009252,0x00001252,0x00001252}, | ||
1206 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1207 | 0x0000a493,0x00009292,0x00001252,0x00001252}, | ||
1208 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1209 | 0x0000a493,0x0000a49b,0x00009292,0x00009292}, | ||
1210 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1211 | 0x0000a493,0x0000a49b,0x00009292,0x00009292}, | ||
1212 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1213 | 0x0001249b,0x0000a49b,0x00009493,0x00009292}, | ||
1214 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1215 | 0x000124db,0x000124db,0x00009493,0x00009493}, | ||
1216 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1217 | 0x000124db,0x000124db,0x0000a49b,0x00009493}, | ||
1218 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1219 | 0x000126dc,0x000124db,0x0000a49b,0x00009493}, | ||
1220 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1221 | 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b}, | ||
1222 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1223 | 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, | ||
1224 | {0x00000000,0x00000000,0x00009492,0x000126db, | ||
1225 | 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, | ||
1226 | {0x00000000,0x00000000,0x00009492,0x000126db, | ||
1227 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
1228 | {0x00000000,0x00000000,0x00009492,0x000126db, | ||
1229 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
1230 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1231 | 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, | ||
1232 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1233 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1234 | } | ||
1235 | }, | ||
1236 | { /* version 13 */ | ||
1237 | { /* version 13, passes 0 */ | ||
1238 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
1239 | 0x00009252,0x00009292,0x00009493,0x00009493}, | ||
1240 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
1241 | 0x0000a493,0x000124db,0x000126dc,0x00009493}, | ||
1242 | {0x00000000,0x00000000,0x00001249,0x0000a49b, | ||
1243 | 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, | ||
1244 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1245 | 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, | ||
1246 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1247 | 0x000126dc,0x000136e4,0x0001b725,0x000124db}, | ||
1248 | {0x00000000,0x00000000,0x00009292,0x0000a49b, | ||
1249 | 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, | ||
1250 | {0x00000000,0x00000000,0x00009292,0x000124db, | ||
1251 | 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, | ||
1252 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1253 | 0x000136e4,0x0001b724,0x0001c96e,0x000136e4}, | ||
1254 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1255 | 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, | ||
1256 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
1257 | 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, | ||
1258 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
1259 | 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925}, | ||
1260 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
1261 | 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, | ||
1262 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
1263 | 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, | ||
1264 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
1265 | 0x0001b924,0x0001c92d,0x00024b76,0x0002496e}, | ||
1266 | {0x00000000,0x00000000,0x00012492,0x000136db, | ||
1267 | 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf}, | ||
1268 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1269 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1270 | }, | ||
1271 | { /* version 13, passes 1 */ | ||
1272 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
1273 | 0x0000124a,0x0000124a,0x00001252,0x00001252}, | ||
1274 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1275 | 0x00009492,0x00009292,0x00001252,0x00001252}, | ||
1276 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1277 | 0x0000a493,0x0000a49b,0x00001252,0x00001252}, | ||
1278 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1279 | 0x0000a493,0x0000a49b,0x00009292,0x00009292}, | ||
1280 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1281 | 0x0000a493,0x0000a49b,0x00009292,0x00009292}, | ||
1282 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1283 | 0x000126dc,0x0000a49b,0x00009493,0x00009292}, | ||
1284 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1285 | 0x000126dc,0x000124db,0x00009493,0x00009493}, | ||
1286 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1287 | 0x000136e4,0x000124db,0x0000a49b,0x00009493}, | ||
1288 | {0x00000000,0x00000000,0x0000924a,0x000136db, | ||
1289 | 0x0001b724,0x000124db,0x0000a49b,0x00009493}, | ||
1290 | {0x00000000,0x00000000,0x0000924a,0x000136db, | ||
1291 | 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b}, | ||
1292 | {0x00000000,0x00000000,0x00009292,0x000136db, | ||
1293 | 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, | ||
1294 | {0x00000000,0x00000000,0x00009492,0x000136db, | ||
1295 | 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, | ||
1296 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1297 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
1298 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1299 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
1300 | {0x00000000,0x00000000,0x00012492,0x0001b6db, | ||
1301 | 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, | ||
1302 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1303 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1304 | } | ||
1305 | }, | ||
1306 | { /* version 14 */ | ||
1307 | { /* version 14, passes 0 */ | ||
1308 | {0x00000000,0x00000000,0x00001249,0x0000924a, | ||
1309 | 0x00009292,0x00009493,0x00009493,0x00009493}, | ||
1310 | {0x00000000,0x00000000,0x00001249,0x0000a49b, | ||
1311 | 0x0000a493,0x000124db,0x000126dc,0x00009493}, | ||
1312 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1313 | 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, | ||
1314 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1315 | 0x000126dc,0x000136e4,0x0001b725,0x000124db}, | ||
1316 | {0x00000000,0x00000000,0x00009292,0x000124db, | ||
1317 | 0x000126dc,0x0001b724,0x0001b92d,0x000126dc}, | ||
1318 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1319 | 0x000136e4,0x0001b724,0x0001b92d,0x000126dc}, | ||
1320 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1321 | 0x000136e4,0x0001c92d,0x0001c96e,0x000136e4}, | ||
1322 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1323 | 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724}, | ||
1324 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
1325 | 0x0001b724,0x0001c92d,0x00024b76,0x0001b925}, | ||
1326 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
1327 | 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, | ||
1328 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
1329 | 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, | ||
1330 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1331 | 0x0001b724,0x0001c92d,0x00024b76,0x0002496e}, | ||
1332 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1333 | 0x0001b924,0x0002496d,0x00024b76,0x00024b77}, | ||
1334 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1335 | 0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf}, | ||
1336 | {0x00000000,0x00000000,0x00012492,0x0001b6db, | ||
1337 | 0x00024924,0x0002db6d,0x00036db6,0x0002efff}, | ||
1338 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1339 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1340 | }, | ||
1341 | { /* version 14, passes 1 */ | ||
1342 | {0x00000000,0x00000000,0x00001249,0x00001249, | ||
1343 | 0x0000124a,0x0000124a,0x00001252,0x00001252}, | ||
1344 | {0x00000000,0x00000000,0x0000924a,0x00009493, | ||
1345 | 0x0000a493,0x00009292,0x00001252,0x00001252}, | ||
1346 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1347 | 0x0000a493,0x0000a49b,0x00001252,0x00001252}, | ||
1348 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1349 | 0x0001249b,0x000136e4,0x00009292,0x00009292}, | ||
1350 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1351 | 0x0001249b,0x000136e4,0x00009292,0x00009292}, | ||
1352 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1353 | 0x000136e4,0x000136e4,0x00009493,0x00009292}, | ||
1354 | {0x00000000,0x00000000,0x00009492,0x000136db, | ||
1355 | 0x0001b724,0x000136e4,0x00009493,0x00009493}, | ||
1356 | {0x00000000,0x00000000,0x00009492,0x000136db, | ||
1357 | 0x0001b724,0x000136e4,0x0000a49b,0x00009493}, | ||
1358 | {0x00000000,0x00000000,0x00009492,0x000136db, | ||
1359 | 0x0001b724,0x000136e4,0x0000a49b,0x00009493}, | ||
1360 | {0x00000000,0x00000000,0x00009492,0x000136db, | ||
1361 | 0x0001b724,0x000136e4,0x0000a49b,0x0000a49b}, | ||
1362 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1363 | 0x0001b724,0x000136e4,0x000124db,0x0000a49b}, | ||
1364 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1365 | 0x0001b724,0x000136e4,0x000124db,0x0000a49b}, | ||
1366 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1367 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
1368 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1369 | 0x0001b724,0x000136e4,0x000126dc,0x000124db}, | ||
1370 | {0x00000000,0x00000000,0x00012492,0x0001b6db, | ||
1371 | 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, | ||
1372 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1373 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1374 | } | ||
1375 | }, | ||
1376 | { /* version 15 */ | ||
1377 | { /* version 15, passes 0 */ | ||
1378 | {0x00000000,0x00000000,0x00001249,0x00009493, | ||
1379 | 0x0000a493,0x0000a49b,0x000124db,0x000124db}, | ||
1380 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1381 | 0x0001249b,0x000126dc,0x000136e4,0x000124db}, | ||
1382 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1383 | 0x000126dc,0x0001b724,0x0001b725,0x000126dc}, | ||
1384 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1385 | 0x000136e4,0x0001b724,0x0001b92d,0x000126dc}, | ||
1386 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1387 | 0x000136e4,0x0001b925,0x0001c96e,0x000136e4}, | ||
1388 | {0x00000000,0x00000000,0x00009492,0x000124db, | ||
1389 | 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724}, | ||
1390 | {0x00000000,0x00000000,0x0000a492,0x000124db, | ||
1391 | 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724}, | ||
1392 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
1393 | 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925}, | ||
1394 | {0x00000000,0x00000000,0x0000a492,0x000126db, | ||
1395 | 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, | ||
1396 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1397 | 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, | ||
1398 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1399 | 0x0001b924,0x0002496d,0x00024b76,0x0002496e}, | ||
1400 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1401 | 0x0001c924,0x0002496d,0x00025bb6,0x00024b77}, | ||
1402 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1403 | 0x0001c924,0x00024b6d,0x00025bb6,0x00024b77}, | ||
1404 | {0x00000000,0x00000000,0x00012492,0x000136db, | ||
1405 | 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf}, | ||
1406 | {0x00000000,0x00000000,0x00012492,0x0001b6db, | ||
1407 | 0x00024924,0x0002db6d,0x00036db6,0x0002efff}, | ||
1408 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1409 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1410 | }, | ||
1411 | { /* version 15, passes 1 */ | ||
1412 | {0x00000000,0x00000000,0x0000924a,0x0000924a, | ||
1413 | 0x00009292,0x00009292,0x00009292,0x00009292}, | ||
1414 | {0x00000000,0x00000000,0x0000924a,0x0000a49b, | ||
1415 | 0x0000a493,0x000124db,0x00009292,0x00009292}, | ||
1416 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1417 | 0x000124db,0x0001b724,0x00009493,0x00009493}, | ||
1418 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1419 | 0x000126dc,0x0001b724,0x00009493,0x00009493}, | ||
1420 | {0x00000000,0x00000000,0x0000924a,0x000124db, | ||
1421 | 0x000136e4,0x0001b724,0x0000a49b,0x0000a49b}, | ||
1422 | {0x00000000,0x00000000,0x00009292,0x000136db, | ||
1423 | 0x0001b724,0x0001b724,0x0000a49b,0x0000a49b}, | ||
1424 | {0x00000000,0x00000000,0x00009492,0x000136db, | ||
1425 | 0x0001c924,0x0001b724,0x000124db,0x000124db}, | ||
1426 | {0x00000000,0x00000000,0x00009492,0x000136db, | ||
1427 | 0x0001c924,0x0001b724,0x000124db,0x000124db}, | ||
1428 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1429 | 0x0001c924,0x0001b724,0x000126dc,0x000126dc}, | ||
1430 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1431 | 0x0001c924,0x0001b925,0x000126dc,0x000126dc}, | ||
1432 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1433 | 0x0001c924,0x0001b925,0x000136e4,0x000136e4}, | ||
1434 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1435 | 0x0001c924,0x0001b925,0x000136e4,0x000136e4}, | ||
1436 | {0x00000000,0x00000000,0x0000a492,0x000136db, | ||
1437 | 0x0001c924,0x0001b925,0x0001b725,0x0001b724}, | ||
1438 | {0x00000000,0x00000000,0x00012492,0x000136db, | ||
1439 | 0x0001c924,0x0001b925,0x0001b725,0x0001b724}, | ||
1440 | {0x00000000,0x00000000,0x00012492,0x0001b6db, | ||
1441 | 0x00024924,0x0002496d,0x0001b92d,0x0001b925}, | ||
1442 | {0x00000000,0x00000000,0x00000000,0x00000000, | ||
1443 | 0x00000000,0x00000000,0x00000000,0x00000000} | ||
1444 | } | ||
1445 | } | ||
1446 | }; | ||
diff --git a/drivers/media/video/pwc/pwc-timon.h b/drivers/media/video/pwc/pwc-timon.h index a86b3782a081..eef9e2cd4320 100644 --- a/drivers/media/video/pwc/pwc-timon.h +++ b/drivers/media/video/pwc/pwc-timon.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Linux driver for Philips webcam | 1 | /* Linux driver for Philips webcam |
2 | (C) 2004 Luc Saillard (luc@saillard.org) | 2 | (C) 2004-2006 Luc Saillard (luc@saillard.org) |
3 | 3 | ||
4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx |
5 | driver and thus may have bugs that are not present in the original version. | 5 | driver and thus may have bugs that are not present in the original version. |
@@ -42,7 +42,7 @@ | |||
42 | #ifndef PWC_TIMON_H | 42 | #ifndef PWC_TIMON_H |
43 | #define PWC_TIMON_H | 43 | #define PWC_TIMON_H |
44 | 44 | ||
45 | #include "pwc-ioctl.h" | 45 | #include <media/pwc-ioctl.h> |
46 | 46 | ||
47 | struct Timon_table_entry | 47 | struct Timon_table_entry |
48 | { | 48 | { |
@@ -52,8 +52,8 @@ struct Timon_table_entry | |||
52 | unsigned char mode[13]; /* precomputed mode settings for cam */ | 52 | unsigned char mode[13]; /* precomputed mode settings for cam */ |
53 | }; | 53 | }; |
54 | 54 | ||
55 | const extern struct Timon_table_entry Timon_table[PSZ_MAX][6][4]; | 55 | extern const struct Timon_table_entry Timon_table[PSZ_MAX][6][4]; |
56 | const extern unsigned int TimonRomTable [16][2][16][8]; | 56 | extern const unsigned int TimonRomTable [16][2][16][8]; |
57 | 57 | ||
58 | 58 | ||
59 | #endif | 59 | #endif |
diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c index b37a89a163f9..5d82028ef942 100644 --- a/drivers/media/video/pwc/pwc-uncompress.c +++ b/drivers/media/video/pwc/pwc-uncompress.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* Linux driver for Philips webcam | 1 | /* Linux driver for Philips webcam |
2 | Decompression frontend. | 2 | Decompression frontend. |
3 | (C) 1999-2003 Nemosoft Unv. | 3 | (C) 1999-2003 Nemosoft Unv. |
4 | (C) 2004 Luc Saillard (luc@saillard.org) | 4 | (C) 2004-2006 Luc Saillard (luc@saillard.org) |
5 | 5 | ||
6 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 6 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx |
7 | driver and thus may have bugs that are not present in the original version. | 7 | driver and thus may have bugs that are not present in the original version. |
@@ -22,6 +22,8 @@ | |||
22 | You should have received a copy of the GNU General Public License | 22 | You should have received a copy of the GNU General Public License |
23 | along with this program; if not, write to the Free Software | 23 | along with this program; if not, write to the Free Software |
24 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 24 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
25 | |||
26 | vim: set ts=8: | ||
25 | */ | 27 | */ |
26 | 28 | ||
27 | #include <asm/current.h> | 29 | #include <asm/current.h> |
@@ -29,6 +31,8 @@ | |||
29 | 31 | ||
30 | #include "pwc.h" | 32 | #include "pwc.h" |
31 | #include "pwc-uncompress.h" | 33 | #include "pwc-uncompress.h" |
34 | #include "pwc-dec1.h" | ||
35 | #include "pwc-dec23.h" | ||
32 | 36 | ||
33 | int pwc_decompress(struct pwc_device *pdev) | 37 | int pwc_decompress(struct pwc_device *pdev) |
34 | { | 38 | { |
@@ -40,107 +44,95 @@ int pwc_decompress(struct pwc_device *pdev) | |||
40 | 44 | ||
41 | if (pdev == NULL) | 45 | if (pdev == NULL) |
42 | return -EFAULT; | 46 | return -EFAULT; |
43 | #if defined(__KERNEL__) && defined(PWC_MAGIC) | ||
44 | if (pdev->magic != PWC_MAGIC) { | ||
45 | Err("pwc_decompress(): magic failed.\n"); | ||
46 | return -EFAULT; | ||
47 | } | ||
48 | #endif | ||
49 | 47 | ||
50 | fbuf = pdev->read_frame; | 48 | fbuf = pdev->read_frame; |
51 | if (fbuf == NULL) | 49 | if (fbuf == NULL) |
52 | return -EFAULT; | 50 | return -EFAULT; |
53 | image = pdev->image_ptr[pdev->fill_image]; | 51 | image = pdev->image_data; |
54 | if (!image) | 52 | image += pdev->images[pdev->fill_image].offset; |
55 | return -EFAULT; | ||
56 | 53 | ||
57 | yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ | 54 | yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ |
58 | 55 | ||
59 | /* Raw format; that's easy... */ | 56 | /* Raw format; that's easy... */ |
60 | if (pdev->vpalette == VIDEO_PALETTE_RAW) | 57 | if (pdev->vpalette == VIDEO_PALETTE_RAW) |
61 | { | 58 | { |
62 | memcpy(image, yuv, pdev->frame_size); | 59 | struct pwc_raw_frame *raw_frame = image; |
60 | raw_frame->type = cpu_to_le16(pdev->type); | ||
61 | raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength); | ||
62 | /* cmd_buf is always 4 bytes, but sometimes, only the | ||
63 | * first 3 bytes is filled (Nala case). We can | ||
64 | * determine this using the type of the webcam */ | ||
65 | memcpy(raw_frame->cmd, pdev->cmd_buf, 4); | ||
66 | memcpy(raw_frame+1, yuv, pdev->frame_size); | ||
63 | return 0; | 67 | return 0; |
64 | } | 68 | } |
65 | 69 | ||
66 | if (pdev->vbandlength == 0) { | 70 | if (pdev->vbandlength == 0) { |
67 | /* Uncompressed mode. We copy the data into the output buffer, | 71 | /* Uncompressed mode. |
68 | using the viewport size (which may be larger than the image | 72 | * We copy the data into the output buffer, using the viewport |
69 | size). Unfortunately we have to do a bit of byte stuffing | 73 | * size (which may be larger than the image size). |
70 | to get the desired output format/size. | 74 | * Unfortunately we have to do a bit of byte stuffing to get |
75 | * the desired output format/size. | ||
76 | * | ||
77 | * We do some byte shuffling here to go from the | ||
78 | * native format to YUV420P. | ||
71 | */ | 79 | */ |
72 | /* | 80 | src = (u16 *)yuv; |
73 | * We do some byte shuffling here to go from the | 81 | n = pdev->view.x * pdev->view.y; |
74 | * native format to YUV420P. | 82 | |
75 | */ | 83 | /* offset in Y plane */ |
76 | src = (u16 *)yuv; | 84 | stride = pdev->view.x * pdev->offset.y + pdev->offset.x; |
77 | n = pdev->view.x * pdev->view.y; | 85 | dsty = (u16 *)(image + stride); |
78 | 86 | ||
79 | /* offset in Y plane */ | 87 | /* offsets in U/V planes */ |
80 | stride = pdev->view.x * pdev->offset.y + pdev->offset.x; | 88 | stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; |
81 | dsty = (u16 *)(image + stride); | 89 | dstu = (u16 *)(image + n + stride); |
82 | 90 | dstv = (u16 *)(image + n + n / 4 + stride); | |
83 | /* offsets in U/V planes */ | 91 | |
84 | stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; | 92 | /* increment after each line */ |
85 | dstu = (u16 *)(image + n + stride); | 93 | stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ |
86 | dstv = (u16 *)(image + n + n / 4 + stride); | 94 | |
87 | 95 | for (line = 0; line < pdev->image.y; line++) { | |
88 | /* increment after each line */ | 96 | for (col = 0; col < pdev->image.x; col += 4) { |
89 | stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ | 97 | *dsty++ = *src++; |
90 | 98 | *dsty++ = *src++; | |
91 | for (line = 0; line < pdev->image.y; line++) { | ||
92 | for (col = 0; col < pdev->image.x; col += 4) { | ||
93 | *dsty++ = *src++; | ||
94 | *dsty++ = *src++; | ||
95 | if (line & 1) | ||
96 | *dstv++ = *src++; | ||
97 | else | ||
98 | *dstu++ = *src++; | ||
99 | } | ||
100 | dsty += stride; | ||
101 | if (line & 1) | 99 | if (line & 1) |
102 | dstv += (stride >> 1); | 100 | *dstv++ = *src++; |
103 | else | 101 | else |
104 | dstu += (stride >> 1); | 102 | *dstu++ = *src++; |
105 | } | 103 | } |
104 | dsty += stride; | ||
105 | if (line & 1) | ||
106 | dstv += (stride >> 1); | ||
107 | else | ||
108 | dstu += (stride >> 1); | ||
109 | } | ||
110 | |||
111 | return 0; | ||
106 | } | 112 | } |
107 | else { | 113 | |
108 | /* Compressed; the decompressor routines will write the data | 114 | /* |
109 | in planar format immediately. | 115 | * Compressed; |
110 | */ | 116 | * the decompressor routines will write the data in planar format |
111 | int flags; | 117 | * immediately. |
112 | 118 | */ | |
113 | flags = PWCX_FLAG_PLANAR; | 119 | if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) { |
114 | if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) | 120 | PWC_ERROR("Mode Bayer is not supported for now\n"); |
115 | { | 121 | /* flags |= PWCX_FLAG_BAYER; */ |
116 | printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n"); | 122 | return -ENXIO; /* No such device or address: missing decompressor */ |
117 | flags |= PWCX_FLAG_BAYER; | 123 | } |
118 | return -ENXIO; /* No such device or address: missing decompressor */ | 124 | |
119 | } | 125 | if (DEVICE_USE_CODEC1(pdev->type)) { |
120 | 126 | ||
121 | #if 0 | 127 | /* TODO & FIXME */ |
122 | switch (pdev->type) | 128 | PWC_ERROR("This chipset is not supported for now\n"); |
123 | { | 129 | return -ENXIO; /* No such device or address: missing decompressor */ |
124 | case 675: | 130 | |
125 | case 680: | 131 | } else { |
126 | case 690: | 132 | pwc_dec23_decompress(pdev, yuv, image, PWCX_FLAG_PLANAR); |
127 | case 720: | ||
128 | case 730: | ||
129 | case 740: | ||
130 | case 750: | ||
131 | pwc_dec23_decompress(&pdev->image, &pdev->view, | ||
132 | &pdev->offset, yuv, image, flags, | ||
133 | pdev->decompress_data, pdev->vbandlength); | ||
134 | break; | ||
135 | case 645: | ||
136 | case 646: | ||
137 | /* TODO & FIXME */ | ||
138 | return -ENXIO; /* Missing decompressor */ | ||
139 | break; | ||
140 | } | ||
141 | #endif | ||
142 | } | 133 | } |
143 | return 0; | 134 | return 0; |
144 | } | 135 | } |
145 | 136 | ||
146 | 137 | ||
138 | /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | ||
diff --git a/drivers/media/video/pwc/pwc-uncompress.h b/drivers/media/video/pwc/pwc-uncompress.h index f75e1b6cbe19..041227f65246 100644 --- a/drivers/media/video/pwc/pwc-uncompress.h +++ b/drivers/media/video/pwc/pwc-uncompress.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* (C) 1999-2003 Nemosoft Unv. | 1 | /* (C) 1999-2003 Nemosoft Unv. |
2 | (C) 2004 Luc Saillard (luc@saillard.org) | 2 | (C) 2004-2006 Luc Saillard (luc@saillard.org) |
3 | 3 | ||
4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx |
5 | driver and thus may have bugs that are not present in the original version. | 5 | driver and thus may have bugs that are not present in the original version. |
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | #include <linux/config.h> | 33 | #include <linux/config.h> |
34 | 34 | ||
35 | #include "pwc-ioctl.h" | 35 | #include <media/pwc-ioctl.h> |
36 | 36 | ||
37 | /* from pwc-dec.h */ | 37 | /* from pwc-dec.h */ |
38 | #define PWCX_FLAG_PLANAR 0x0001 | 38 | #define PWCX_FLAG_PLANAR 0x0001 |
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c new file mode 100644 index 000000000000..b7eb3ce3b968 --- /dev/null +++ b/drivers/media/video/pwc/pwc-v4l.c | |||
@@ -0,0 +1,1202 @@ | |||
1 | /* Linux driver for Philips webcam | ||
2 | USB and Video4Linux interface part. | ||
3 | (C) 1999-2004 Nemosoft Unv. | ||
4 | (C) 2004-2006 Luc Saillard (luc@saillard.org) | ||
5 | |||
6 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | ||
7 | driver and thus may have bugs that are not present in the original version. | ||
8 | Please send bug reports and support requests to <luc@saillard.org>. | ||
9 | The decompression routines have been implemented by reverse-engineering the | ||
10 | Nemosoft binary pwcx module. Caveat emptor. | ||
11 | |||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; if not, write to the Free Software | ||
24 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | |||
26 | */ | ||
27 | |||
28 | #include <linux/errno.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/poll.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/vmalloc.h> | ||
35 | #include <asm/io.h> | ||
36 | |||
37 | #include "pwc.h" | ||
38 | |||
39 | static struct v4l2_queryctrl pwc_controls[] = { | ||
40 | { | ||
41 | .id = V4L2_CID_BRIGHTNESS, | ||
42 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
43 | .name = "Brightness", | ||
44 | .minimum = 0, | ||
45 | .maximum = 128, | ||
46 | .step = 1, | ||
47 | .default_value = 64, | ||
48 | }, | ||
49 | { | ||
50 | .id = V4L2_CID_CONTRAST, | ||
51 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
52 | .name = "Contrast", | ||
53 | .minimum = 0, | ||
54 | .maximum = 64, | ||
55 | .step = 1, | ||
56 | .default_value = 0, | ||
57 | }, | ||
58 | { | ||
59 | .id = V4L2_CID_SATURATION, | ||
60 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
61 | .name = "Saturation", | ||
62 | .minimum = -100, | ||
63 | .maximum = 100, | ||
64 | .step = 1, | ||
65 | .default_value = 0, | ||
66 | }, | ||
67 | { | ||
68 | .id = V4L2_CID_GAMMA, | ||
69 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
70 | .name = "Gamma", | ||
71 | .minimum = 0, | ||
72 | .maximum = 32, | ||
73 | .step = 1, | ||
74 | .default_value = 0, | ||
75 | }, | ||
76 | { | ||
77 | .id = V4L2_CID_RED_BALANCE, | ||
78 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
79 | .name = "Red Gain", | ||
80 | .minimum = 0, | ||
81 | .maximum = 256, | ||
82 | .step = 1, | ||
83 | .default_value = 0, | ||
84 | }, | ||
85 | { | ||
86 | .id = V4L2_CID_BLUE_BALANCE, | ||
87 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
88 | .name = "Blue Gain", | ||
89 | .minimum = 0, | ||
90 | .maximum = 256, | ||
91 | .step = 1, | ||
92 | .default_value = 0, | ||
93 | }, | ||
94 | { | ||
95 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | ||
96 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
97 | .name = "Auto White Balance", | ||
98 | .minimum = 0, | ||
99 | .maximum = 1, | ||
100 | .step = 1, | ||
101 | .default_value = 0, | ||
102 | }, | ||
103 | { | ||
104 | .id = V4L2_CID_EXPOSURE, | ||
105 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
106 | .name = "Shutter Speed (Exposure)", | ||
107 | .minimum = 0, | ||
108 | .maximum = 256, | ||
109 | .step = 1, | ||
110 | .default_value = 200, | ||
111 | }, | ||
112 | { | ||
113 | .id = V4L2_CID_AUTOGAIN, | ||
114 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
115 | .name = "Auto Gain Enabled", | ||
116 | .minimum = 0, | ||
117 | .maximum = 1, | ||
118 | .step = 1, | ||
119 | .default_value = 1, | ||
120 | }, | ||
121 | { | ||
122 | .id = V4L2_CID_GAIN, | ||
123 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
124 | .name = "Gain Level", | ||
125 | .minimum = 0, | ||
126 | .maximum = 256, | ||
127 | .step = 1, | ||
128 | .default_value = 0, | ||
129 | }, | ||
130 | { | ||
131 | .id = V4L2_CID_PRIVATE_SAVE_USER, | ||
132 | .type = V4L2_CTRL_TYPE_BUTTON, | ||
133 | .name = "Save User Settings", | ||
134 | .minimum = 0, | ||
135 | .maximum = 0, | ||
136 | .step = 0, | ||
137 | .default_value = 0, | ||
138 | }, | ||
139 | { | ||
140 | .id = V4L2_CID_PRIVATE_RESTORE_USER, | ||
141 | .type = V4L2_CTRL_TYPE_BUTTON, | ||
142 | .name = "Restore User Settings", | ||
143 | .minimum = 0, | ||
144 | .maximum = 0, | ||
145 | .step = 0, | ||
146 | .default_value = 0, | ||
147 | }, | ||
148 | { | ||
149 | .id = V4L2_CID_PRIVATE_RESTORE_FACTORY, | ||
150 | .type = V4L2_CTRL_TYPE_BUTTON, | ||
151 | .name = "Restore Factory Settings", | ||
152 | .minimum = 0, | ||
153 | .maximum = 0, | ||
154 | .step = 0, | ||
155 | .default_value = 0, | ||
156 | }, | ||
157 | { | ||
158 | .id = V4L2_CID_PRIVATE_COLOUR_MODE, | ||
159 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
160 | .name = "Colour mode", | ||
161 | .minimum = 0, | ||
162 | .maximum = 1, | ||
163 | .step = 1, | ||
164 | .default_value = 0, | ||
165 | }, | ||
166 | { | ||
167 | .id = V4L2_CID_PRIVATE_AUTOCONTOUR, | ||
168 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
169 | .name = "Auto contour", | ||
170 | .minimum = 0, | ||
171 | .maximum = 1, | ||
172 | .step = 1, | ||
173 | .default_value = 0, | ||
174 | }, | ||
175 | { | ||
176 | .id = V4L2_CID_PRIVATE_CONTOUR, | ||
177 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
178 | .name = "Contour", | ||
179 | .minimum = 0, | ||
180 | .maximum = 63, | ||
181 | .step = 1, | ||
182 | .default_value = 0, | ||
183 | }, | ||
184 | { | ||
185 | .id = V4L2_CID_PRIVATE_BACKLIGHT, | ||
186 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
187 | .name = "Backlight compensation", | ||
188 | .minimum = 0, | ||
189 | .maximum = 1, | ||
190 | .step = 1, | ||
191 | .default_value = 0, | ||
192 | }, | ||
193 | { | ||
194 | .id = V4L2_CID_PRIVATE_FLICKERLESS, | ||
195 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
196 | .name = "Flickerless", | ||
197 | .minimum = 0, | ||
198 | .maximum = 1, | ||
199 | .step = 1, | ||
200 | .default_value = 0, | ||
201 | }, | ||
202 | { | ||
203 | .id = V4L2_CID_PRIVATE_NOISE_REDUCTION, | ||
204 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
205 | .name = "Noise reduction", | ||
206 | .minimum = 0, | ||
207 | .maximum = 3, | ||
208 | .step = 1, | ||
209 | .default_value = 0, | ||
210 | }, | ||
211 | }; | ||
212 | |||
213 | |||
214 | static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f) | ||
215 | { | ||
216 | memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); | ||
217 | f->fmt.pix.width = pdev->view.x; | ||
218 | f->fmt.pix.height = pdev->view.y; | ||
219 | f->fmt.pix.field = V4L2_FIELD_NONE; | ||
220 | if (pdev->vpalette == VIDEO_PALETTE_YUV420P) { | ||
221 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; | ||
222 | f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2; | ||
223 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
224 | } else { | ||
225 | /* vbandlength contains 4 lines ... */ | ||
226 | f->fmt.pix.bytesperline = pdev->vbandlength/4; | ||
227 | f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame); | ||
228 | if (DEVICE_USE_CODEC1(pdev->type)) | ||
229 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC1; | ||
230 | else | ||
231 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC2; | ||
232 | } | ||
233 | PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() " | ||
234 | "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n", | ||
235 | f->fmt.pix.width, | ||
236 | f->fmt.pix.height, | ||
237 | f->fmt.pix.bytesperline, | ||
238 | f->fmt.pix.sizeimage, | ||
239 | (f->fmt.pix.pixelformat)&255, | ||
240 | (f->fmt.pix.pixelformat>>8)&255, | ||
241 | (f->fmt.pix.pixelformat>>16)&255, | ||
242 | (f->fmt.pix.pixelformat>>24)&255); | ||
243 | } | ||
244 | |||
245 | /* ioctl(VIDIOC_TRY_FMT) */ | ||
246 | static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) | ||
247 | { | ||
248 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
249 | PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); | ||
250 | return -EINVAL; | ||
251 | } | ||
252 | |||
253 | switch (f->fmt.pix.pixelformat) { | ||
254 | case V4L2_PIX_FMT_YUV420: | ||
255 | break; | ||
256 | case V4L2_PIX_FMT_PWC1: | ||
257 | if (DEVICE_USE_CODEC23(pdev->type)) { | ||
258 | PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n"); | ||
259 | return -EINVAL; | ||
260 | } | ||
261 | break; | ||
262 | case V4L2_PIX_FMT_PWC2: | ||
263 | if (DEVICE_USE_CODEC1(pdev->type)) { | ||
264 | PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n"); | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | break; | ||
268 | default: | ||
269 | PWC_DEBUG_IOCTL("Unsupported pixel format\n"); | ||
270 | return -EINVAL; | ||
271 | |||
272 | } | ||
273 | |||
274 | if (f->fmt.pix.width > pdev->view_max.x) | ||
275 | f->fmt.pix.width = pdev->view_max.x; | ||
276 | else if (f->fmt.pix.width < pdev->view_min.x) | ||
277 | f->fmt.pix.width = pdev->view_min.x; | ||
278 | |||
279 | if (f->fmt.pix.height > pdev->view_max.y) | ||
280 | f->fmt.pix.height = pdev->view_max.y; | ||
281 | else if (f->fmt.pix.height < pdev->view_min.y) | ||
282 | f->fmt.pix.height = pdev->view_min.y; | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | /* ioctl(VIDIOC_SET_FMT) */ | ||
288 | static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f) | ||
289 | { | ||
290 | int ret, fps, snapshot, compression, pixelformat; | ||
291 | |||
292 | ret = pwc_vidioc_try_fmt(pdev, f); | ||
293 | if (ret<0) | ||
294 | return ret; | ||
295 | |||
296 | pixelformat = f->fmt.pix.pixelformat; | ||
297 | compression = pdev->vcompression; | ||
298 | snapshot = 0; | ||
299 | fps = pdev->vframes; | ||
300 | if (f->fmt.pix.priv) { | ||
301 | compression = (f->fmt.pix.priv & PWC_QLT_MASK) >> PWC_QLT_SHIFT; | ||
302 | snapshot = !!(f->fmt.pix.priv & PWC_FPS_SNAPSHOT); | ||
303 | fps = (f->fmt.pix.priv & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; | ||
304 | if (fps == 0) | ||
305 | fps = pdev->vframes; | ||
306 | } | ||
307 | |||
308 | if (pixelformat == V4L2_PIX_FMT_YUV420) | ||
309 | pdev->vpalette = VIDEO_PALETTE_YUV420P; | ||
310 | else | ||
311 | pdev->vpalette = VIDEO_PALETTE_RAW; | ||
312 | |||
313 | PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d " | ||
314 | "compression=%d snapshot=%d format=%c%c%c%c\n", | ||
315 | f->fmt.pix.width, f->fmt.pix.height, fps, | ||
316 | compression, snapshot, | ||
317 | (pixelformat)&255, | ||
318 | (pixelformat>>8)&255, | ||
319 | (pixelformat>>16)&255, | ||
320 | (pixelformat>>24)&255); | ||
321 | |||
322 | ret = pwc_try_video_mode(pdev, | ||
323 | f->fmt.pix.width, | ||
324 | f->fmt.pix.height, | ||
325 | fps, | ||
326 | compression, | ||
327 | snapshot); | ||
328 | |||
329 | PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret); | ||
330 | |||
331 | if (ret) | ||
332 | return ret; | ||
333 | |||
334 | pwc_vidioc_fill_fmt(pdev, f); | ||
335 | |||
336 | return 0; | ||
337 | |||
338 | } | ||
339 | |||
340 | int pwc_video_do_ioctl(struct inode *inode, struct file *file, | ||
341 | unsigned int cmd, void *arg) | ||
342 | { | ||
343 | struct video_device *vdev = video_devdata(file); | ||
344 | struct pwc_device *pdev; | ||
345 | DECLARE_WAITQUEUE(wait, current); | ||
346 | |||
347 | if (vdev == NULL) | ||
348 | return -EFAULT; | ||
349 | pdev = vdev->priv; | ||
350 | if (pdev == NULL) | ||
351 | return -EFAULT; | ||
352 | |||
353 | #if CONFIG_PWC_DEBUG | ||
354 | if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) | ||
355 | v4l_printk_ioctl(cmd); | ||
356 | #endif | ||
357 | |||
358 | |||
359 | switch (cmd) { | ||
360 | /* Query cabapilities */ | ||
361 | case VIDIOCGCAP: | ||
362 | { | ||
363 | struct video_capability *caps = arg; | ||
364 | |||
365 | strcpy(caps->name, vdev->name); | ||
366 | caps->type = VID_TYPE_CAPTURE; | ||
367 | caps->channels = 1; | ||
368 | caps->audios = 1; | ||
369 | caps->minwidth = pdev->view_min.x; | ||
370 | caps->minheight = pdev->view_min.y; | ||
371 | caps->maxwidth = pdev->view_max.x; | ||
372 | caps->maxheight = pdev->view_max.y; | ||
373 | break; | ||
374 | } | ||
375 | |||
376 | /* Channel functions (simulate 1 channel) */ | ||
377 | case VIDIOCGCHAN: | ||
378 | { | ||
379 | struct video_channel *v = arg; | ||
380 | |||
381 | if (v->channel != 0) | ||
382 | return -EINVAL; | ||
383 | v->flags = 0; | ||
384 | v->tuners = 0; | ||
385 | v->type = VIDEO_TYPE_CAMERA; | ||
386 | strcpy(v->name, "Webcam"); | ||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | case VIDIOCSCHAN: | ||
391 | { | ||
392 | /* The spec says the argument is an integer, but | ||
393 | the bttv driver uses a video_channel arg, which | ||
394 | makes sense becasue it also has the norm flag. | ||
395 | */ | ||
396 | struct video_channel *v = arg; | ||
397 | if (v->channel != 0) | ||
398 | return -EINVAL; | ||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | |||
403 | /* Picture functions; contrast etc. */ | ||
404 | case VIDIOCGPICT: | ||
405 | { | ||
406 | struct video_picture *p = arg; | ||
407 | int val; | ||
408 | |||
409 | val = pwc_get_brightness(pdev); | ||
410 | if (val >= 0) | ||
411 | p->brightness = (val<<9); | ||
412 | else | ||
413 | p->brightness = 0xffff; | ||
414 | val = pwc_get_contrast(pdev); | ||
415 | if (val >= 0) | ||
416 | p->contrast = (val<<10); | ||
417 | else | ||
418 | p->contrast = 0xffff; | ||
419 | /* Gamma, Whiteness, what's the difference? :) */ | ||
420 | val = pwc_get_gamma(pdev); | ||
421 | if (val >= 0) | ||
422 | p->whiteness = (val<<11); | ||
423 | else | ||
424 | p->whiteness = 0xffff; | ||
425 | if (pwc_get_saturation(pdev, &val)<0) | ||
426 | p->colour = 0xffff; | ||
427 | else | ||
428 | p->colour = 32768 + val * 327; | ||
429 | p->depth = 24; | ||
430 | p->palette = pdev->vpalette; | ||
431 | p->hue = 0xFFFF; /* N/A */ | ||
432 | break; | ||
433 | } | ||
434 | |||
435 | case VIDIOCSPICT: | ||
436 | { | ||
437 | struct video_picture *p = arg; | ||
438 | /* | ||
439 | * FIXME: Suppose we are mid read | ||
440 | ANSWER: No problem: the firmware of the camera | ||
441 | can handle brightness/contrast/etc | ||
442 | changes at _any_ time, and the palette | ||
443 | is used exactly once in the uncompress | ||
444 | routine. | ||
445 | */ | ||
446 | pwc_set_brightness(pdev, p->brightness); | ||
447 | pwc_set_contrast(pdev, p->contrast); | ||
448 | pwc_set_gamma(pdev, p->whiteness); | ||
449 | pwc_set_saturation(pdev, (p->colour-32768)/327); | ||
450 | if (p->palette && p->palette != pdev->vpalette) { | ||
451 | switch (p->palette) { | ||
452 | case VIDEO_PALETTE_YUV420P: | ||
453 | case VIDEO_PALETTE_RAW: | ||
454 | pdev->vpalette = p->palette; | ||
455 | return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); | ||
456 | break; | ||
457 | default: | ||
458 | return -EINVAL; | ||
459 | break; | ||
460 | } | ||
461 | } | ||
462 | break; | ||
463 | } | ||
464 | |||
465 | /* Window/size parameters */ | ||
466 | case VIDIOCGWIN: | ||
467 | { | ||
468 | struct video_window *vw = arg; | ||
469 | |||
470 | vw->x = 0; | ||
471 | vw->y = 0; | ||
472 | vw->width = pdev->view.x; | ||
473 | vw->height = pdev->view.y; | ||
474 | vw->chromakey = 0; | ||
475 | vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | | ||
476 | (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0); | ||
477 | break; | ||
478 | } | ||
479 | |||
480 | case VIDIOCSWIN: | ||
481 | { | ||
482 | struct video_window *vw = arg; | ||
483 | int fps, snapshot, ret; | ||
484 | |||
485 | fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; | ||
486 | snapshot = vw->flags & PWC_FPS_SNAPSHOT; | ||
487 | if (fps == 0) | ||
488 | fps = pdev->vframes; | ||
489 | if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot) | ||
490 | return 0; | ||
491 | ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot); | ||
492 | if (ret) | ||
493 | return ret; | ||
494 | break; | ||
495 | } | ||
496 | |||
497 | /* We don't have overlay support (yet) */ | ||
498 | case VIDIOCGFBUF: | ||
499 | { | ||
500 | struct video_buffer *vb = arg; | ||
501 | |||
502 | memset(vb,0,sizeof(*vb)); | ||
503 | break; | ||
504 | } | ||
505 | |||
506 | /* mmap() functions */ | ||
507 | case VIDIOCGMBUF: | ||
508 | { | ||
509 | /* Tell the user program how much memory is needed for a mmap() */ | ||
510 | struct video_mbuf *vm = arg; | ||
511 | int i; | ||
512 | |||
513 | memset(vm, 0, sizeof(*vm)); | ||
514 | vm->size = pwc_mbufs * pdev->len_per_image; | ||
515 | vm->frames = pwc_mbufs; /* double buffering should be enough for most applications */ | ||
516 | for (i = 0; i < pwc_mbufs; i++) | ||
517 | vm->offsets[i] = i * pdev->len_per_image; | ||
518 | break; | ||
519 | } | ||
520 | |||
521 | case VIDIOCMCAPTURE: | ||
522 | { | ||
523 | /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */ | ||
524 | struct video_mmap *vm = arg; | ||
525 | |||
526 | PWC_DEBUG_READ("VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format); | ||
527 | if (vm->frame < 0 || vm->frame >= pwc_mbufs) | ||
528 | return -EINVAL; | ||
529 | |||
530 | /* xawtv is nasty. It probes the available palettes | ||
531 | by setting a very small image size and trying | ||
532 | various palettes... The driver doesn't support | ||
533 | such small images, so I'm working around it. | ||
534 | */ | ||
535 | if (vm->format) | ||
536 | { | ||
537 | switch (vm->format) | ||
538 | { | ||
539 | case VIDEO_PALETTE_YUV420P: | ||
540 | case VIDEO_PALETTE_RAW: | ||
541 | break; | ||
542 | default: | ||
543 | return -EINVAL; | ||
544 | break; | ||
545 | } | ||
546 | } | ||
547 | |||
548 | if ((vm->width != pdev->view.x || vm->height != pdev->view.y) && | ||
549 | (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) { | ||
550 | int ret; | ||
551 | |||
552 | PWC_DEBUG_OPEN("VIDIOCMCAPTURE: changing size to please xawtv :-(.\n"); | ||
553 | ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot); | ||
554 | if (ret) | ||
555 | return ret; | ||
556 | } /* ... size mismatch */ | ||
557 | |||
558 | /* FIXME: should we lock here? */ | ||
559 | if (pdev->image_used[vm->frame]) | ||
560 | return -EBUSY; /* buffer wasn't available. Bummer */ | ||
561 | pdev->image_used[vm->frame] = 1; | ||
562 | |||
563 | /* Okay, we're done here. In the SYNC call we wait until a | ||
564 | frame comes available, then expand image into the given | ||
565 | buffer. | ||
566 | In contrast to the CPiA cam the Philips cams deliver a | ||
567 | constant stream, almost like a grabber card. Also, | ||
568 | we have separate buffers for the rawdata and the image, | ||
569 | meaning we can nearly always expand into the requested buffer. | ||
570 | */ | ||
571 | PWC_DEBUG_READ("VIDIOCMCAPTURE done.\n"); | ||
572 | break; | ||
573 | } | ||
574 | |||
575 | case VIDIOCSYNC: | ||
576 | { | ||
577 | /* The doc says: "Whenever a buffer is used it should | ||
578 | call VIDIOCSYNC to free this frame up and continue." | ||
579 | |||
580 | The only odd thing about this whole procedure is | ||
581 | that MCAPTURE flags the buffer as "in use", and | ||
582 | SYNC immediately unmarks it, while it isn't | ||
583 | after SYNC that you know that the buffer actually | ||
584 | got filled! So you better not start a CAPTURE in | ||
585 | the same frame immediately (use double buffering). | ||
586 | This is not a problem for this cam, since it has | ||
587 | extra intermediate buffers, but a hardware | ||
588 | grabber card will then overwrite the buffer | ||
589 | you're working on. | ||
590 | */ | ||
591 | int *mbuf = arg; | ||
592 | int ret; | ||
593 | |||
594 | PWC_DEBUG_READ("VIDIOCSYNC called (%d).\n", *mbuf); | ||
595 | |||
596 | /* bounds check */ | ||
597 | if (*mbuf < 0 || *mbuf >= pwc_mbufs) | ||
598 | return -EINVAL; | ||
599 | /* check if this buffer was requested anyway */ | ||
600 | if (pdev->image_used[*mbuf] == 0) | ||
601 | return -EINVAL; | ||
602 | |||
603 | /* Add ourselves to the frame wait-queue. | ||
604 | |||
605 | FIXME: needs auditing for safety. | ||
606 | QUESTION: In what respect? I think that using the | ||
607 | frameq is safe now. | ||
608 | */ | ||
609 | add_wait_queue(&pdev->frameq, &wait); | ||
610 | while (pdev->full_frames == NULL) { | ||
611 | /* Check for unplugged/etc. here */ | ||
612 | if (pdev->error_status) { | ||
613 | remove_wait_queue(&pdev->frameq, &wait); | ||
614 | set_current_state(TASK_RUNNING); | ||
615 | return -pdev->error_status; | ||
616 | } | ||
617 | |||
618 | if (signal_pending(current)) { | ||
619 | remove_wait_queue(&pdev->frameq, &wait); | ||
620 | set_current_state(TASK_RUNNING); | ||
621 | return -ERESTARTSYS; | ||
622 | } | ||
623 | schedule(); | ||
624 | set_current_state(TASK_INTERRUPTIBLE); | ||
625 | } | ||
626 | remove_wait_queue(&pdev->frameq, &wait); | ||
627 | set_current_state(TASK_RUNNING); | ||
628 | |||
629 | /* The frame is ready. Expand in the image buffer | ||
630 | requested by the user. I don't care if you | ||
631 | mmap() 5 buffers and request data in this order: | ||
632 | buffer 4 2 3 0 1 2 3 0 4 3 1 . . . | ||
633 | Grabber hardware may not be so forgiving. | ||
634 | */ | ||
635 | PWC_DEBUG_READ("VIDIOCSYNC: frame ready.\n"); | ||
636 | pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */ | ||
637 | /* Decompress, etc */ | ||
638 | ret = pwc_handle_frame(pdev); | ||
639 | pdev->image_used[*mbuf] = 0; | ||
640 | if (ret) | ||
641 | return -EFAULT; | ||
642 | break; | ||
643 | } | ||
644 | |||
645 | case VIDIOCGAUDIO: | ||
646 | { | ||
647 | struct video_audio *v = arg; | ||
648 | |||
649 | strcpy(v->name, "Microphone"); | ||
650 | v->audio = -1; /* unknown audio minor */ | ||
651 | v->flags = 0; | ||
652 | v->mode = VIDEO_SOUND_MONO; | ||
653 | v->volume = 0; | ||
654 | v->bass = 0; | ||
655 | v->treble = 0; | ||
656 | v->balance = 0x8000; | ||
657 | v->step = 1; | ||
658 | break; | ||
659 | } | ||
660 | |||
661 | case VIDIOCSAUDIO: | ||
662 | { | ||
663 | /* Dummy: nothing can be set */ | ||
664 | break; | ||
665 | } | ||
666 | |||
667 | case VIDIOCGUNIT: | ||
668 | { | ||
669 | struct video_unit *vu = arg; | ||
670 | |||
671 | vu->video = pdev->vdev->minor & 0x3F; | ||
672 | vu->audio = -1; /* not known yet */ | ||
673 | vu->vbi = -1; | ||
674 | vu->radio = -1; | ||
675 | vu->teletext = -1; | ||
676 | break; | ||
677 | } | ||
678 | |||
679 | /* V4L2 Layer */ | ||
680 | case VIDIOC_QUERYCAP: | ||
681 | { | ||
682 | struct v4l2_capability *cap = arg; | ||
683 | |||
684 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCAP) This application "\ | ||
685 | "try to use the v4l2 layer\n"); | ||
686 | strcpy(cap->driver,PWC_NAME); | ||
687 | strlcpy(cap->card, vdev->name, sizeof(cap->card)); | ||
688 | usb_make_path(pdev->udev,cap->bus_info,sizeof(cap->bus_info)); | ||
689 | cap->version = PWC_VERSION_CODE; | ||
690 | cap->capabilities = | ||
691 | V4L2_CAP_VIDEO_CAPTURE | | ||
692 | V4L2_CAP_STREAMING | | ||
693 | V4L2_CAP_READWRITE; | ||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | case VIDIOC_ENUMINPUT: | ||
698 | { | ||
699 | struct v4l2_input *i = arg; | ||
700 | |||
701 | if ( i->index ) /* Only one INPUT is supported */ | ||
702 | return -EINVAL; | ||
703 | |||
704 | memset(i, 0, sizeof(struct v4l2_input)); | ||
705 | strcpy(i->name, "usb"); | ||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | case VIDIOC_G_INPUT: | ||
710 | { | ||
711 | int *i = arg; | ||
712 | *i = 0; /* Only one INPUT is supported */ | ||
713 | return 0; | ||
714 | } | ||
715 | case VIDIOC_S_INPUT: | ||
716 | { | ||
717 | int *i = arg; | ||
718 | |||
719 | if ( *i ) { /* Only one INPUT is supported */ | ||
720 | PWC_DEBUG_IOCTL("Only one input source is"\ | ||
721 | " supported with this webcam.\n"); | ||
722 | return -EINVAL; | ||
723 | } | ||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | /* TODO: */ | ||
728 | case VIDIOC_QUERYCTRL: | ||
729 | { | ||
730 | struct v4l2_queryctrl *c = arg; | ||
731 | int i; | ||
732 | |||
733 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) query id=%d\n", c->id); | ||
734 | for (i=0; i<sizeof(pwc_controls)/sizeof(struct v4l2_queryctrl); i++) { | ||
735 | if (pwc_controls[i].id == c->id) { | ||
736 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n"); | ||
737 | memcpy(c,&pwc_controls[i],sizeof(struct v4l2_queryctrl)); | ||
738 | return 0; | ||
739 | } | ||
740 | } | ||
741 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) not found\n"); | ||
742 | |||
743 | return -EINVAL; | ||
744 | } | ||
745 | case VIDIOC_G_CTRL: | ||
746 | { | ||
747 | struct v4l2_control *c = arg; | ||
748 | int ret; | ||
749 | |||
750 | switch (c->id) | ||
751 | { | ||
752 | case V4L2_CID_BRIGHTNESS: | ||
753 | c->value = pwc_get_brightness(pdev); | ||
754 | if (c->value<0) | ||
755 | return -EINVAL; | ||
756 | return 0; | ||
757 | case V4L2_CID_CONTRAST: | ||
758 | c->value = pwc_get_contrast(pdev); | ||
759 | if (c->value<0) | ||
760 | return -EINVAL; | ||
761 | return 0; | ||
762 | case V4L2_CID_SATURATION: | ||
763 | ret = pwc_get_saturation(pdev, &c->value); | ||
764 | if (ret<0) | ||
765 | return -EINVAL; | ||
766 | return 0; | ||
767 | case V4L2_CID_GAMMA: | ||
768 | c->value = pwc_get_gamma(pdev); | ||
769 | if (c->value<0) | ||
770 | return -EINVAL; | ||
771 | return 0; | ||
772 | case V4L2_CID_RED_BALANCE: | ||
773 | ret = pwc_get_red_gain(pdev, &c->value); | ||
774 | if (ret<0) | ||
775 | return -EINVAL; | ||
776 | c->value >>= 8; | ||
777 | return 0; | ||
778 | case V4L2_CID_BLUE_BALANCE: | ||
779 | ret = pwc_get_blue_gain(pdev, &c->value); | ||
780 | if (ret<0) | ||
781 | return -EINVAL; | ||
782 | c->value >>= 8; | ||
783 | return 0; | ||
784 | case V4L2_CID_AUTO_WHITE_BALANCE: | ||
785 | ret = pwc_get_awb(pdev); | ||
786 | if (ret<0) | ||
787 | return -EINVAL; | ||
788 | c->value = (ret == PWC_WB_MANUAL)?0:1; | ||
789 | return 0; | ||
790 | case V4L2_CID_GAIN: | ||
791 | ret = pwc_get_agc(pdev, &c->value); | ||
792 | if (ret<0) | ||
793 | return -EINVAL; | ||
794 | c->value >>= 8; | ||
795 | return 0; | ||
796 | case V4L2_CID_AUTOGAIN: | ||
797 | ret = pwc_get_agc(pdev, &c->value); | ||
798 | if (ret<0) | ||
799 | return -EINVAL; | ||
800 | c->value = (c->value < 0)?1:0; | ||
801 | return 0; | ||
802 | case V4L2_CID_EXPOSURE: | ||
803 | ret = pwc_get_shutter_speed(pdev, &c->value); | ||
804 | if (ret<0) | ||
805 | return -EINVAL; | ||
806 | return 0; | ||
807 | case V4L2_CID_PRIVATE_COLOUR_MODE: | ||
808 | ret = pwc_get_colour_mode(pdev, &c->value); | ||
809 | if (ret < 0) | ||
810 | return -EINVAL; | ||
811 | return 0; | ||
812 | case V4L2_CID_PRIVATE_AUTOCONTOUR: | ||
813 | ret = pwc_get_contour(pdev, &c->value); | ||
814 | if (ret < 0) | ||
815 | return -EINVAL; | ||
816 | c->value=(c->value == -1?1:0); | ||
817 | return 0; | ||
818 | case V4L2_CID_PRIVATE_CONTOUR: | ||
819 | ret = pwc_get_contour(pdev, &c->value); | ||
820 | if (ret < 0) | ||
821 | return -EINVAL; | ||
822 | c->value >>= 10; | ||
823 | return 0; | ||
824 | case V4L2_CID_PRIVATE_BACKLIGHT: | ||
825 | ret = pwc_get_backlight(pdev, &c->value); | ||
826 | if (ret < 0) | ||
827 | return -EINVAL; | ||
828 | return 0; | ||
829 | case V4L2_CID_PRIVATE_FLICKERLESS: | ||
830 | ret = pwc_get_flicker(pdev, &c->value); | ||
831 | if (ret < 0) | ||
832 | return -EINVAL; | ||
833 | c->value=(c->value?1:0); | ||
834 | return 0; | ||
835 | case V4L2_CID_PRIVATE_NOISE_REDUCTION: | ||
836 | ret = pwc_get_dynamic_noise(pdev, &c->value); | ||
837 | if (ret < 0) | ||
838 | return -EINVAL; | ||
839 | return 0; | ||
840 | |||
841 | case V4L2_CID_PRIVATE_SAVE_USER: | ||
842 | case V4L2_CID_PRIVATE_RESTORE_USER: | ||
843 | case V4L2_CID_PRIVATE_RESTORE_FACTORY: | ||
844 | return -EINVAL; | ||
845 | } | ||
846 | return -EINVAL; | ||
847 | } | ||
848 | case VIDIOC_S_CTRL: | ||
849 | { | ||
850 | struct v4l2_control *c = arg; | ||
851 | int ret; | ||
852 | |||
853 | switch (c->id) | ||
854 | { | ||
855 | case V4L2_CID_BRIGHTNESS: | ||
856 | c->value <<= 9; | ||
857 | ret = pwc_set_brightness(pdev, c->value); | ||
858 | if (ret<0) | ||
859 | return -EINVAL; | ||
860 | return 0; | ||
861 | case V4L2_CID_CONTRAST: | ||
862 | c->value <<= 10; | ||
863 | ret = pwc_set_contrast(pdev, c->value); | ||
864 | if (ret<0) | ||
865 | return -EINVAL; | ||
866 | return 0; | ||
867 | case V4L2_CID_SATURATION: | ||
868 | ret = pwc_set_saturation(pdev, c->value); | ||
869 | if (ret<0) | ||
870 | return -EINVAL; | ||
871 | return 0; | ||
872 | case V4L2_CID_GAMMA: | ||
873 | c->value <<= 11; | ||
874 | ret = pwc_set_gamma(pdev, c->value); | ||
875 | if (ret<0) | ||
876 | return -EINVAL; | ||
877 | return 0; | ||
878 | case V4L2_CID_RED_BALANCE: | ||
879 | c->value <<= 8; | ||
880 | ret = pwc_set_red_gain(pdev, c->value); | ||
881 | if (ret<0) | ||
882 | return -EINVAL; | ||
883 | return 0; | ||
884 | case V4L2_CID_BLUE_BALANCE: | ||
885 | c->value <<= 8; | ||
886 | ret = pwc_set_blue_gain(pdev, c->value); | ||
887 | if (ret<0) | ||
888 | return -EINVAL; | ||
889 | return 0; | ||
890 | case V4L2_CID_AUTO_WHITE_BALANCE: | ||
891 | c->value = (c->value == 0)?PWC_WB_MANUAL:PWC_WB_AUTO; | ||
892 | ret = pwc_set_awb(pdev, c->value); | ||
893 | if (ret<0) | ||
894 | return -EINVAL; | ||
895 | return 0; | ||
896 | case V4L2_CID_EXPOSURE: | ||
897 | c->value <<= 8; | ||
898 | ret = pwc_set_shutter_speed(pdev, c->value?0:1, c->value); | ||
899 | if (ret<0) | ||
900 | return -EINVAL; | ||
901 | return 0; | ||
902 | case V4L2_CID_AUTOGAIN: | ||
903 | /* autogain off means nothing without a gain */ | ||
904 | if (c->value == 0) | ||
905 | return 0; | ||
906 | ret = pwc_set_agc(pdev, c->value, 0); | ||
907 | if (ret<0) | ||
908 | return -EINVAL; | ||
909 | return 0; | ||
910 | case V4L2_CID_GAIN: | ||
911 | c->value <<= 8; | ||
912 | ret = pwc_set_agc(pdev, 0, c->value); | ||
913 | if (ret<0) | ||
914 | return -EINVAL; | ||
915 | return 0; | ||
916 | case V4L2_CID_PRIVATE_SAVE_USER: | ||
917 | if (pwc_save_user(pdev)) | ||
918 | return -EINVAL; | ||
919 | return 0; | ||
920 | case V4L2_CID_PRIVATE_RESTORE_USER: | ||
921 | if (pwc_restore_user(pdev)) | ||
922 | return -EINVAL; | ||
923 | return 0; | ||
924 | case V4L2_CID_PRIVATE_RESTORE_FACTORY: | ||
925 | if (pwc_restore_factory(pdev)) | ||
926 | return -EINVAL; | ||
927 | return 0; | ||
928 | case V4L2_CID_PRIVATE_COLOUR_MODE: | ||
929 | ret = pwc_set_colour_mode(pdev, c->value); | ||
930 | if (ret < 0) | ||
931 | return -EINVAL; | ||
932 | return 0; | ||
933 | case V4L2_CID_PRIVATE_AUTOCONTOUR: | ||
934 | c->value=(c->value == 1)?-1:0; | ||
935 | ret = pwc_set_contour(pdev, c->value); | ||
936 | if (ret < 0) | ||
937 | return -EINVAL; | ||
938 | return 0; | ||
939 | case V4L2_CID_PRIVATE_CONTOUR: | ||
940 | c->value <<= 10; | ||
941 | ret = pwc_set_contour(pdev, c->value); | ||
942 | if (ret < 0) | ||
943 | return -EINVAL; | ||
944 | return 0; | ||
945 | case V4L2_CID_PRIVATE_BACKLIGHT: | ||
946 | ret = pwc_set_backlight(pdev, c->value); | ||
947 | if (ret < 0) | ||
948 | return -EINVAL; | ||
949 | return 0; | ||
950 | case V4L2_CID_PRIVATE_FLICKERLESS: | ||
951 | ret = pwc_set_flicker(pdev, c->value); | ||
952 | if (ret < 0) | ||
953 | return -EINVAL; | ||
954 | case V4L2_CID_PRIVATE_NOISE_REDUCTION: | ||
955 | ret = pwc_set_dynamic_noise(pdev, c->value); | ||
956 | if (ret < 0) | ||
957 | return -EINVAL; | ||
958 | return 0; | ||
959 | |||
960 | } | ||
961 | return -EINVAL; | ||
962 | } | ||
963 | |||
964 | case VIDIOC_ENUM_FMT: | ||
965 | { | ||
966 | struct v4l2_fmtdesc *f = arg; | ||
967 | int index; | ||
968 | |||
969 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
970 | return -EINVAL; | ||
971 | |||
972 | /* We only support two format: the raw format, and YUV */ | ||
973 | index = f->index; | ||
974 | memset(f,0,sizeof(struct v4l2_fmtdesc)); | ||
975 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
976 | f->index = index; | ||
977 | switch(index) | ||
978 | { | ||
979 | case 0: | ||
980 | /* RAW format */ | ||
981 | f->pixelformat = pdev->type<=646?V4L2_PIX_FMT_PWC1:V4L2_PIX_FMT_PWC2; | ||
982 | f->flags = V4L2_FMT_FLAG_COMPRESSED; | ||
983 | strlcpy(f->description,"Raw Philips Webcam",sizeof(f->description)); | ||
984 | break; | ||
985 | case 1: | ||
986 | f->pixelformat = V4L2_PIX_FMT_YUV420; | ||
987 | strlcpy(f->description,"4:2:0, planar, Y-Cb-Cr",sizeof(f->description)); | ||
988 | break; | ||
989 | default: | ||
990 | return -EINVAL; | ||
991 | } | ||
992 | return 0; | ||
993 | } | ||
994 | |||
995 | case VIDIOC_G_FMT: | ||
996 | { | ||
997 | struct v4l2_format *f = arg; | ||
998 | |||
999 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",pdev->image.x,pdev->image.y); | ||
1000 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1001 | return -EINVAL; | ||
1002 | |||
1003 | pwc_vidioc_fill_fmt(pdev, f); | ||
1004 | |||
1005 | return 0; | ||
1006 | } | ||
1007 | |||
1008 | case VIDIOC_TRY_FMT: | ||
1009 | return pwc_vidioc_try_fmt(pdev, arg); | ||
1010 | |||
1011 | case VIDIOC_S_FMT: | ||
1012 | return pwc_vidioc_set_fmt(pdev, arg); | ||
1013 | |||
1014 | case VIDIOC_G_STD: | ||
1015 | { | ||
1016 | v4l2_std_id *std = arg; | ||
1017 | *std = V4L2_STD_UNKNOWN; | ||
1018 | return 0; | ||
1019 | } | ||
1020 | |||
1021 | case VIDIOC_S_STD: | ||
1022 | { | ||
1023 | v4l2_std_id *std = arg; | ||
1024 | if (*std != V4L2_STD_UNKNOWN) | ||
1025 | return -EINVAL; | ||
1026 | return 0; | ||
1027 | } | ||
1028 | |||
1029 | case VIDIOC_ENUMSTD: | ||
1030 | { | ||
1031 | struct v4l2_standard *std = arg; | ||
1032 | if (std->index != 0) | ||
1033 | return -EINVAL; | ||
1034 | std->id = V4L2_STD_UNKNOWN; | ||
1035 | strncpy(std->name, "webcam", sizeof(std->name)); | ||
1036 | return 0; | ||
1037 | } | ||
1038 | |||
1039 | case VIDIOC_REQBUFS: | ||
1040 | { | ||
1041 | struct v4l2_requestbuffers *rb = arg; | ||
1042 | int nbuffers; | ||
1043 | |||
1044 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n",rb->count); | ||
1045 | if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1046 | return -EINVAL; | ||
1047 | if (rb->memory != V4L2_MEMORY_MMAP) | ||
1048 | return -EINVAL; | ||
1049 | |||
1050 | nbuffers = rb->count; | ||
1051 | if (nbuffers < 2) | ||
1052 | nbuffers = 2; | ||
1053 | else if (nbuffers > pwc_mbufs) | ||
1054 | nbuffers = pwc_mbufs; | ||
1055 | /* Force to use our # of buffers */ | ||
1056 | rb->count = pwc_mbufs; | ||
1057 | return 0; | ||
1058 | } | ||
1059 | |||
1060 | case VIDIOC_QUERYBUF: | ||
1061 | { | ||
1062 | struct v4l2_buffer *buf = arg; | ||
1063 | int index; | ||
1064 | |||
1065 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n",buf->index); | ||
1066 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1067 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n"); | ||
1068 | return -EINVAL; | ||
1069 | } | ||
1070 | if (buf->memory != V4L2_MEMORY_MMAP) { | ||
1071 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad memory type\n"); | ||
1072 | return -EINVAL; | ||
1073 | } | ||
1074 | index = buf->index; | ||
1075 | if (index < 0 || index >= pwc_mbufs) { | ||
1076 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index); | ||
1077 | return -EINVAL; | ||
1078 | } | ||
1079 | |||
1080 | memset(buf, 0, sizeof(struct v4l2_buffer)); | ||
1081 | buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1082 | buf->index = index; | ||
1083 | buf->m.offset = index * pdev->len_per_image; | ||
1084 | if (pdev->vpalette == VIDEO_PALETTE_RAW) | ||
1085 | buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame); | ||
1086 | else | ||
1087 | buf->bytesused = pdev->view.size; | ||
1088 | buf->field = V4L2_FIELD_NONE; | ||
1089 | buf->memory = V4L2_MEMORY_MMAP; | ||
1090 | //buf->flags = V4L2_BUF_FLAG_MAPPED; | ||
1091 | buf->length = pdev->len_per_image; | ||
1092 | |||
1093 | PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n",buf->index); | ||
1094 | PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n",buf->m.offset); | ||
1095 | PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n",buf->bytesused); | ||
1096 | |||
1097 | return 0; | ||
1098 | } | ||
1099 | |||
1100 | case VIDIOC_QBUF: | ||
1101 | { | ||
1102 | struct v4l2_buffer *buf = arg; | ||
1103 | |||
1104 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n",buf->index); | ||
1105 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1106 | return -EINVAL; | ||
1107 | if (buf->memory != V4L2_MEMORY_MMAP) | ||
1108 | return -EINVAL; | ||
1109 | if (buf->index < 0 || buf->index >= pwc_mbufs) | ||
1110 | return -EINVAL; | ||
1111 | |||
1112 | buf->flags |= V4L2_BUF_FLAG_QUEUED; | ||
1113 | buf->flags &= ~V4L2_BUF_FLAG_DONE; | ||
1114 | |||
1115 | return 0; | ||
1116 | } | ||
1117 | |||
1118 | case VIDIOC_DQBUF: | ||
1119 | { | ||
1120 | struct v4l2_buffer *buf = arg; | ||
1121 | int ret; | ||
1122 | |||
1123 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n"); | ||
1124 | |||
1125 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1126 | return -EINVAL; | ||
1127 | |||
1128 | /* Add ourselves to the frame wait-queue. | ||
1129 | |||
1130 | FIXME: needs auditing for safety. | ||
1131 | QUESTION: In what respect? I think that using the | ||
1132 | frameq is safe now. | ||
1133 | */ | ||
1134 | add_wait_queue(&pdev->frameq, &wait); | ||
1135 | while (pdev->full_frames == NULL) { | ||
1136 | if (pdev->error_status) { | ||
1137 | remove_wait_queue(&pdev->frameq, &wait); | ||
1138 | set_current_state(TASK_RUNNING); | ||
1139 | return -pdev->error_status; | ||
1140 | } | ||
1141 | |||
1142 | if (signal_pending(current)) { | ||
1143 | remove_wait_queue(&pdev->frameq, &wait); | ||
1144 | set_current_state(TASK_RUNNING); | ||
1145 | return -ERESTARTSYS; | ||
1146 | } | ||
1147 | schedule(); | ||
1148 | set_current_state(TASK_INTERRUPTIBLE); | ||
1149 | } | ||
1150 | remove_wait_queue(&pdev->frameq, &wait); | ||
1151 | set_current_state(TASK_RUNNING); | ||
1152 | |||
1153 | PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n"); | ||
1154 | /* Decompress data in pdev->images[pdev->fill_image] */ | ||
1155 | ret = pwc_handle_frame(pdev); | ||
1156 | if (ret) | ||
1157 | return -EFAULT; | ||
1158 | PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n"); | ||
1159 | |||
1160 | buf->index = pdev->fill_image; | ||
1161 | if (pdev->vpalette == VIDEO_PALETTE_RAW) | ||
1162 | buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame); | ||
1163 | else | ||
1164 | buf->bytesused = pdev->view.size; | ||
1165 | buf->flags = V4L2_BUF_FLAG_MAPPED; | ||
1166 | buf->field = V4L2_FIELD_NONE; | ||
1167 | do_gettimeofday(&buf->timestamp); | ||
1168 | buf->sequence = 0; | ||
1169 | buf->memory = V4L2_MEMORY_MMAP; | ||
1170 | buf->m.offset = pdev->fill_image * pdev->len_per_image; | ||
1171 | buf->length = buf->bytesused; | ||
1172 | pwc_next_image(pdev); | ||
1173 | |||
1174 | PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n",buf->index); | ||
1175 | PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n",buf->length); | ||
1176 | PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n",buf->m.offset); | ||
1177 | PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n",buf->bytesused); | ||
1178 | PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n"); | ||
1179 | return 0; | ||
1180 | |||
1181 | } | ||
1182 | |||
1183 | case VIDIOC_STREAMON: | ||
1184 | { | ||
1185 | /* WARNING: pwc_try_video_mode() called pwc_isoc_init */ | ||
1186 | pwc_isoc_init(pdev); | ||
1187 | return 0; | ||
1188 | } | ||
1189 | |||
1190 | case VIDIOC_STREAMOFF: | ||
1191 | { | ||
1192 | pwc_isoc_cleanup(pdev); | ||
1193 | return 0; | ||
1194 | } | ||
1195 | |||
1196 | default: | ||
1197 | return pwc_ioctl(pdev, cmd, arg); | ||
1198 | } /* ..switch */ | ||
1199 | return 0; | ||
1200 | } | ||
1201 | |||
1202 | /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | ||
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 1b0ee0ced0ed..629f79e44fb6 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* (C) 1999-2003 Nemosoft Unv. | 1 | /* (C) 1999-2003 Nemosoft Unv. |
2 | (C) 2004 Luc Saillard (luc@saillard.org) | 2 | (C) 2004-2006 Luc Saillard (luc@saillard.org) |
3 | 3 | ||
4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 4 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx |
5 | driver and thus may have bugs that are not present in the original version. | 5 | driver and thus may have bugs that are not present in the original version. |
@@ -29,51 +29,87 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/usb.h> | 30 | #include <linux/usb.h> |
31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
32 | #include <linux/videodev.h> | ||
33 | #include <linux/wait.h> | 32 | #include <linux/wait.h> |
34 | #include <linux/smp_lock.h> | 33 | #include <linux/smp_lock.h> |
34 | #include <linux/version.h> | ||
35 | #include <asm/semaphore.h> | 35 | #include <asm/semaphore.h> |
36 | #include <asm/errno.h> | 36 | #include <asm/errno.h> |
37 | #include <linux/videodev.h> | ||
38 | #include <media/v4l2-common.h> | ||
37 | 39 | ||
38 | #include "pwc-uncompress.h" | 40 | #include "pwc-uncompress.h" |
39 | #include "pwc-ioctl.h" | 41 | #include <media/pwc-ioctl.h> |
40 | |||
41 | /* Defines and structures for the Philips webcam */ | ||
42 | /* Used for checking memory corruption/pointer validation */ | ||
43 | #define PWC_MAGIC 0x89DC10ABUL | ||
44 | #undef PWC_MAGIC | ||
45 | 42 | ||
46 | /* Turn some debugging options on/off */ | 43 | /* Turn some debugging options on/off */ |
47 | #define PWC_DEBUG 0 | 44 | #ifndef CONFIG_PWC_DEBUG |
45 | #define CONFIG_PWC_DEBUG 1 | ||
46 | #endif | ||
47 | |||
48 | /* Version block */ | ||
49 | #define PWC_MAJOR 10 | ||
50 | #define PWC_MINOR 0 | ||
51 | #define PWC_EXTRAMINOR 12 | ||
52 | #define PWC_VERSION_CODE KERNEL_VERSION(PWC_MAJOR,PWC_MINOR,PWC_EXTRAMINOR) | ||
53 | #define PWC_VERSION "10.0.12" | ||
54 | #define PWC_NAME "pwc" | ||
55 | #define PFX PWC_NAME ": " | ||
56 | |||
48 | 57 | ||
49 | /* Trace certain actions in the driver */ | 58 | /* Trace certain actions in the driver */ |
50 | #define TRACE_MODULE 0x0001 | 59 | #define PWC_DEBUG_LEVEL_MODULE (1<<0) |
51 | #define TRACE_PROBE 0x0002 | 60 | #define PWC_DEBUG_LEVEL_PROBE (1<<1) |
52 | #define TRACE_OPEN 0x0004 | 61 | #define PWC_DEBUG_LEVEL_OPEN (1<<2) |
53 | #define TRACE_READ 0x0008 | 62 | #define PWC_DEBUG_LEVEL_READ (1<<3) |
54 | #define TRACE_MEMORY 0x0010 | 63 | #define PWC_DEBUG_LEVEL_MEMORY (1<<4) |
55 | #define TRACE_FLOW 0x0020 | 64 | #define PWC_DEBUG_LEVEL_FLOW (1<<5) |
56 | #define TRACE_SIZE 0x0040 | 65 | #define PWC_DEBUG_LEVEL_SIZE (1<<6) |
57 | #define TRACE_PWCX 0x0080 | 66 | #define PWC_DEBUG_LEVEL_IOCTL (1<<7) |
58 | #define TRACE_SEQUENCE 0x1000 | 67 | #define PWC_DEBUG_LEVEL_TRACE (1<<8) |
59 | 68 | ||
60 | #define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A) | 69 | #define PWC_DEBUG_MODULE(fmt, args...) PWC_DEBUG(MODULE, fmt, ##args) |
61 | #define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A) | 70 | #define PWC_DEBUG_PROBE(fmt, args...) PWC_DEBUG(PROBE, fmt, ##args) |
62 | #define Info(A...) printk(KERN_INFO PWC_NAME " " A) | 71 | #define PWC_DEBUG_OPEN(fmt, args...) PWC_DEBUG(OPEN, fmt, ##args) |
63 | #define Err(A...) printk(KERN_ERR PWC_NAME " " A) | 72 | #define PWC_DEBUG_READ(fmt, args...) PWC_DEBUG(READ, fmt, ##args) |
73 | #define PWC_DEBUG_MEMORY(fmt, args...) PWC_DEBUG(MEMORY, fmt, ##args) | ||
74 | #define PWC_DEBUG_FLOW(fmt, args...) PWC_DEBUG(FLOW, fmt, ##args) | ||
75 | #define PWC_DEBUG_SIZE(fmt, args...) PWC_DEBUG(SIZE, fmt, ##args) | ||
76 | #define PWC_DEBUG_IOCTL(fmt, args...) PWC_DEBUG(IOCTL, fmt, ##args) | ||
77 | #define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args) | ||
78 | |||
79 | |||
80 | #if CONFIG_PWC_DEBUG | ||
81 | |||
82 | #define PWC_DEBUG_LEVEL (PWC_DEBUG_LEVEL_MODULE) | ||
83 | |||
84 | #define PWC_DEBUG(level, fmt, args...) do {\ | ||
85 | if ((PWC_DEBUG_LEVEL_ ##level) & pwc_trace) \ | ||
86 | printk(KERN_DEBUG PFX fmt, ##args); \ | ||
87 | } while(0) | ||
88 | |||
89 | #define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args) | ||
90 | #define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args) | ||
91 | #define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args) | ||
92 | #define PWC_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args) | ||
93 | |||
94 | #else /* if ! CONFIG_PWC_DEBUG */ | ||
95 | |||
96 | #define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args) | ||
97 | #define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args) | ||
98 | #define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args) | ||
99 | #define PWC_TRACE(fmt, args...) do { } while(0) | ||
100 | #define PWC_DEBUG(level, fmt, args...) do { } while(0) | ||
101 | |||
102 | #define pwc_trace 0 | ||
64 | 103 | ||
104 | #endif | ||
65 | 105 | ||
66 | /* Defines for ToUCam cameras */ | 106 | /* Defines for ToUCam cameras */ |
67 | #define TOUCAM_HEADER_SIZE 8 | 107 | #define TOUCAM_HEADER_SIZE 8 |
68 | #define TOUCAM_TRAILER_SIZE 4 | 108 | #define TOUCAM_TRAILER_SIZE 4 |
69 | 109 | ||
70 | #define FEATURE_MOTOR_PANTILT 0x0001 | 110 | #define FEATURE_MOTOR_PANTILT 0x0001 |
71 | 111 | #define FEATURE_CODEC1 0x0002 | |
72 | /* Version block */ | 112 | #define FEATURE_CODEC2 0x0004 |
73 | #define PWC_MAJOR 9 | ||
74 | #define PWC_MINOR 0 | ||
75 | #define PWC_VERSION "9.0.2-unofficial" | ||
76 | #define PWC_NAME "pwc" | ||
77 | 113 | ||
78 | /* Turn certain features on/off */ | 114 | /* Turn certain features on/off */ |
79 | #define PWC_INT_PIPE 0 | 115 | #define PWC_INT_PIPE 0 |
@@ -95,6 +131,18 @@ | |||
95 | /* Absolute maximum number of buffers available for mmap() */ | 131 | /* Absolute maximum number of buffers available for mmap() */ |
96 | #define MAX_IMAGES 10 | 132 | #define MAX_IMAGES 10 |
97 | 133 | ||
134 | /* Some macros to quickly find the type of a webcam */ | ||
135 | #define DEVICE_USE_CODEC1(x) ((x)<675) | ||
136 | #define DEVICE_USE_CODEC2(x) ((x)>=675 && (x)<700) | ||
137 | #define DEVICE_USE_CODEC3(x) ((x)>=700) | ||
138 | #define DEVICE_USE_CODEC23(x) ((x)>=675) | ||
139 | |||
140 | |||
141 | #ifndef V4L2_PIX_FMT_PWC1 | ||
142 | #define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P','W','C','1') | ||
143 | #define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P','W','C','2') | ||
144 | #endif | ||
145 | |||
98 | /* The following structures were based on cpia.h. Why reinvent the wheel? :-) */ | 146 | /* The following structures were based on cpia.h. Why reinvent the wheel? :-) */ |
99 | struct pwc_iso_buf | 147 | struct pwc_iso_buf |
100 | { | 148 | { |
@@ -110,17 +158,19 @@ struct pwc_frame_buf | |||
110 | void *data; | 158 | void *data; |
111 | volatile int filled; /* number of bytes filled */ | 159 | volatile int filled; /* number of bytes filled */ |
112 | struct pwc_frame_buf *next; /* list */ | 160 | struct pwc_frame_buf *next; /* list */ |
113 | #if PWC_DEBUG | 161 | }; |
114 | int sequence; /* Sequence number */ | 162 | |
115 | #endif | 163 | /* additionnal informations used when dealing image between kernel and userland */ |
164 | struct pwc_imgbuf | ||
165 | { | ||
166 | unsigned long offset; /* offset of this buffer in the big array of image_data */ | ||
167 | int vma_use_count; /* count the number of time this memory is mapped */ | ||
116 | }; | 168 | }; |
117 | 169 | ||
118 | struct pwc_device | 170 | struct pwc_device |
119 | { | 171 | { |
120 | struct video_device *vdev; | 172 | struct video_device *vdev; |
121 | #ifdef PWC_MAGIC | 173 | |
122 | int magic; | ||
123 | #endif | ||
124 | /* Pointer to our usb_device */ | 174 | /* Pointer to our usb_device */ |
125 | struct usb_device *udev; | 175 | struct usb_device *udev; |
126 | 176 | ||
@@ -177,12 +227,8 @@ struct pwc_device | |||
177 | int frame_size; | 227 | int frame_size; |
178 | int frame_total_size; /* including header & trailer */ | 228 | int frame_total_size; /* including header & trailer */ |
179 | int drop_frames; | 229 | int drop_frames; |
180 | #if PWC_DEBUG | ||
181 | int sequence; /* Debugging aid */ | ||
182 | #endif | ||
183 | 230 | ||
184 | /* 3: decompression */ | 231 | /* 3: decompression */ |
185 | struct pwc_decompressor *decompressor; /* function block with decompression routines */ | ||
186 | void *decompress_data; /* private data for decompression engine */ | 232 | void *decompress_data; /* private data for decompression engine */ |
187 | 233 | ||
188 | /* 4: image */ | 234 | /* 4: image */ |
@@ -198,7 +244,7 @@ struct pwc_device | |||
198 | struct pwc_coord offset; /* offset within the viewport */ | 244 | struct pwc_coord offset; /* offset within the viewport */ |
199 | 245 | ||
200 | void *image_data; /* total buffer, which is subdivided into ... */ | 246 | void *image_data; /* total buffer, which is subdivided into ... */ |
201 | void *image_ptr[MAX_IMAGES]; /* ...several images... */ | 247 | struct pwc_imgbuf images[MAX_IMAGES];/* ...several images... */ |
202 | int fill_image; /* ...which are rotated. */ | 248 | int fill_image; /* ...which are rotated. */ |
203 | int len_per_image; /* length per image */ | 249 | int len_per_image; /* length per image */ |
204 | int image_read_pos; /* In case we read data in pieces, keep track of were we are in the imagebuffer */ | 250 | int image_read_pos; /* In case we read data in pieces, keep track of were we are in the imagebuffer */ |
@@ -211,6 +257,7 @@ struct pwc_device | |||
211 | struct pwc_mpt_range angle_range; | 257 | struct pwc_mpt_range angle_range; |
212 | int pan_angle; /* in degrees * 100 */ | 258 | int pan_angle; /* in degrees * 100 */ |
213 | int tilt_angle; /* absolute angle; 0,0 is home position */ | 259 | int tilt_angle; /* absolute angle; 0,0 is home position */ |
260 | int snapshot_button_status; /* set to 1 when the user push the button, reset to 0 when this value is read */ | ||
214 | 261 | ||
215 | /*** Misc. data ***/ | 262 | /*** Misc. data ***/ |
216 | wait_queue_head_t frameq; /* When waiting for a frame to finish... */ | 263 | wait_queue_head_t frameq; /* When waiting for a frame to finish... */ |
@@ -219,20 +266,26 @@ struct pwc_device | |||
219 | #endif | 266 | #endif |
220 | }; | 267 | }; |
221 | 268 | ||
222 | |||
223 | #ifdef __cplusplus | 269 | #ifdef __cplusplus |
224 | extern "C" { | 270 | extern "C" { |
225 | #endif | 271 | #endif |
226 | 272 | ||
227 | /* Global variable */ | 273 | /* Global variables */ |
274 | #if CONFIG_PWC_DEBUG | ||
228 | extern int pwc_trace; | 275 | extern int pwc_trace; |
276 | #endif | ||
277 | extern int pwc_mbufs; | ||
229 | 278 | ||
230 | /** functions in pwc-if.c */ | 279 | /** functions in pwc-if.c */ |
231 | int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot); | 280 | int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot); |
281 | int pwc_handle_frame(struct pwc_device *pdev); | ||
282 | void pwc_next_image(struct pwc_device *pdev); | ||
283 | int pwc_isoc_init(struct pwc_device *pdev); | ||
284 | void pwc_isoc_cleanup(struct pwc_device *pdev); | ||
232 | 285 | ||
233 | /** Functions in pwc-misc.c */ | 286 | /** Functions in pwc-misc.c */ |
234 | /* sizes in pixels */ | 287 | /* sizes in pixels */ |
235 | extern struct pwc_coord pwc_image_sizes[PSZ_MAX]; | 288 | extern const struct pwc_coord pwc_image_sizes[PSZ_MAX]; |
236 | 289 | ||
237 | int pwc_decode_size(struct pwc_device *pdev, int width, int height); | 290 | int pwc_decode_size(struct pwc_device *pdev, int width, int height); |
238 | void pwc_construct(struct pwc_device *pdev); | 291 | void pwc_construct(struct pwc_device *pdev); |
@@ -240,6 +293,9 @@ void pwc_construct(struct pwc_device *pdev); | |||
240 | /** Functions in pwc-ctrl.c */ | 293 | /** Functions in pwc-ctrl.c */ |
241 | /* Request a certain video mode. Returns < 0 if not possible */ | 294 | /* Request a certain video mode. Returns < 0 if not possible */ |
242 | extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot); | 295 | extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot); |
296 | /* Calculate the number of bytes per image (not frame) */ | ||
297 | extern int pwc_mpt_reset(struct pwc_device *pdev, int flags); | ||
298 | extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt); | ||
243 | 299 | ||
244 | /* Various controls; should be obvious. Value 0..65535, or < 0 on error */ | 300 | /* Various controls; should be obvious. Value 0..65535, or < 0 on error */ |
245 | extern int pwc_get_brightness(struct pwc_device *pdev); | 301 | extern int pwc_get_brightness(struct pwc_device *pdev); |
@@ -248,10 +304,36 @@ extern int pwc_get_contrast(struct pwc_device *pdev); | |||
248 | extern int pwc_set_contrast(struct pwc_device *pdev, int value); | 304 | extern int pwc_set_contrast(struct pwc_device *pdev, int value); |
249 | extern int pwc_get_gamma(struct pwc_device *pdev); | 305 | extern int pwc_get_gamma(struct pwc_device *pdev); |
250 | extern int pwc_set_gamma(struct pwc_device *pdev, int value); | 306 | extern int pwc_set_gamma(struct pwc_device *pdev, int value); |
251 | extern int pwc_get_saturation(struct pwc_device *pdev); | 307 | extern int pwc_get_saturation(struct pwc_device *pdev, int *value); |
252 | extern int pwc_set_saturation(struct pwc_device *pdev, int value); | 308 | extern int pwc_set_saturation(struct pwc_device *pdev, int value); |
253 | extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value); | 309 | extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value); |
254 | extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor); | 310 | extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor); |
311 | extern int pwc_restore_user(struct pwc_device *pdev); | ||
312 | extern int pwc_save_user(struct pwc_device *pdev); | ||
313 | extern int pwc_restore_factory(struct pwc_device *pdev); | ||
314 | |||
315 | /* exported for use by v4l2 controls */ | ||
316 | extern int pwc_get_red_gain(struct pwc_device *pdev, int *value); | ||
317 | extern int pwc_set_red_gain(struct pwc_device *pdev, int value); | ||
318 | extern int pwc_get_blue_gain(struct pwc_device *pdev, int *value); | ||
319 | extern int pwc_set_blue_gain(struct pwc_device *pdev, int value); | ||
320 | extern int pwc_get_awb(struct pwc_device *pdev); | ||
321 | extern int pwc_set_awb(struct pwc_device *pdev, int mode); | ||
322 | extern int pwc_set_agc(struct pwc_device *pdev, int mode, int value); | ||
323 | extern int pwc_get_agc(struct pwc_device *pdev, int *value); | ||
324 | extern int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value); | ||
325 | extern int pwc_get_shutter_speed(struct pwc_device *pdev, int *value); | ||
326 | |||
327 | extern int pwc_set_colour_mode(struct pwc_device *pdev, int colour); | ||
328 | extern int pwc_get_colour_mode(struct pwc_device *pdev, int *colour); | ||
329 | extern int pwc_set_contour(struct pwc_device *pdev, int contour); | ||
330 | extern int pwc_get_contour(struct pwc_device *pdev, int *contour); | ||
331 | extern int pwc_set_backlight(struct pwc_device *pdev, int backlight); | ||
332 | extern int pwc_get_backlight(struct pwc_device *pdev, int *backlight); | ||
333 | extern int pwc_set_flicker(struct pwc_device *pdev, int flicker); | ||
334 | extern int pwc_get_flicker(struct pwc_device *pdev, int *flicker); | ||
335 | extern int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise); | ||
336 | extern int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise); | ||
255 | 337 | ||
256 | /* Power down or up the camera; not supported by all models */ | 338 | /* Power down or up the camera; not supported by all models */ |
257 | extern int pwc_camera_power(struct pwc_device *pdev, int power); | 339 | extern int pwc_camera_power(struct pwc_device *pdev, int power); |
@@ -259,6 +341,9 @@ extern int pwc_camera_power(struct pwc_device *pdev, int power); | |||
259 | /* Private ioctl()s; see pwc-ioctl.h */ | 341 | /* Private ioctl()s; see pwc-ioctl.h */ |
260 | extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg); | 342 | extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg); |
261 | 343 | ||
344 | /** Functions in pwc-v4l.c */ | ||
345 | extern int pwc_video_do_ioctl(struct inode *inode, struct file *file, | ||
346 | unsigned int cmd, void *arg); | ||
262 | 347 | ||
263 | /** pwc-uncompress.c */ | 348 | /** pwc-uncompress.c */ |
264 | /* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */ | 349 | /* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */ |
@@ -270,3 +355,4 @@ extern int pwc_decompress(struct pwc_device *pdev); | |||
270 | 355 | ||
271 | 356 | ||
272 | #endif | 357 | #endif |
358 | /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | ||
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index dd830e0e5e96..59a187272c83 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/i2c.h> | 46 | #include <linux/i2c.h> |
47 | #include <linux/videotext.h> | 47 | #include <linux/videotext.h> |
48 | #include <linux/videodev.h> | 48 | #include <linux/videodev.h> |
49 | #include <media/v4l2-common.h> | ||
49 | #include <linux/mutex.h> | 50 | #include <linux/mutex.h> |
50 | 51 | ||
51 | #include "saa5246a.h" | 52 | #include "saa5246a.h" |
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 531e9461cb66..19a8d65699f8 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/i2c.h> | 56 | #include <linux/i2c.h> |
57 | #include <linux/videotext.h> | 57 | #include <linux/videotext.h> |
58 | #include <linux/videodev.h> | 58 | #include <linux/videodev.h> |
59 | #include <media/v4l2-common.h> | ||
59 | #include <linux/mutex.h> | 60 | #include <linux/mutex.h> |
60 | 61 | ||
61 | 62 | ||
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 41d951db6ec0..676b9970eb2e 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c | |||
@@ -43,6 +43,7 @@ MODULE_LICENSE("GPL"); | |||
43 | #define I2C_NAME(s) (s)->name | 43 | #define I2C_NAME(s) (s)->name |
44 | 44 | ||
45 | #include <linux/videodev.h> | 45 | #include <linux/videodev.h> |
46 | #include <media/v4l2-common.h> | ||
46 | #include <linux/video_decoder.h> | 47 | #include <linux/video_decoder.h> |
47 | 48 | ||
48 | static int debug = 0; | 49 | static int debug = 0; |
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index dceebc0b1250..b59c11717273 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -72,6 +72,10 @@ struct saa7115_state { | |||
72 | int sat; | 72 | int sat; |
73 | enum v4l2_chip_ident ident; | 73 | enum v4l2_chip_ident ident; |
74 | u32 audclk_freq; | 74 | u32 audclk_freq; |
75 | u32 crystal_freq; | ||
76 | u8 ucgc; | ||
77 | u8 cgcdiv; | ||
78 | u8 apll; | ||
75 | }; | 79 | }; |
76 | 80 | ||
77 | /* ----------------------------------------------------------------------- */ | 81 | /* ----------------------------------------------------------------------- */ |
@@ -375,10 +379,6 @@ static const unsigned char saa7113_init_auto_input[] = { | |||
375 | }; | 379 | }; |
376 | 380 | ||
377 | static const unsigned char saa7115_init_misc[] = { | 381 | static const unsigned char saa7115_init_misc[] = { |
378 | 0x38, 0x03, /* audio stuff */ | ||
379 | 0x39, 0x10, | ||
380 | 0x3a, 0x08, | ||
381 | |||
382 | 0x81, 0x01, /* reg 0x15,0x16 define blanking window */ | 382 | 0x81, 0x01, /* reg 0x15,0x16 define blanking window */ |
383 | 0x82, 0x00, | 383 | 0x82, 0x00, |
384 | 0x83, 0x01, /* I port settings */ | 384 | 0x83, 0x01, /* I port settings */ |
@@ -584,6 +584,7 @@ static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq) | |||
584 | u32 acni; | 584 | u32 acni; |
585 | u32 hz; | 585 | u32 hz; |
586 | u64 f; | 586 | u64 f; |
587 | u8 acc = 0; /* reg 0x3a, audio clock control */ | ||
587 | 588 | ||
588 | v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq); | 589 | v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq); |
589 | 590 | ||
@@ -591,18 +592,34 @@ static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq) | |||
591 | if (freq < 32000 || freq > 48000) | 592 | if (freq < 32000 || freq > 48000) |
592 | return -EINVAL; | 593 | return -EINVAL; |
593 | 594 | ||
595 | /* The saa7113 has no audio clock */ | ||
596 | if (state->ident == V4L2_IDENT_SAA7113) | ||
597 | return 0; | ||
598 | |||
594 | /* hz is the refresh rate times 100 */ | 599 | /* hz is the refresh rate times 100 */ |
595 | hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000; | 600 | hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000; |
596 | /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */ | 601 | /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */ |
597 | acpf = (25600 * freq) / hz; | 602 | acpf = (25600 * freq) / hz; |
598 | /* acni = (256 * freq * 2^23) / crystal_frequency = | 603 | /* acni = (256 * freq * 2^23) / crystal_frequency = |
599 | (freq * 2^(8+23)) / crystal_frequency = | 604 | (freq * 2^(8+23)) / crystal_frequency = |
600 | (freq << 31) / 32.11 MHz */ | 605 | (freq << 31) / crystal_frequency */ |
601 | f = freq; | 606 | f = freq; |
602 | f = f << 31; | 607 | f = f << 31; |
603 | do_div(f, 32110000); | 608 | do_div(f, state->crystal_freq); |
604 | acni = f; | 609 | acni = f; |
610 | if (state->ucgc) { | ||
611 | acpf = acpf * state->cgcdiv / 16; | ||
612 | acni = acni * state->cgcdiv / 16; | ||
613 | acc = 0x80; | ||
614 | if (state->cgcdiv == 3) | ||
615 | acc |= 0x40; | ||
616 | } | ||
617 | if (state->apll) | ||
618 | acc |= 0x08; | ||
605 | 619 | ||
620 | saa7115_write(client, 0x38, 0x03); | ||
621 | saa7115_write(client, 0x39, 0x10); | ||
622 | saa7115_write(client, 0x3a, acc); | ||
606 | saa7115_write(client, 0x30, acpf & 0xff); | 623 | saa7115_write(client, 0x30, acpf & 0xff); |
607 | saa7115_write(client, 0x31, (acpf >> 8) & 0xff); | 624 | saa7115_write(client, 0x31, (acpf >> 8) & 0xff); |
608 | saa7115_write(client, 0x32, (acpf >> 16) & 0x03); | 625 | saa7115_write(client, 0x32, (acpf >> 16) & 0x03); |
@@ -1073,48 +1090,6 @@ static void saa7115_decode_vbi_line(struct i2c_client *client, | |||
1073 | 1090 | ||
1074 | /* ============ SAA7115 AUDIO settings (end) ============= */ | 1091 | /* ============ SAA7115 AUDIO settings (end) ============= */ |
1075 | 1092 | ||
1076 | static struct v4l2_queryctrl saa7115_qctrl[] = { | ||
1077 | { | ||
1078 | .id = V4L2_CID_BRIGHTNESS, | ||
1079 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1080 | .name = "Brightness", | ||
1081 | .minimum = 0, | ||
1082 | .maximum = 255, | ||
1083 | .step = 1, | ||
1084 | .default_value = 128, | ||
1085 | .flags = 0, | ||
1086 | }, { | ||
1087 | .id = V4L2_CID_CONTRAST, | ||
1088 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1089 | .name = "Contrast", | ||
1090 | .minimum = 0, | ||
1091 | .maximum = 127, | ||
1092 | .step = 1, | ||
1093 | .default_value = 64, | ||
1094 | .flags = 0, | ||
1095 | }, { | ||
1096 | .id = V4L2_CID_SATURATION, | ||
1097 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1098 | .name = "Saturation", | ||
1099 | .minimum = 0, | ||
1100 | .maximum = 127, | ||
1101 | .step = 1, | ||
1102 | .default_value = 64, | ||
1103 | .flags = 0, | ||
1104 | }, { | ||
1105 | .id = V4L2_CID_HUE, | ||
1106 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1107 | .name = "Hue", | ||
1108 | .minimum = -128, | ||
1109 | .maximum = 127, | ||
1110 | .step = 1, | ||
1111 | .default_value = 0, | ||
1112 | .flags = 0, | ||
1113 | }, | ||
1114 | }; | ||
1115 | |||
1116 | /* ----------------------------------------------------------------------- */ | ||
1117 | |||
1118 | static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) | 1093 | static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) |
1119 | { | 1094 | { |
1120 | struct saa7115_state *state = i2c_get_clientdata(client); | 1095 | struct saa7115_state *state = i2c_get_clientdata(client); |
@@ -1158,14 +1133,16 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1158 | case VIDIOC_QUERYCTRL: | 1133 | case VIDIOC_QUERYCTRL: |
1159 | { | 1134 | { |
1160 | struct v4l2_queryctrl *qc = arg; | 1135 | struct v4l2_queryctrl *qc = arg; |
1161 | int i; | ||
1162 | 1136 | ||
1163 | for (i = 0; i < ARRAY_SIZE(saa7115_qctrl); i++) | 1137 | switch (qc->id) { |
1164 | if (qc->id && qc->id == saa7115_qctrl[i].id) { | 1138 | case V4L2_CID_BRIGHTNESS: |
1165 | memcpy(qc, &saa7115_qctrl[i], sizeof(*qc)); | 1139 | case V4L2_CID_CONTRAST: |
1166 | return 0; | 1140 | case V4L2_CID_SATURATION: |
1167 | } | 1141 | case V4L2_CID_HUE: |
1168 | return -EINVAL; | 1142 | return v4l2_ctrl_query_fill_std(qc); |
1143 | default: | ||
1144 | return -EINVAL; | ||
1145 | } | ||
1169 | } | 1146 | } |
1170 | 1147 | ||
1171 | case VIDIOC_G_STD: | 1148 | case VIDIOC_G_STD: |
@@ -1221,34 +1198,6 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1221 | break; | 1198 | break; |
1222 | } | 1199 | } |
1223 | 1200 | ||
1224 | case VIDIOC_G_INPUT: | ||
1225 | *(int *)arg = state->input; | ||
1226 | break; | ||
1227 | |||
1228 | case VIDIOC_S_INPUT: | ||
1229 | v4l_dbg(1, debug, client, "decoder set input %d\n", *iarg); | ||
1230 | /* inputs from 0-9 are available */ | ||
1231 | if (*iarg < 0 || *iarg > 9) { | ||
1232 | return -EINVAL; | ||
1233 | } | ||
1234 | |||
1235 | if (state->input == *iarg) | ||
1236 | break; | ||
1237 | v4l_dbg(1, debug, client, "now setting %s input\n", | ||
1238 | *iarg >= 6 ? "S-Video" : "Composite"); | ||
1239 | state->input = *iarg; | ||
1240 | |||
1241 | /* select mode */ | ||
1242 | saa7115_write(client, 0x02, | ||
1243 | (saa7115_read(client, 0x02) & 0xf0) | | ||
1244 | state->input); | ||
1245 | |||
1246 | /* bypass chrominance trap for modes 6..9 */ | ||
1247 | saa7115_write(client, 0x09, | ||
1248 | (saa7115_read(client, 0x09) & 0x7f) | | ||
1249 | (state->input < 6 ? 0x0 : 0x80)); | ||
1250 | break; | ||
1251 | |||
1252 | case VIDIOC_STREAMON: | 1201 | case VIDIOC_STREAMON: |
1253 | case VIDIOC_STREAMOFF: | 1202 | case VIDIOC_STREAMOFF: |
1254 | v4l_dbg(1, debug, client, "%s output\n", | 1203 | v4l_dbg(1, debug, client, "%s output\n", |
@@ -1260,6 +1209,21 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1260 | } | 1209 | } |
1261 | break; | 1210 | break; |
1262 | 1211 | ||
1212 | case VIDIOC_INT_S_CRYSTAL_FREQ: | ||
1213 | { | ||
1214 | struct v4l2_crystal_freq *freq = arg; | ||
1215 | |||
1216 | if (freq->freq != SAA7115_FREQ_32_11_MHZ && | ||
1217 | freq->freq != SAA7115_FREQ_24_576_MHZ) | ||
1218 | return -EINVAL; | ||
1219 | state->crystal_freq = freq->freq; | ||
1220 | state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4; | ||
1221 | state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0; | ||
1222 | state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0; | ||
1223 | saa7115_set_audio_clock_freq(client, state->audclk_freq); | ||
1224 | break; | ||
1225 | } | ||
1226 | |||
1263 | case VIDIOC_INT_DECODE_VBI_LINE: | 1227 | case VIDIOC_INT_DECODE_VBI_LINE: |
1264 | saa7115_decode_vbi_line(client, arg); | 1228 | saa7115_decode_vbi_line(client, arg); |
1265 | break; | 1229 | break; |
@@ -1401,10 +1365,13 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1401 | v4l_dbg(1, debug, client, "writing init values\n"); | 1365 | v4l_dbg(1, debug, client, "writing init values\n"); |
1402 | 1366 | ||
1403 | /* init to 60hz/48khz */ | 1367 | /* init to 60hz/48khz */ |
1404 | if (state->ident == V4L2_IDENT_SAA7113) | 1368 | if (state->ident == V4L2_IDENT_SAA7113) { |
1369 | state->crystal_freq = SAA7115_FREQ_24_576_MHZ; | ||
1405 | saa7115_writeregs(client, saa7113_init_auto_input); | 1370 | saa7115_writeregs(client, saa7113_init_auto_input); |
1406 | else | 1371 | } else { |
1372 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; | ||
1407 | saa7115_writeregs(client, saa7115_init_auto_input); | 1373 | saa7115_writeregs(client, saa7115_init_auto_input); |
1374 | } | ||
1408 | saa7115_writeregs(client, saa7115_init_misc); | 1375 | saa7115_writeregs(client, saa7115_init_misc); |
1409 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); | 1376 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); |
1410 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); | 1377 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); |
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index c271e2e14105..ad401bdefeaf 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c | |||
@@ -270,7 +270,7 @@ static const char * const wss_strs[] = { | |||
270 | "letterbox 16:9 top", | 270 | "letterbox 16:9 top", |
271 | "invalid", | 271 | "invalid", |
272 | "invalid", | 272 | "invalid", |
273 | "16:9 full format anamorphic" | 273 | "16:9 full format anamorphic", |
274 | "4:3 full format", | 274 | "4:3 full format", |
275 | "invalid", | 275 | "invalid", |
276 | "invalid", | 276 | "invalid", |
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 0e0ba50946e8..de7b9e6e932a 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c | |||
@@ -39,6 +39,23 @@ enum saa6752hs_videoformat { | |||
39 | SAA6752HS_VF_UNKNOWN, | 39 | SAA6752HS_VF_UNKNOWN, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | struct saa6752hs_mpeg_params { | ||
43 | /* transport streams */ | ||
44 | __u16 ts_pid_pmt; | ||
45 | __u16 ts_pid_audio; | ||
46 | __u16 ts_pid_video; | ||
47 | __u16 ts_pid_pcr; | ||
48 | |||
49 | /* audio */ | ||
50 | enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate; | ||
51 | |||
52 | /* video */ | ||
53 | enum v4l2_mpeg_video_aspect vi_aspect; | ||
54 | enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode; | ||
55 | __u32 vi_bitrate; | ||
56 | __u32 vi_bitrate_peak; | ||
57 | }; | ||
58 | |||
42 | static const struct v4l2_format v4l2_format_table[] = | 59 | static const struct v4l2_format v4l2_format_table[] = |
43 | { | 60 | { |
44 | [SAA6752HS_VF_D1] = | 61 | [SAA6752HS_VF_D1] = |
@@ -55,18 +72,19 @@ static const struct v4l2_format v4l2_format_table[] = | |||
55 | 72 | ||
56 | struct saa6752hs_state { | 73 | struct saa6752hs_state { |
57 | struct i2c_client client; | 74 | struct i2c_client client; |
58 | struct v4l2_mpeg_compression params; | 75 | struct v4l2_mpeg_compression old_params; |
76 | struct saa6752hs_mpeg_params params; | ||
59 | enum saa6752hs_videoformat video_format; | 77 | enum saa6752hs_videoformat video_format; |
60 | v4l2_std_id standard; | 78 | v4l2_std_id standard; |
61 | }; | 79 | }; |
62 | 80 | ||
63 | enum saa6752hs_command { | 81 | enum saa6752hs_command { |
64 | SAA6752HS_COMMAND_RESET = 0, | 82 | SAA6752HS_COMMAND_RESET = 0, |
65 | SAA6752HS_COMMAND_STOP = 1, | 83 | SAA6752HS_COMMAND_STOP = 1, |
66 | SAA6752HS_COMMAND_START = 2, | 84 | SAA6752HS_COMMAND_START = 2, |
67 | SAA6752HS_COMMAND_PAUSE = 3, | 85 | SAA6752HS_COMMAND_PAUSE = 3, |
68 | SAA6752HS_COMMAND_RECONFIGURE = 4, | 86 | SAA6752HS_COMMAND_RECONFIGURE = 4, |
69 | SAA6752HS_COMMAND_SLEEP = 5, | 87 | SAA6752HS_COMMAND_SLEEP = 5, |
70 | SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6, | 88 | SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6, |
71 | 89 | ||
72 | SAA6752HS_COMMAND_MAX | 90 | SAA6752HS_COMMAND_MAX |
@@ -129,7 +147,22 @@ static u8 PMT[] = { | |||
129 | 0x00, 0x00, 0x00, 0x00 /* CRC32 */ | 147 | 0x00, 0x00, 0x00, 0x00 /* CRC32 */ |
130 | }; | 148 | }; |
131 | 149 | ||
132 | static struct v4l2_mpeg_compression param_defaults = | 150 | static struct saa6752hs_mpeg_params param_defaults = |
151 | { | ||
152 | .ts_pid_pmt = 16, | ||
153 | .ts_pid_video = 260, | ||
154 | .ts_pid_audio = 256, | ||
155 | .ts_pid_pcr = 259, | ||
156 | |||
157 | .vi_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3, | ||
158 | .vi_bitrate = 4000, | ||
159 | .vi_bitrate_peak = 6000, | ||
160 | .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, | ||
161 | |||
162 | .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K, | ||
163 | }; | ||
164 | |||
165 | static struct v4l2_mpeg_compression old_param_defaults = | ||
133 | { | 166 | { |
134 | .st_type = V4L2_MPEG_TS_2, | 167 | .st_type = V4L2_MPEG_TS_2, |
135 | .st_bitrate = { | 168 | .st_bitrate = { |
@@ -228,45 +261,57 @@ static int saa6752hs_chip_command(struct i2c_client* client, | |||
228 | 261 | ||
229 | 262 | ||
230 | static int saa6752hs_set_bitrate(struct i2c_client* client, | 263 | static int saa6752hs_set_bitrate(struct i2c_client* client, |
231 | struct v4l2_mpeg_compression* params) | 264 | struct saa6752hs_mpeg_params* params) |
232 | { | 265 | { |
233 | u8 buf[3]; | 266 | u8 buf[3]; |
267 | int tot_bitrate; | ||
234 | 268 | ||
235 | /* set the bitrate mode */ | 269 | /* set the bitrate mode */ |
236 | buf[0] = 0x71; | 270 | buf[0] = 0x71; |
237 | buf[1] = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ? 0 : 1; | 271 | buf[1] = (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ? 0 : 1; |
238 | i2c_master_send(client, buf, 2); | 272 | i2c_master_send(client, buf, 2); |
239 | 273 | ||
240 | /* set the video bitrate */ | 274 | /* set the video bitrate */ |
241 | if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) { | 275 | if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { |
242 | /* set the target bitrate */ | 276 | /* set the target bitrate */ |
243 | buf[0] = 0x80; | 277 | buf[0] = 0x80; |
244 | buf[1] = params->vi_bitrate.target >> 8; | 278 | buf[1] = params->vi_bitrate >> 8; |
245 | buf[2] = params->vi_bitrate.target & 0xff; | 279 | buf[2] = params->vi_bitrate & 0xff; |
246 | i2c_master_send(client, buf, 3); | 280 | i2c_master_send(client, buf, 3); |
247 | 281 | ||
248 | /* set the max bitrate */ | 282 | /* set the max bitrate */ |
249 | buf[0] = 0x81; | 283 | buf[0] = 0x81; |
250 | buf[1] = params->vi_bitrate.max >> 8; | 284 | buf[1] = params->vi_bitrate_peak >> 8; |
251 | buf[2] = params->vi_bitrate.max & 0xff; | 285 | buf[2] = params->vi_bitrate_peak & 0xff; |
252 | i2c_master_send(client, buf, 3); | 286 | i2c_master_send(client, buf, 3); |
287 | tot_bitrate = params->vi_bitrate_peak; | ||
253 | } else { | 288 | } else { |
254 | /* set the target bitrate (no max bitrate for CBR) */ | 289 | /* set the target bitrate (no max bitrate for CBR) */ |
255 | buf[0] = 0x81; | 290 | buf[0] = 0x81; |
256 | buf[1] = params->vi_bitrate.target >> 8; | 291 | buf[1] = params->vi_bitrate >> 8; |
257 | buf[2] = params->vi_bitrate.target & 0xff; | 292 | buf[2] = params->vi_bitrate & 0xff; |
258 | i2c_master_send(client, buf, 3); | 293 | i2c_master_send(client, buf, 3); |
294 | tot_bitrate = params->vi_bitrate; | ||
259 | } | 295 | } |
260 | 296 | ||
261 | /* set the audio bitrate */ | 297 | /* set the audio bitrate */ |
262 | buf[0] = 0x94; | 298 | buf[0] = 0x94; |
263 | buf[1] = (256 == params->au_bitrate.target) ? 0 : 1; | 299 | buf[1] = (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 0 : 1; |
264 | i2c_master_send(client, buf, 2); | 300 | i2c_master_send(client, buf, 2); |
301 | tot_bitrate += (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 256 : 384; | ||
302 | |||
303 | /* Note: the total max bitrate is determined by adding the video and audio | ||
304 | bitrates together and also adding an extra 768kbit/s to stay on the | ||
305 | safe side. If more control should be required, then an extra MPEG control | ||
306 | should be added. */ | ||
307 | tot_bitrate += 768; | ||
308 | if (tot_bitrate > MPEG_TOTAL_TARGET_BITRATE_MAX) | ||
309 | tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX; | ||
265 | 310 | ||
266 | /* set the total bitrate */ | 311 | /* set the total bitrate */ |
267 | buf[0] = 0xb1; | 312 | buf[0] = 0xb1; |
268 | buf[1] = params->st_bitrate.target >> 8; | 313 | buf[1] = tot_bitrate >> 8; |
269 | buf[2] = params->st_bitrate.target & 0xff; | 314 | buf[2] = tot_bitrate & 0xff; |
270 | i2c_master_send(client, buf, 3); | 315 | i2c_master_send(client, buf, 3); |
271 | 316 | ||
272 | return 0; | 317 | return 0; |
@@ -318,50 +363,188 @@ static void saa6752hs_set_subsampling(struct i2c_client* client, | |||
318 | } | 363 | } |
319 | 364 | ||
320 | 365 | ||
321 | static void saa6752hs_set_params(struct i2c_client* client, | 366 | static void saa6752hs_old_set_params(struct i2c_client* client, |
322 | struct v4l2_mpeg_compression* params) | 367 | struct v4l2_mpeg_compression* params) |
323 | { | 368 | { |
324 | struct saa6752hs_state *h = i2c_get_clientdata(client); | 369 | struct saa6752hs_state *h = i2c_get_clientdata(client); |
325 | 370 | ||
326 | /* check PIDs */ | 371 | /* check PIDs */ |
327 | if (params->ts_pid_pmt <= MPEG_PID_MAX) | 372 | if (params->ts_pid_pmt <= MPEG_PID_MAX) { |
373 | h->old_params.ts_pid_pmt = params->ts_pid_pmt; | ||
328 | h->params.ts_pid_pmt = params->ts_pid_pmt; | 374 | h->params.ts_pid_pmt = params->ts_pid_pmt; |
329 | if (params->ts_pid_pcr <= MPEG_PID_MAX) | 375 | } |
376 | if (params->ts_pid_pcr <= MPEG_PID_MAX) { | ||
377 | h->old_params.ts_pid_pcr = params->ts_pid_pcr; | ||
330 | h->params.ts_pid_pcr = params->ts_pid_pcr; | 378 | h->params.ts_pid_pcr = params->ts_pid_pcr; |
331 | if (params->ts_pid_video <= MPEG_PID_MAX) | 379 | } |
380 | if (params->ts_pid_video <= MPEG_PID_MAX) { | ||
381 | h->old_params.ts_pid_video = params->ts_pid_video; | ||
332 | h->params.ts_pid_video = params->ts_pid_video; | 382 | h->params.ts_pid_video = params->ts_pid_video; |
333 | if (params->ts_pid_audio <= MPEG_PID_MAX) | 383 | } |
384 | if (params->ts_pid_audio <= MPEG_PID_MAX) { | ||
385 | h->old_params.ts_pid_audio = params->ts_pid_audio; | ||
334 | h->params.ts_pid_audio = params->ts_pid_audio; | 386 | h->params.ts_pid_audio = params->ts_pid_audio; |
387 | } | ||
335 | 388 | ||
336 | /* check bitrate parameters */ | 389 | /* check bitrate parameters */ |
337 | if ((params->vi_bitrate.mode == V4L2_BITRATE_CBR) || | 390 | if ((params->vi_bitrate.mode == V4L2_BITRATE_CBR) || |
338 | (params->vi_bitrate.mode == V4L2_BITRATE_VBR)) | 391 | (params->vi_bitrate.mode == V4L2_BITRATE_VBR)) { |
339 | h->params.vi_bitrate.mode = params->vi_bitrate.mode; | 392 | h->old_params.vi_bitrate.mode = params->vi_bitrate.mode; |
393 | h->params.vi_bitrate_mode = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ? | ||
394 | V4L2_MPEG_VIDEO_BITRATE_MODE_VBR : V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; | ||
395 | } | ||
340 | if (params->vi_bitrate.mode != V4L2_BITRATE_NONE) | 396 | if (params->vi_bitrate.mode != V4L2_BITRATE_NONE) |
341 | h->params.st_bitrate.target = params->st_bitrate.target; | 397 | h->old_params.st_bitrate.target = params->st_bitrate.target; |
342 | if (params->vi_bitrate.mode != V4L2_BITRATE_NONE) | 398 | if (params->vi_bitrate.mode != V4L2_BITRATE_NONE) |
343 | h->params.vi_bitrate.target = params->vi_bitrate.target; | 399 | h->old_params.vi_bitrate.target = params->vi_bitrate.target; |
344 | if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) | 400 | if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) |
345 | h->params.vi_bitrate.max = params->vi_bitrate.max; | 401 | h->old_params.vi_bitrate.max = params->vi_bitrate.max; |
346 | if (params->au_bitrate.mode != V4L2_BITRATE_NONE) | 402 | if (params->au_bitrate.mode != V4L2_BITRATE_NONE) |
347 | h->params.au_bitrate.target = params->au_bitrate.target; | 403 | h->old_params.au_bitrate.target = params->au_bitrate.target; |
348 | 404 | ||
349 | /* aspect ratio */ | 405 | /* aspect ratio */ |
350 | if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3 || | 406 | if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3 || |
351 | params->vi_aspect_ratio == V4L2_MPEG_ASPECT_16_9) | 407 | params->vi_aspect_ratio == V4L2_MPEG_ASPECT_16_9) { |
352 | h->params.vi_aspect_ratio = params->vi_aspect_ratio; | 408 | h->old_params.vi_aspect_ratio = params->vi_aspect_ratio; |
409 | if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3) | ||
410 | h->params.vi_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3; | ||
411 | else | ||
412 | h->params.vi_aspect = V4L2_MPEG_VIDEO_ASPECT_16x9; | ||
413 | } | ||
353 | 414 | ||
354 | /* range checks */ | 415 | /* range checks */ |
355 | if (h->params.st_bitrate.target > MPEG_TOTAL_TARGET_BITRATE_MAX) | 416 | if (h->old_params.st_bitrate.target > MPEG_TOTAL_TARGET_BITRATE_MAX) |
356 | h->params.st_bitrate.target = MPEG_TOTAL_TARGET_BITRATE_MAX; | 417 | h->old_params.st_bitrate.target = MPEG_TOTAL_TARGET_BITRATE_MAX; |
357 | if (h->params.vi_bitrate.target > MPEG_VIDEO_TARGET_BITRATE_MAX) | 418 | if (h->old_params.vi_bitrate.target > MPEG_VIDEO_TARGET_BITRATE_MAX) |
358 | h->params.vi_bitrate.target = MPEG_VIDEO_TARGET_BITRATE_MAX; | 419 | h->old_params.vi_bitrate.target = MPEG_VIDEO_TARGET_BITRATE_MAX; |
359 | if (h->params.vi_bitrate.max > MPEG_VIDEO_MAX_BITRATE_MAX) | 420 | if (h->old_params.vi_bitrate.max > MPEG_VIDEO_MAX_BITRATE_MAX) |
360 | h->params.vi_bitrate.max = MPEG_VIDEO_MAX_BITRATE_MAX; | 421 | h->old_params.vi_bitrate.max = MPEG_VIDEO_MAX_BITRATE_MAX; |
361 | if (h->params.au_bitrate.target <= 256) | 422 | h->params.vi_bitrate = params->vi_bitrate.target; |
362 | h->params.au_bitrate.target = 256; | 423 | h->params.vi_bitrate_peak = params->vi_bitrate.max; |
424 | if (h->old_params.au_bitrate.target <= 256) { | ||
425 | h->old_params.au_bitrate.target = 256; | ||
426 | h->params.au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K; | ||
427 | } | ||
428 | else { | ||
429 | h->old_params.au_bitrate.target = 384; | ||
430 | h->params.au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_384K; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | static int handle_ctrl(struct saa6752hs_mpeg_params *params, | ||
435 | struct v4l2_ext_control *ctrl, int cmd) | ||
436 | { | ||
437 | int old = 0, new; | ||
438 | int set = cmd == VIDIOC_S_EXT_CTRLS; | ||
439 | |||
440 | new = ctrl->value; | ||
441 | switch (ctrl->id) { | ||
442 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
443 | old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; | ||
444 | if (set && new != old) | ||
445 | return -ERANGE; | ||
446 | new = old; | ||
447 | break; | ||
448 | case V4L2_CID_MPEG_STREAM_PID_PMT: | ||
449 | old = params->ts_pid_pmt; | ||
450 | if (set && new > MPEG_PID_MAX) | ||
451 | return -ERANGE; | ||
452 | if (new > MPEG_PID_MAX) | ||
453 | new = MPEG_PID_MAX; | ||
454 | params->ts_pid_pmt = new; | ||
455 | break; | ||
456 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: | ||
457 | old = params->ts_pid_audio; | ||
458 | if (set && new > MPEG_PID_MAX) | ||
459 | return -ERANGE; | ||
460 | if (new > MPEG_PID_MAX) | ||
461 | new = MPEG_PID_MAX; | ||
462 | params->ts_pid_audio = new; | ||
463 | break; | ||
464 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: | ||
465 | old = params->ts_pid_video; | ||
466 | if (set && new > MPEG_PID_MAX) | ||
467 | return -ERANGE; | ||
468 | if (new > MPEG_PID_MAX) | ||
469 | new = MPEG_PID_MAX; | ||
470 | params->ts_pid_video = new; | ||
471 | break; | ||
472 | case V4L2_CID_MPEG_STREAM_PID_PCR: | ||
473 | old = params->ts_pid_pcr; | ||
474 | if (set && new > MPEG_PID_MAX) | ||
475 | return -ERANGE; | ||
476 | if (new > MPEG_PID_MAX) | ||
477 | new = MPEG_PID_MAX; | ||
478 | params->ts_pid_pcr = new; | ||
479 | break; | ||
480 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
481 | old = V4L2_MPEG_AUDIO_ENCODING_LAYER_2; | ||
482 | if (set && new != old) | ||
483 | return -ERANGE; | ||
484 | new = old; | ||
485 | break; | ||
486 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | ||
487 | old = params->au_l2_bitrate; | ||
488 | if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K && | ||
489 | new != V4L2_MPEG_AUDIO_L2_BITRATE_384K) | ||
490 | return -ERANGE; | ||
491 | if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K) | ||
492 | new = V4L2_MPEG_AUDIO_L2_BITRATE_256K; | ||
493 | else | ||
494 | new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; | ||
495 | params->au_l2_bitrate = new; | ||
496 | break; | ||
497 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | ||
498 | old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; | ||
499 | if (set && new != old) | ||
500 | return -ERANGE; | ||
501 | new = old; | ||
502 | break; | ||
503 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
504 | old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; | ||
505 | if (set && new != old) | ||
506 | return -ERANGE; | ||
507 | new = old; | ||
508 | break; | ||
509 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
510 | old = params->vi_aspect; | ||
511 | if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 && | ||
512 | new != V4L2_MPEG_VIDEO_ASPECT_4x3) | ||
513 | return -ERANGE; | ||
514 | if (new != V4L2_MPEG_VIDEO_ASPECT_16x9) | ||
515 | new = V4L2_MPEG_VIDEO_ASPECT_4x3; | ||
516 | params->vi_aspect = new; | ||
517 | break; | ||
518 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
519 | old = params->vi_bitrate * 1000; | ||
520 | new = 1000 * (new / 1000); | ||
521 | if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
522 | return -ERANGE; | ||
523 | if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
524 | new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; | ||
525 | params->vi_bitrate = new / 1000; | ||
526 | break; | ||
527 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
528 | old = params->vi_bitrate_peak * 1000; | ||
529 | new = 1000 * (new / 1000); | ||
530 | if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
531 | return -ERANGE; | ||
532 | if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
533 | new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; | ||
534 | params->vi_bitrate_peak = new / 1000; | ||
535 | break; | ||
536 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
537 | old = params->vi_bitrate_mode; | ||
538 | params->vi_bitrate_mode = new; | ||
539 | break; | ||
540 | default: | ||
541 | return -EINVAL; | ||
542 | } | ||
543 | if (cmd == VIDIOC_G_EXT_CTRLS) | ||
544 | ctrl->value = old; | ||
363 | else | 545 | else |
364 | h->params.au_bitrate.target = 384; | 546 | ctrl->value = new; |
547 | return 0; | ||
365 | } | 548 | } |
366 | 549 | ||
367 | static int saa6752hs_init(struct i2c_client* client) | 550 | static int saa6752hs_init(struct i2c_client* client) |
@@ -395,22 +578,22 @@ static int saa6752hs_init(struct i2c_client* client) | |||
395 | buf[2] = 0x0D; | 578 | buf[2] = 0x0D; |
396 | i2c_master_send(client,buf,3); | 579 | i2c_master_send(client,buf,3); |
397 | 580 | ||
398 | /* Set minimum Q-scale {4} */ | 581 | /* Set minimum Q-scale {4} */ |
399 | buf[0] = 0x82; | 582 | buf[0] = 0x82; |
400 | buf[1] = 0x04; | 583 | buf[1] = 0x04; |
401 | i2c_master_send(client,buf,2); | 584 | i2c_master_send(client,buf,2); |
402 | 585 | ||
403 | /* Set maximum Q-scale {12} */ | 586 | /* Set maximum Q-scale {12} */ |
404 | buf[0] = 0x83; | 587 | buf[0] = 0x83; |
405 | buf[1] = 0x0C; | 588 | buf[1] = 0x0C; |
406 | i2c_master_send(client,buf,2); | 589 | i2c_master_send(client,buf,2); |
407 | 590 | ||
408 | /* Set Output Protocol */ | 591 | /* Set Output Protocol */ |
409 | buf[0] = 0xD0; | 592 | buf[0] = 0xD0; |
410 | buf[1] = 0x81; | 593 | buf[1] = 0x81; |
411 | i2c_master_send(client,buf,2); | 594 | i2c_master_send(client,buf,2); |
412 | 595 | ||
413 | /* Set video output stream format {TS} */ | 596 | /* Set video output stream format {TS} */ |
414 | buf[0] = 0xB0; | 597 | buf[0] = 0xB0; |
415 | buf[1] = 0x05; | 598 | buf[1] = 0x05; |
416 | i2c_master_send(client,buf,2); | 599 | i2c_master_send(client,buf,2); |
@@ -441,7 +624,7 @@ static int saa6752hs_init(struct i2c_client* client) | |||
441 | localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF; | 624 | localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF; |
442 | localPMT[sizeof(PMT) - 1] = crc & 0xFF; | 625 | localPMT[sizeof(PMT) - 1] = crc & 0xFF; |
443 | 626 | ||
444 | /* Set Audio PID */ | 627 | /* Set Audio PID */ |
445 | buf[0] = 0xC1; | 628 | buf[0] = 0xC1; |
446 | buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF; | 629 | buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF; |
447 | buf[2] = h->params.ts_pid_audio & 0xFF; | 630 | buf[2] = h->params.ts_pid_audio & 0xFF; |
@@ -489,11 +672,11 @@ static int saa6752hs_init(struct i2c_client* client) | |||
489 | buf[3] = 0x82; | 672 | buf[3] = 0x82; |
490 | buf[4] = 0xB0; | 673 | buf[4] = 0xB0; |
491 | buf[5] = buf2[0]; | 674 | buf[5] = buf2[0]; |
492 | switch(h->params.vi_aspect_ratio) { | 675 | switch(h->params.vi_aspect) { |
493 | case V4L2_MPEG_ASPECT_16_9: | 676 | case V4L2_MPEG_VIDEO_ASPECT_16x9: |
494 | buf[6] = buf2[1] | 0x40; | 677 | buf[6] = buf2[1] | 0x40; |
495 | break; | 678 | break; |
496 | case V4L2_MPEG_ASPECT_4_3: | 679 | case V4L2_MPEG_VIDEO_ASPECT_4x3: |
497 | default: | 680 | default: |
498 | buf[6] = buf2[1] & 0xBF; | 681 | buf[6] = buf2[1] & 0xBF; |
499 | break; | 682 | break; |
@@ -515,6 +698,7 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) | |||
515 | return -ENOMEM; | 698 | return -ENOMEM; |
516 | h->client = client_template; | 699 | h->client = client_template; |
517 | h->params = param_defaults; | 700 | h->params = param_defaults; |
701 | h->old_params = old_param_defaults; | ||
518 | h->client.adapter = adap; | 702 | h->client.adapter = adap; |
519 | h->client.addr = addr; | 703 | h->client.addr = addr; |
520 | 704 | ||
@@ -550,20 +734,45 @@ static int | |||
550 | saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | 734 | saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) |
551 | { | 735 | { |
552 | struct saa6752hs_state *h = i2c_get_clientdata(client); | 736 | struct saa6752hs_state *h = i2c_get_clientdata(client); |
553 | struct v4l2_mpeg_compression *params = arg; | 737 | struct v4l2_ext_controls *ctrls = arg; |
738 | struct v4l2_mpeg_compression *old_params = arg; | ||
739 | struct saa6752hs_mpeg_params params; | ||
554 | int err = 0; | 740 | int err = 0; |
741 | int i; | ||
555 | 742 | ||
556 | switch (cmd) { | 743 | switch (cmd) { |
557 | case VIDIOC_S_MPEGCOMP: | 744 | case VIDIOC_S_MPEGCOMP: |
558 | if (NULL == params) { | 745 | if (NULL == old_params) { |
559 | /* apply settings and start encoder */ | 746 | /* apply settings and start encoder */ |
560 | saa6752hs_init(client); | 747 | saa6752hs_init(client); |
561 | break; | 748 | break; |
562 | } | 749 | } |
563 | saa6752hs_set_params(client, params); | 750 | saa6752hs_old_set_params(client, old_params); |
564 | /* fall through */ | 751 | /* fall through */ |
565 | case VIDIOC_G_MPEGCOMP: | 752 | case VIDIOC_G_MPEGCOMP: |
566 | *params = h->params; | 753 | *old_params = h->old_params; |
754 | break; | ||
755 | case VIDIOC_S_EXT_CTRLS: | ||
756 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | ||
757 | return -EINVAL; | ||
758 | if (ctrls->count == 0) { | ||
759 | /* apply settings and start encoder */ | ||
760 | saa6752hs_init(client); | ||
761 | break; | ||
762 | } | ||
763 | /* fall through */ | ||
764 | case VIDIOC_TRY_EXT_CTRLS: | ||
765 | case VIDIOC_G_EXT_CTRLS: | ||
766 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | ||
767 | return -EINVAL; | ||
768 | params = h->params; | ||
769 | for (i = 0; i < ctrls->count; i++) { | ||
770 | if ((err = handle_ctrl(¶ms, ctrls->controls + i, cmd))) { | ||
771 | ctrls->error_idx = i; | ||
772 | return err; | ||
773 | } | ||
774 | } | ||
775 | h->params = params; | ||
567 | break; | 776 | break; |
568 | case VIDIOC_G_FMT: | 777 | case VIDIOC_G_FMT: |
569 | { | 778 | { |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index bb3e0ba946d3..d77e6a8d9432 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -818,7 +818,7 @@ static int snd_saa7134_capsrc_put(struct snd_kcontrol * kcontrol, | |||
818 | break; | 818 | break; |
819 | } | 819 | } |
820 | 820 | ||
821 | /* output xbar always main channel */ | 821 | /* output xbar always main channel */ |
822 | saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); | 822 | saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); |
823 | 823 | ||
824 | if (left || right) { // We've got data, turn the input on | 824 | if (left || right) { // We've got data, turn the input on |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 86eae3528330..927413aded10 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -2160,7 +2160,7 @@ struct saa7134_board saa7134_boards[] = { | |||
2160 | .radio = { | 2160 | .radio = { |
2161 | .name = name_radio, | 2161 | .name = name_radio, |
2162 | .amux = LINE2, | 2162 | .amux = LINE2, |
2163 | }, | 2163 | }, |
2164 | }, | 2164 | }, |
2165 | [SAA7134_BOARD_GOTVIEW_7135] = { | 2165 | [SAA7134_BOARD_GOTVIEW_7135] = { |
2166 | /* Mike Baikov <mike@baikov.com> */ | 2166 | /* Mike Baikov <mike@baikov.com> */ |
@@ -2842,6 +2842,55 @@ struct saa7134_board saa7134_boards[] = { | |||
2842 | .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ | 2842 | .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ |
2843 | }, | 2843 | }, |
2844 | }, | 2844 | }, |
2845 | [SAA7134_BOARD_FLYVIDEO3000_NTSC] = { | ||
2846 | /* "Zac Bowling" <zac@zacbowling.com> */ | ||
2847 | .name = "LifeView FlyVIDEO3000 (NTSC)", | ||
2848 | .audio_clock = 0x00200000, | ||
2849 | .tuner_type = TUNER_PHILIPS_NTSC, | ||
2850 | .radio_type = UNSET, | ||
2851 | .tuner_addr = ADDR_UNSET, | ||
2852 | .radio_addr = ADDR_UNSET, | ||
2853 | |||
2854 | .gpiomask = 0xe000, | ||
2855 | .inputs = {{ | ||
2856 | .name = name_tv, | ||
2857 | .vmux = 1, | ||
2858 | .amux = TV, | ||
2859 | .gpio = 0x8000, | ||
2860 | .tv = 1, | ||
2861 | },{ | ||
2862 | .name = name_tv_mono, | ||
2863 | .vmux = 1, | ||
2864 | .amux = LINE2, | ||
2865 | .gpio = 0x0000, | ||
2866 | .tv = 1, | ||
2867 | },{ | ||
2868 | .name = name_comp1, | ||
2869 | .vmux = 0, | ||
2870 | .amux = LINE2, | ||
2871 | .gpio = 0x4000, | ||
2872 | },{ | ||
2873 | .name = name_comp2, | ||
2874 | .vmux = 3, | ||
2875 | .amux = LINE2, | ||
2876 | .gpio = 0x4000, | ||
2877 | },{ | ||
2878 | .name = name_svideo, | ||
2879 | .vmux = 8, | ||
2880 | .amux = LINE2, | ||
2881 | .gpio = 0x4000, | ||
2882 | }}, | ||
2883 | .radio = { | ||
2884 | .name = name_radio, | ||
2885 | .amux = LINE2, | ||
2886 | .gpio = 0x2000, | ||
2887 | }, | ||
2888 | .mute = { | ||
2889 | .name = name_mute, | ||
2890 | .amux = TV, | ||
2891 | .gpio = 0x8000, | ||
2892 | }, | ||
2893 | }, | ||
2845 | }; | 2894 | }; |
2846 | 2895 | ||
2847 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); | 2896 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); |
@@ -2901,6 +2950,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
2901 | },{ | 2950 | },{ |
2902 | .vendor = PCI_VENDOR_ID_PHILIPS, | 2951 | .vendor = PCI_VENDOR_ID_PHILIPS, |
2903 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 2952 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
2953 | .subvendor = 0x5169, | ||
2954 | .subdevice = 0x0138, | ||
2955 | .driver_data = SAA7134_BOARD_FLYVIDEO3000_NTSC, | ||
2956 | },{ | ||
2957 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
2958 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | ||
2904 | .subvendor = 0x5168, | 2959 | .subvendor = 0x5168, |
2905 | .subdevice = 0x0138, | 2960 | .subdevice = 0x0138, |
2906 | .driver_data = SAA7134_BOARD_FLYVIDEO3000, | 2961 | .driver_data = SAA7134_BOARD_FLYVIDEO3000, |
@@ -3459,6 +3514,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
3459 | switch (dev->board) { | 3514 | switch (dev->board) { |
3460 | case SAA7134_BOARD_FLYVIDEO2000: | 3515 | case SAA7134_BOARD_FLYVIDEO2000: |
3461 | case SAA7134_BOARD_FLYVIDEO3000: | 3516 | case SAA7134_BOARD_FLYVIDEO3000: |
3517 | case SAA7134_BOARD_FLYVIDEO3000_NTSC: | ||
3462 | dev->has_remote = SAA7134_REMOTE_GPIO; | 3518 | dev->has_remote = SAA7134_REMOTE_GPIO; |
3463 | board_flyvideo(dev); | 3519 | board_flyvideo(dev); |
3464 | break; | 3520 | break; |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 222a36c38917..279828b8f299 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -132,9 +132,8 @@ static int mt352_aver777_init(struct dvb_frontend* fe) | |||
132 | return 0; | 132 | return 0; |
133 | } | 133 | } |
134 | 134 | ||
135 | static int mt352_pinnacle_pll_set(struct dvb_frontend* fe, | 135 | static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe, |
136 | struct dvb_frontend_parameters* params, | 136 | struct dvb_frontend_parameters* params) |
137 | u8* pllbuf) | ||
138 | { | 137 | { |
139 | u8 off[] = { 0x00, 0xf1}; | 138 | u8 off[] = { 0x00, 0xf1}; |
140 | u8 on[] = { 0x00, 0x71}; | 139 | u8 on[] = { 0x00, 0x71}; |
@@ -147,30 +146,31 @@ static int mt352_pinnacle_pll_set(struct dvb_frontend* fe, | |||
147 | f.tuner = 0; | 146 | f.tuner = 0; |
148 | f.type = V4L2_TUNER_DIGITAL_TV; | 147 | f.type = V4L2_TUNER_DIGITAL_TV; |
149 | f.frequency = params->frequency / 1000 * 16 / 1000; | 148 | f.frequency = params->frequency / 1000 * 16 / 1000; |
149 | if (fe->ops.i2c_gate_ctrl) | ||
150 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
150 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 151 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
151 | saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f); | 152 | saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f); |
152 | msg.buf = on; | 153 | msg.buf = on; |
154 | if (fe->ops.i2c_gate_ctrl) | ||
155 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
153 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 156 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
154 | 157 | ||
155 | pinnacle_antenna_pwr(dev, antenna_pwr); | 158 | pinnacle_antenna_pwr(dev, antenna_pwr); |
156 | 159 | ||
157 | /* mt352 setup */ | 160 | /* mt352 setup */ |
158 | mt352_pinnacle_init(fe); | 161 | return mt352_pinnacle_init(fe); |
159 | pllbuf[0] = 0xc2; | ||
160 | pllbuf[1] = 0x00; | ||
161 | pllbuf[2] = 0x00; | ||
162 | pllbuf[3] = 0x80; | ||
163 | pllbuf[4] = 0x00; | ||
164 | return 0; | ||
165 | } | 162 | } |
166 | 163 | ||
167 | static int mt352_aver777_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf) | 164 | static int mt352_aver777_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len) |
168 | { | 165 | { |
169 | pllbuf[0] = 0xc2; | 166 | if (buf_len < 5) |
167 | return -EINVAL; | ||
168 | |||
169 | pllbuf[0] = 0x61; | ||
170 | dvb_pll_configure(&dvb_pll_philips_td1316, pllbuf+1, | 170 | dvb_pll_configure(&dvb_pll_philips_td1316, pllbuf+1, |
171 | params->frequency, | 171 | params->frequency, |
172 | params->u.ofdm.bandwidth); | 172 | params->u.ofdm.bandwidth); |
173 | return 0; | 173 | return 5; |
174 | } | 174 | } |
175 | 175 | ||
176 | static struct mt352_config pinnacle_300i = { | 176 | static struct mt352_config pinnacle_300i = { |
@@ -179,13 +179,11 @@ static struct mt352_config pinnacle_300i = { | |||
179 | .if2 = 36150, | 179 | .if2 = 36150, |
180 | .no_tuner = 1, | 180 | .no_tuner = 1, |
181 | .demod_init = mt352_pinnacle_init, | 181 | .demod_init = mt352_pinnacle_init, |
182 | .pll_set = mt352_pinnacle_pll_set, | ||
183 | }; | 182 | }; |
184 | 183 | ||
185 | static struct mt352_config avermedia_777 = { | 184 | static struct mt352_config avermedia_777 = { |
186 | .demod_address = 0xf, | 185 | .demod_address = 0xf, |
187 | .demod_init = mt352_aver777_init, | 186 | .demod_init = mt352_aver777_init, |
188 | .pll_set = mt352_aver777_pll_set, | ||
189 | }; | 187 | }; |
190 | #endif | 188 | #endif |
191 | 189 | ||
@@ -268,6 +266,8 @@ static int philips_tda6651_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb_ | |||
268 | tuner_buf[2] = 0xca; | 266 | tuner_buf[2] = 0xca; |
269 | tuner_buf[3] = (cp << 5) | (filter << 3) | band; | 267 | tuner_buf[3] = (cp << 5) | (filter << 3) | band; |
270 | 268 | ||
269 | if (fe->ops.i2c_gate_ctrl) | ||
270 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
271 | if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) | 271 | if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) |
272 | return -EIO; | 272 | return -EIO; |
273 | msleep(1); | 273 | msleep(1); |
@@ -281,6 +281,8 @@ static int philips_tda6651_pll_init(u8 addr, struct dvb_frontend *fe) | |||
281 | struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) }; | 281 | struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) }; |
282 | 282 | ||
283 | /* setup PLL configuration */ | 283 | /* setup PLL configuration */ |
284 | if (fe->ops.i2c_gate_ctrl) | ||
285 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
284 | if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) | 286 | if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) |
285 | return -EIO; | 287 | return -EIO; |
286 | msleep(1); | 288 | msleep(1); |
@@ -290,12 +292,12 @@ static int philips_tda6651_pll_init(u8 addr, struct dvb_frontend *fe) | |||
290 | 292 | ||
291 | /* ------------------------------------------------------------------ */ | 293 | /* ------------------------------------------------------------------ */ |
292 | 294 | ||
293 | static int philips_tu1216_pll_60_init(struct dvb_frontend *fe) | 295 | static int philips_tu1216_tuner_60_init(struct dvb_frontend *fe) |
294 | { | 296 | { |
295 | return philips_tda6651_pll_init(0x60, fe); | 297 | return philips_tda6651_pll_init(0x60, fe); |
296 | } | 298 | } |
297 | 299 | ||
298 | static int philips_tu1216_pll_60_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 300 | static int philips_tu1216_tuner_60_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) |
299 | { | 301 | { |
300 | return philips_tda6651_pll_set(0x60, fe, params); | 302 | return philips_tda6651_pll_set(0x60, fe, params); |
301 | } | 303 | } |
@@ -315,20 +317,17 @@ static struct tda1004x_config philips_tu1216_60_config = { | |||
315 | .xtal_freq = TDA10046_XTAL_4M, | 317 | .xtal_freq = TDA10046_XTAL_4M, |
316 | .agc_config = TDA10046_AGC_DEFAULT, | 318 | .agc_config = TDA10046_AGC_DEFAULT, |
317 | .if_freq = TDA10046_FREQ_3617, | 319 | .if_freq = TDA10046_FREQ_3617, |
318 | .pll_init = philips_tu1216_pll_60_init, | ||
319 | .pll_set = philips_tu1216_pll_60_set, | ||
320 | .pll_sleep = NULL, | ||
321 | .request_firmware = philips_tu1216_request_firmware, | 320 | .request_firmware = philips_tu1216_request_firmware, |
322 | }; | 321 | }; |
323 | 322 | ||
324 | /* ------------------------------------------------------------------ */ | 323 | /* ------------------------------------------------------------------ */ |
325 | 324 | ||
326 | static int philips_tu1216_pll_61_init(struct dvb_frontend *fe) | 325 | static int philips_tu1216_tuner_61_init(struct dvb_frontend *fe) |
327 | { | 326 | { |
328 | return philips_tda6651_pll_init(0x61, fe); | 327 | return philips_tda6651_pll_init(0x61, fe); |
329 | } | 328 | } |
330 | 329 | ||
331 | static int philips_tu1216_pll_61_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 330 | static int philips_tu1216_tuner_61_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) |
332 | { | 331 | { |
333 | return philips_tda6651_pll_set(0x61, fe, params); | 332 | return philips_tda6651_pll_set(0x61, fe, params); |
334 | } | 333 | } |
@@ -341,21 +340,20 @@ static struct tda1004x_config philips_tu1216_61_config = { | |||
341 | .xtal_freq = TDA10046_XTAL_4M, | 340 | .xtal_freq = TDA10046_XTAL_4M, |
342 | .agc_config = TDA10046_AGC_DEFAULT, | 341 | .agc_config = TDA10046_AGC_DEFAULT, |
343 | .if_freq = TDA10046_FREQ_3617, | 342 | .if_freq = TDA10046_FREQ_3617, |
344 | .pll_init = philips_tu1216_pll_61_init, | ||
345 | .pll_set = philips_tu1216_pll_61_set, | ||
346 | .pll_sleep = NULL, | ||
347 | .request_firmware = philips_tu1216_request_firmware, | 343 | .request_firmware = philips_tu1216_request_firmware, |
348 | }; | 344 | }; |
349 | 345 | ||
350 | /* ------------------------------------------------------------------ */ | 346 | /* ------------------------------------------------------------------ */ |
351 | 347 | ||
352 | static int philips_europa_pll_init(struct dvb_frontend *fe) | 348 | static int philips_europa_tuner_init(struct dvb_frontend *fe) |
353 | { | 349 | { |
354 | struct saa7134_dev *dev = fe->dvb->priv; | 350 | struct saa7134_dev *dev = fe->dvb->priv; |
355 | static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab }; | 351 | static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab }; |
356 | struct i2c_msg init_msg = {.addr = 0x61,.flags = 0,.buf = msg,.len = sizeof(msg) }; | 352 | struct i2c_msg init_msg = {.addr = 0x61,.flags = 0,.buf = msg,.len = sizeof(msg) }; |
357 | 353 | ||
358 | /* setup PLL configuration */ | 354 | /* setup PLL configuration */ |
355 | if (fe->ops.i2c_gate_ctrl) | ||
356 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
359 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) | 357 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) |
360 | return -EIO; | 358 | return -EIO; |
361 | msleep(1); | 359 | msleep(1); |
@@ -365,18 +363,20 @@ static int philips_europa_pll_init(struct dvb_frontend *fe) | |||
365 | init_msg.len = 0x02; | 363 | init_msg.len = 0x02; |
366 | msg[0] = 0x00; | 364 | msg[0] = 0x00; |
367 | msg[1] = 0x40; | 365 | msg[1] = 0x40; |
366 | if (fe->ops.i2c_gate_ctrl) | ||
367 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
368 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) | 368 | if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) |
369 | return -EIO; | 369 | return -EIO; |
370 | 370 | ||
371 | return 0; | 371 | return 0; |
372 | } | 372 | } |
373 | 373 | ||
374 | static int philips_td1316_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 374 | static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) |
375 | { | 375 | { |
376 | return philips_tda6651_pll_set(0x61, fe, params); | 376 | return philips_tda6651_pll_set(0x61, fe, params); |
377 | } | 377 | } |
378 | 378 | ||
379 | static void philips_europa_analog(struct dvb_frontend *fe) | 379 | static int philips_europa_tuner_sleep(struct dvb_frontend *fe) |
380 | { | 380 | { |
381 | struct saa7134_dev *dev = fe->dvb->priv; | 381 | struct saa7134_dev *dev = fe->dvb->priv; |
382 | /* this message actually turns the tuner back to analog mode */ | 382 | /* this message actually turns the tuner back to analog mode */ |
@@ -391,7 +391,20 @@ static void philips_europa_analog(struct dvb_frontend *fe) | |||
391 | analog_msg.len = 0x02; | 391 | analog_msg.len = 0x02; |
392 | msg[0] = 0x00; | 392 | msg[0] = 0x00; |
393 | msg[1] = 0x14; | 393 | msg[1] = 0x14; |
394 | if (fe->ops.i2c_gate_ctrl) | ||
395 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
394 | i2c_transfer(&dev->i2c_adap, &analog_msg, 1); | 396 | i2c_transfer(&dev->i2c_adap, &analog_msg, 1); |
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static int philips_europa_demod_sleep(struct dvb_frontend *fe) | ||
401 | { | ||
402 | struct saa7134_dev *dev = fe->dvb->priv; | ||
403 | |||
404 | if (dev->original_demod_sleep) | ||
405 | dev->original_demod_sleep(fe); | ||
406 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
407 | return 0; | ||
395 | } | 408 | } |
396 | 409 | ||
397 | static struct tda1004x_config philips_europa_config = { | 410 | static struct tda1004x_config philips_europa_config = { |
@@ -402,21 +415,20 @@ static struct tda1004x_config philips_europa_config = { | |||
402 | .xtal_freq = TDA10046_XTAL_4M, | 415 | .xtal_freq = TDA10046_XTAL_4M, |
403 | .agc_config = TDA10046_AGC_IFO_AUTO_POS, | 416 | .agc_config = TDA10046_AGC_IFO_AUTO_POS, |
404 | .if_freq = TDA10046_FREQ_052, | 417 | .if_freq = TDA10046_FREQ_052, |
405 | .pll_init = philips_europa_pll_init, | ||
406 | .pll_set = philips_td1316_pll_set, | ||
407 | .pll_sleep = philips_europa_analog, | ||
408 | .request_firmware = NULL, | 418 | .request_firmware = NULL, |
409 | }; | 419 | }; |
410 | 420 | ||
411 | /* ------------------------------------------------------------------ */ | 421 | /* ------------------------------------------------------------------ */ |
412 | 422 | ||
413 | static int philips_fmd1216_pll_init(struct dvb_frontend *fe) | 423 | static int philips_fmd1216_tuner_init(struct dvb_frontend *fe) |
414 | { | 424 | { |
415 | struct saa7134_dev *dev = fe->dvb->priv; | 425 | struct saa7134_dev *dev = fe->dvb->priv; |
416 | /* this message is to set up ATC and ALC */ | 426 | /* this message is to set up ATC and ALC */ |
417 | static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; | 427 | static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; |
418 | struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) }; | 428 | struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) }; |
419 | 429 | ||
430 | if (fe->ops.i2c_gate_ctrl) | ||
431 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
420 | if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) | 432 | if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) |
421 | return -EIO; | 433 | return -EIO; |
422 | msleep(1); | 434 | msleep(1); |
@@ -424,22 +436,27 @@ static int philips_fmd1216_pll_init(struct dvb_frontend *fe) | |||
424 | return 0; | 436 | return 0; |
425 | } | 437 | } |
426 | 438 | ||
427 | static void philips_fmd1216_analog(struct dvb_frontend *fe) | 439 | static int philips_fmd1216_tuner_sleep(struct dvb_frontend *fe) |
428 | { | 440 | { |
429 | struct saa7134_dev *dev = fe->dvb->priv; | 441 | struct saa7134_dev *dev = fe->dvb->priv; |
430 | /* this message actually turns the tuner back to analog mode */ | 442 | /* this message actually turns the tuner back to analog mode */ |
431 | static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0x60 }; | 443 | static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0x60 }; |
432 | struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) }; | 444 | struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) }; |
433 | 445 | ||
446 | if (fe->ops.i2c_gate_ctrl) | ||
447 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
434 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); | 448 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); |
435 | msleep(1); | 449 | msleep(1); |
436 | fmd1216_init[2] = 0x86; | 450 | fmd1216_init[2] = 0x86; |
437 | fmd1216_init[3] = 0x54; | 451 | fmd1216_init[3] = 0x54; |
452 | if (fe->ops.i2c_gate_ctrl) | ||
453 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
438 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); | 454 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); |
439 | msleep(1); | 455 | msleep(1); |
456 | return 0; | ||
440 | } | 457 | } |
441 | 458 | ||
442 | static int philips_fmd1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 459 | static int philips_fmd1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) |
443 | { | 460 | { |
444 | struct saa7134_dev *dev = fe->dvb->priv; | 461 | struct saa7134_dev *dev = fe->dvb->priv; |
445 | u8 tuner_buf[4]; | 462 | u8 tuner_buf[4]; |
@@ -516,6 +533,8 @@ static int philips_fmd1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ | |||
516 | tuner_buf[2] = 0x80 | (cp << 6) | (mode << 3) | 4; | 533 | tuner_buf[2] = 0x80 | (cp << 6) | (mode << 3) | 4; |
517 | tuner_buf[3] = 0x40 | band; | 534 | tuner_buf[3] = 0x40 | band; |
518 | 535 | ||
536 | if (fe->ops.i2c_gate_ctrl) | ||
537 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
519 | if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) | 538 | if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) |
520 | return -EIO; | 539 | return -EIO; |
521 | return 0; | 540 | return 0; |
@@ -528,9 +547,6 @@ static struct tda1004x_config medion_cardbus = { | |||
528 | .xtal_freq = TDA10046_XTAL_16M, | 547 | .xtal_freq = TDA10046_XTAL_16M, |
529 | .agc_config = TDA10046_AGC_IFO_AUTO_NEG, | 548 | .agc_config = TDA10046_AGC_IFO_AUTO_NEG, |
530 | .if_freq = TDA10046_FREQ_3613, | 549 | .if_freq = TDA10046_FREQ_3613, |
531 | .pll_init = philips_fmd1216_pll_init, | ||
532 | .pll_set = philips_fmd1216_pll_set, | ||
533 | .pll_sleep = philips_fmd1216_analog, | ||
534 | .request_firmware = NULL, | 550 | .request_firmware = NULL, |
535 | }; | 551 | }; |
536 | 552 | ||
@@ -578,12 +594,12 @@ static struct tda827x_data tda827x_dvbt[] = { | |||
578 | { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} | 594 | { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} |
579 | }; | 595 | }; |
580 | 596 | ||
581 | static int philips_tda827x_pll_init(struct dvb_frontend *fe) | 597 | static int philips_tda827x_tuner_init(struct dvb_frontend *fe) |
582 | { | 598 | { |
583 | return 0; | 599 | return 0; |
584 | } | 600 | } |
585 | 601 | ||
586 | static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 602 | static int philips_tda827x_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) |
587 | { | 603 | { |
588 | struct saa7134_dev *dev = fe->dvb->priv; | 604 | struct saa7134_dev *dev = fe->dvb->priv; |
589 | u8 tuner_buf[14]; | 605 | u8 tuner_buf[14]; |
@@ -630,6 +646,8 @@ static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ | |||
630 | tuner_buf[13] = 0x40; | 646 | tuner_buf[13] = 0x40; |
631 | 647 | ||
632 | tuner_msg.len = 14; | 648 | tuner_msg.len = 14; |
649 | if (fe->ops.i2c_gate_ctrl) | ||
650 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
633 | if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) | 651 | if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) |
634 | return -EIO; | 652 | return -EIO; |
635 | 653 | ||
@@ -638,18 +656,23 @@ static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ | |||
638 | tuner_buf[0] = 0x30; | 656 | tuner_buf[0] = 0x30; |
639 | tuner_buf[1] = 0x50 + tda827x_dvbt[i].cp; | 657 | tuner_buf[1] = 0x50 + tda827x_dvbt[i].cp; |
640 | tuner_msg.len = 2; | 658 | tuner_msg.len = 2; |
659 | if (fe->ops.i2c_gate_ctrl) | ||
660 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
641 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); | 661 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); |
642 | 662 | ||
643 | return 0; | 663 | return 0; |
644 | } | 664 | } |
645 | 665 | ||
646 | static void philips_tda827x_pll_sleep(struct dvb_frontend *fe) | 666 | static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe) |
647 | { | 667 | { |
648 | struct saa7134_dev *dev = fe->dvb->priv; | 668 | struct saa7134_dev *dev = fe->dvb->priv; |
649 | static u8 tda827x_sleep[] = { 0x30, 0xd0}; | 669 | static u8 tda827x_sleep[] = { 0x30, 0xd0}; |
650 | struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep, | 670 | struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep, |
651 | .len = sizeof(tda827x_sleep) }; | 671 | .len = sizeof(tda827x_sleep) }; |
672 | if (fe->ops.i2c_gate_ctrl) | ||
673 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
652 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); | 674 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); |
675 | return 0; | ||
653 | } | 676 | } |
654 | 677 | ||
655 | static struct tda1004x_config tda827x_lifeview_config = { | 678 | static struct tda1004x_config tda827x_lifeview_config = { |
@@ -659,9 +682,6 @@ static struct tda1004x_config tda827x_lifeview_config = { | |||
659 | .xtal_freq = TDA10046_XTAL_16M, | 682 | .xtal_freq = TDA10046_XTAL_16M, |
660 | .agc_config = TDA10046_AGC_TDA827X, | 683 | .agc_config = TDA10046_AGC_TDA827X, |
661 | .if_freq = TDA10046_FREQ_045, | 684 | .if_freq = TDA10046_FREQ_045, |
662 | .pll_init = philips_tda827x_pll_init, | ||
663 | .pll_set = philips_tda827x_pll_set, | ||
664 | .pll_sleep = philips_tda827x_pll_sleep, | ||
665 | .request_firmware = NULL, | 685 | .request_firmware = NULL, |
666 | }; | 686 | }; |
667 | 687 | ||
@@ -753,6 +773,8 @@ static int philips_tda827xa_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb | |||
753 | tuner_buf[12] = 0x00; | 773 | tuner_buf[12] = 0x00; |
754 | tuner_buf[13] = 0x39; // lpsel | 774 | tuner_buf[13] = 0x39; // lpsel |
755 | msg.len = 14; | 775 | msg.len = 14; |
776 | if (fe->ops.i2c_gate_ctrl) | ||
777 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
756 | if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) | 778 | if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) |
757 | return -EIO; | 779 | return -EIO; |
758 | 780 | ||
@@ -760,10 +782,14 @@ static int philips_tda827xa_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb | |||
760 | msg.len = 2; | 782 | msg.len = 2; |
761 | reg2[0] = 0x60; | 783 | reg2[0] = 0x60; |
762 | reg2[1] = 0x3c; | 784 | reg2[1] = 0x3c; |
785 | if (fe->ops.i2c_gate_ctrl) | ||
786 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
763 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 787 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
764 | 788 | ||
765 | reg2[0] = 0xa0; | 789 | reg2[0] = 0xa0; |
766 | reg2[1] = 0x40; | 790 | reg2[1] = 0x40; |
791 | if (fe->ops.i2c_gate_ctrl) | ||
792 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
767 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 793 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
768 | 794 | ||
769 | msleep(2); | 795 | msleep(2); |
@@ -771,36 +797,43 @@ static int philips_tda827xa_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb | |||
771 | reg2[0] = 0x30; | 797 | reg2[0] = 0x30; |
772 | reg2[1] = 0x10 + tda827xa_dvbt[i].scr; | 798 | reg2[1] = 0x10 + tda827xa_dvbt[i].scr; |
773 | msg.len = 2; | 799 | msg.len = 2; |
800 | if (fe->ops.i2c_gate_ctrl) | ||
801 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
774 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 802 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
775 | 803 | ||
776 | msleep(550); | 804 | msleep(550); |
777 | reg2[0] = 0x50; | 805 | reg2[0] = 0x50; |
778 | reg2[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4); | 806 | reg2[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4); |
807 | if (fe->ops.i2c_gate_ctrl) | ||
808 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
779 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 809 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
780 | 810 | ||
781 | return 0; | 811 | return 0; |
782 | 812 | ||
783 | } | 813 | } |
784 | 814 | ||
785 | static void philips_tda827xa_pll_sleep(u8 addr, struct dvb_frontend *fe) | 815 | static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe) |
786 | { | 816 | { |
787 | struct saa7134_dev *dev = fe->dvb->priv; | 817 | struct saa7134_dev *dev = fe->dvb->priv; |
788 | static u8 tda827xa_sleep[] = { 0x30, 0x90}; | 818 | static u8 tda827xa_sleep[] = { 0x30, 0x90}; |
789 | struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep, | 819 | struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep, |
790 | .len = sizeof(tda827xa_sleep) }; | 820 | .len = sizeof(tda827xa_sleep) }; |
821 | if (fe->ops.i2c_gate_ctrl) | ||
822 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
791 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); | 823 | i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); |
792 | 824 | return 0; | |
793 | } | 825 | } |
794 | 826 | ||
795 | /* ------------------------------------------------------------------ */ | 827 | /* ------------------------------------------------------------------ */ |
796 | 828 | ||
797 | static int philips_tiger_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 829 | static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) |
798 | { | 830 | { |
799 | int ret; | 831 | int ret; |
800 | struct saa7134_dev *dev = fe->dvb->priv; | 832 | struct saa7134_dev *dev = fe->dvb->priv; |
801 | static u8 tda8290_close[] = { 0x21, 0xc0}; | 833 | static u8 tda8290_close[] = { 0x21, 0xc0}; |
802 | static u8 tda8290_open[] = { 0x21, 0x80}; | 834 | static u8 tda8290_open[] = { 0x21, 0x80}; |
803 | struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2}; | 835 | struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2}; |
836 | |||
804 | /* close tda8290 i2c bridge */ | 837 | /* close tda8290 i2c bridge */ |
805 | tda8290_msg.buf = tda8290_close; | 838 | tda8290_msg.buf = tda8290_close; |
806 | ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); | 839 | ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); |
@@ -816,7 +849,7 @@ static int philips_tiger_pll_set(struct dvb_frontend *fe, struct dvb_frontend_pa | |||
816 | return ret; | 849 | return ret; |
817 | } | 850 | } |
818 | 851 | ||
819 | static int philips_tiger_dvb_mode(struct dvb_frontend *fe) | 852 | static int philips_tiger_tuner_init(struct dvb_frontend *fe) |
820 | { | 853 | { |
821 | struct saa7134_dev *dev = fe->dvb->priv; | 854 | struct saa7134_dev *dev = fe->dvb->priv; |
822 | static u8 data[] = { 0x3c, 0x33, 0x6a}; | 855 | static u8 data[] = { 0x3c, 0x33, 0x6a}; |
@@ -827,14 +860,15 @@ static int philips_tiger_dvb_mode(struct dvb_frontend *fe) | |||
827 | return 0; | 860 | return 0; |
828 | } | 861 | } |
829 | 862 | ||
830 | static void philips_tiger_analog_mode(struct dvb_frontend *fe) | 863 | static int philips_tiger_tuner_sleep(struct dvb_frontend *fe) |
831 | { | 864 | { |
832 | struct saa7134_dev *dev = fe->dvb->priv; | 865 | struct saa7134_dev *dev = fe->dvb->priv; |
833 | static u8 data[] = { 0x3c, 0x33, 0x68}; | 866 | static u8 data[] = { 0x3c, 0x33, 0x68}; |
834 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; | 867 | struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; |
835 | 868 | ||
836 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 869 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
837 | philips_tda827xa_pll_sleep( 0x61, fe); | 870 | philips_tda827xa_tuner_sleep( 0x61, fe); |
871 | return 0; | ||
838 | } | 872 | } |
839 | 873 | ||
840 | static struct tda1004x_config philips_tiger_config = { | 874 | static struct tda1004x_config philips_tiger_config = { |
@@ -844,15 +878,12 @@ static struct tda1004x_config philips_tiger_config = { | |||
844 | .xtal_freq = TDA10046_XTAL_16M, | 878 | .xtal_freq = TDA10046_XTAL_16M, |
845 | .agc_config = TDA10046_AGC_TDA827X, | 879 | .agc_config = TDA10046_AGC_TDA827X, |
846 | .if_freq = TDA10046_FREQ_045, | 880 | .if_freq = TDA10046_FREQ_045, |
847 | .pll_init = philips_tiger_dvb_mode, | ||
848 | .pll_set = philips_tiger_pll_set, | ||
849 | .pll_sleep = philips_tiger_analog_mode, | ||
850 | .request_firmware = NULL, | 881 | .request_firmware = NULL, |
851 | }; | 882 | }; |
852 | 883 | ||
853 | /* ------------------------------------------------------------------ */ | 884 | /* ------------------------------------------------------------------ */ |
854 | 885 | ||
855 | static int lifeview_trio_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 886 | static int lifeview_trio_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) |
856 | { | 887 | { |
857 | int ret; | 888 | int ret; |
858 | 889 | ||
@@ -860,16 +891,12 @@ static int lifeview_trio_pll_set(struct dvb_frontend *fe, struct dvb_frontend_pa | |||
860 | return ret; | 891 | return ret; |
861 | } | 892 | } |
862 | 893 | ||
863 | static int lifeview_trio_dvb_mode(struct dvb_frontend *fe) | 894 | static int lifeview_trio_tuner_sleep(struct dvb_frontend *fe) |
864 | { | 895 | { |
896 | philips_tda827xa_tuner_sleep(0x60, fe); | ||
865 | return 0; | 897 | return 0; |
866 | } | 898 | } |
867 | 899 | ||
868 | static void lifeview_trio_analog_mode(struct dvb_frontend *fe) | ||
869 | { | ||
870 | philips_tda827xa_pll_sleep(0x60, fe); | ||
871 | } | ||
872 | |||
873 | static struct tda1004x_config lifeview_trio_config = { | 900 | static struct tda1004x_config lifeview_trio_config = { |
874 | .demod_address = 0x09, | 901 | .demod_address = 0x09, |
875 | .invert = 1, | 902 | .invert = 1, |
@@ -877,15 +904,12 @@ static struct tda1004x_config lifeview_trio_config = { | |||
877 | .xtal_freq = TDA10046_XTAL_16M, | 904 | .xtal_freq = TDA10046_XTAL_16M, |
878 | .agc_config = TDA10046_AGC_TDA827X_GPL, | 905 | .agc_config = TDA10046_AGC_TDA827X_GPL, |
879 | .if_freq = TDA10046_FREQ_045, | 906 | .if_freq = TDA10046_FREQ_045, |
880 | .pll_init = lifeview_trio_dvb_mode, | ||
881 | .pll_set = lifeview_trio_pll_set, | ||
882 | .pll_sleep = lifeview_trio_analog_mode, | ||
883 | .request_firmware = NULL, | 907 | .request_firmware = NULL, |
884 | }; | 908 | }; |
885 | 909 | ||
886 | /* ------------------------------------------------------------------ */ | 910 | /* ------------------------------------------------------------------ */ |
887 | 911 | ||
888 | static int ads_duo_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 912 | static int ads_duo_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) |
889 | { | 913 | { |
890 | int ret; | 914 | int ret; |
891 | 915 | ||
@@ -893,7 +917,7 @@ static int ads_duo_pll_set(struct dvb_frontend *fe, struct dvb_frontend_paramete | |||
893 | return ret; | 917 | return ret; |
894 | } | 918 | } |
895 | 919 | ||
896 | static int ads_duo_dvb_mode(struct dvb_frontend *fe) | 920 | static int ads_duo_tuner_init(struct dvb_frontend *fe) |
897 | { | 921 | { |
898 | struct saa7134_dev *dev = fe->dvb->priv; | 922 | struct saa7134_dev *dev = fe->dvb->priv; |
899 | /* route TDA8275a AGC input to the channel decoder */ | 923 | /* route TDA8275a AGC input to the channel decoder */ |
@@ -901,12 +925,13 @@ static int ads_duo_dvb_mode(struct dvb_frontend *fe) | |||
901 | return 0; | 925 | return 0; |
902 | } | 926 | } |
903 | 927 | ||
904 | static void ads_duo_analog_mode(struct dvb_frontend *fe) | 928 | static int ads_duo_tuner_sleep(struct dvb_frontend *fe) |
905 | { | 929 | { |
906 | struct saa7134_dev *dev = fe->dvb->priv; | 930 | struct saa7134_dev *dev = fe->dvb->priv; |
907 | /* route TDA8275a AGC input to the analog IF chip*/ | 931 | /* route TDA8275a AGC input to the analog IF chip*/ |
908 | saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x20); | 932 | saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x20); |
909 | philips_tda827xa_pll_sleep( 0x61, fe); | 933 | philips_tda827xa_tuner_sleep( 0x61, fe); |
934 | return 0; | ||
910 | } | 935 | } |
911 | 936 | ||
912 | static struct tda1004x_config ads_tech_duo_config = { | 937 | static struct tda1004x_config ads_tech_duo_config = { |
@@ -916,31 +941,24 @@ static struct tda1004x_config ads_tech_duo_config = { | |||
916 | .xtal_freq = TDA10046_XTAL_16M, | 941 | .xtal_freq = TDA10046_XTAL_16M, |
917 | .agc_config = TDA10046_AGC_TDA827X_GPL, | 942 | .agc_config = TDA10046_AGC_TDA827X_GPL, |
918 | .if_freq = TDA10046_FREQ_045, | 943 | .if_freq = TDA10046_FREQ_045, |
919 | .pll_init = ads_duo_dvb_mode, | ||
920 | .pll_set = ads_duo_pll_set, | ||
921 | .pll_sleep = ads_duo_analog_mode, | ||
922 | .request_firmware = NULL, | 944 | .request_firmware = NULL, |
923 | }; | 945 | }; |
924 | 946 | ||
925 | /* ------------------------------------------------------------------ */ | 947 | /* ------------------------------------------------------------------ */ |
926 | 948 | ||
927 | static int tevion_dvb220rf_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 949 | static int tevion_dvb220rf_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) |
928 | { | 950 | { |
929 | int ret; | 951 | int ret; |
930 | ret = philips_tda827xa_pll_set(0x60, fe, params); | 952 | ret = philips_tda827xa_pll_set(0x60, fe, params); |
931 | return ret; | 953 | return ret; |
932 | } | 954 | } |
933 | 955 | ||
934 | static int tevion_dvb220rf_pll_init(struct dvb_frontend *fe) | 956 | static int tevion_dvb220rf_tuner_sleep(struct dvb_frontend *fe) |
935 | { | 957 | { |
958 | philips_tda827xa_tuner_sleep( 0x61, fe); | ||
936 | return 0; | 959 | return 0; |
937 | } | 960 | } |
938 | 961 | ||
939 | static void tevion_dvb220rf_pll_sleep(struct dvb_frontend *fe) | ||
940 | { | ||
941 | philips_tda827xa_pll_sleep( 0x61, fe); | ||
942 | } | ||
943 | |||
944 | static struct tda1004x_config tevion_dvbt220rf_config = { | 962 | static struct tda1004x_config tevion_dvbt220rf_config = { |
945 | .demod_address = 0x08, | 963 | .demod_address = 0x08, |
946 | .invert = 1, | 964 | .invert = 1, |
@@ -948,9 +966,6 @@ static struct tda1004x_config tevion_dvbt220rf_config = { | |||
948 | .xtal_freq = TDA10046_XTAL_16M, | 966 | .xtal_freq = TDA10046_XTAL_16M, |
949 | .agc_config = TDA10046_AGC_TDA827X, | 967 | .agc_config = TDA10046_AGC_TDA827X, |
950 | .if_freq = TDA10046_FREQ_045, | 968 | .if_freq = TDA10046_FREQ_045, |
951 | .pll_init = tevion_dvb220rf_pll_init, | ||
952 | .pll_set = tevion_dvb220rf_pll_set, | ||
953 | .pll_sleep = tevion_dvb220rf_pll_sleep, | ||
954 | .request_firmware = NULL, | 969 | .request_firmware = NULL, |
955 | }; | 970 | }; |
956 | 971 | ||
@@ -961,8 +976,6 @@ static struct tda1004x_config tevion_dvbt220rf_config = { | |||
961 | #ifdef HAVE_NXT200X | 976 | #ifdef HAVE_NXT200X |
962 | static struct nxt200x_config avertvhda180 = { | 977 | static struct nxt200x_config avertvhda180 = { |
963 | .demod_address = 0x0a, | 978 | .demod_address = 0x0a, |
964 | .pll_address = 0x61, | ||
965 | .pll_desc = &dvb_pll_tdhu2, | ||
966 | }; | 979 | }; |
967 | 980 | ||
968 | static int nxt200x_set_pll_input(u8 *buf, int input) | 981 | static int nxt200x_set_pll_input(u8 *buf, int input) |
@@ -976,8 +989,6 @@ static int nxt200x_set_pll_input(u8 *buf, int input) | |||
976 | 989 | ||
977 | static struct nxt200x_config kworldatsc110 = { | 990 | static struct nxt200x_config kworldatsc110 = { |
978 | .demod_address = 0x0a, | 991 | .demod_address = 0x0a, |
979 | .pll_address = 0x61, | ||
980 | .pll_desc = &dvb_pll_tuv1236d, | ||
981 | .set_pll_input = nxt200x_set_pll_input, | 992 | .set_pll_input = nxt200x_set_pll_input, |
982 | }; | 993 | }; |
983 | #endif | 994 | #endif |
@@ -1003,78 +1014,158 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1003 | printk("%s: pinnacle 300i dvb setup\n",dev->name); | 1014 | printk("%s: pinnacle 300i dvb setup\n",dev->name); |
1004 | dev->dvb.frontend = mt352_attach(&pinnacle_300i, | 1015 | dev->dvb.frontend = mt352_attach(&pinnacle_300i, |
1005 | &dev->i2c_adap); | 1016 | &dev->i2c_adap); |
1017 | if (dev->dvb.frontend) { | ||
1018 | dev->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params; | ||
1019 | } | ||
1006 | break; | 1020 | break; |
1007 | 1021 | ||
1008 | case SAA7134_BOARD_AVERMEDIA_777: | 1022 | case SAA7134_BOARD_AVERMEDIA_777: |
1009 | printk("%s: avertv 777 dvb setup\n",dev->name); | 1023 | printk("%s: avertv 777 dvb setup\n",dev->name); |
1010 | dev->dvb.frontend = mt352_attach(&avermedia_777, | 1024 | dev->dvb.frontend = mt352_attach(&avermedia_777, |
1011 | &dev->i2c_adap); | 1025 | &dev->i2c_adap); |
1026 | if (dev->dvb.frontend) { | ||
1027 | dev->dvb.frontend->ops.tuner_ops.calc_regs = mt352_aver777_tuner_calc_regs; | ||
1028 | } | ||
1012 | break; | 1029 | break; |
1013 | #endif | 1030 | #endif |
1014 | #ifdef HAVE_TDA1004X | 1031 | #ifdef HAVE_TDA1004X |
1015 | case SAA7134_BOARD_MD7134: | 1032 | case SAA7134_BOARD_MD7134: |
1016 | dev->dvb.frontend = tda10046_attach(&medion_cardbus, | 1033 | dev->dvb.frontend = tda10046_attach(&medion_cardbus, |
1017 | &dev->i2c_adap); | 1034 | &dev->i2c_adap); |
1035 | if (dev->dvb.frontend) { | ||
1036 | dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init; | ||
1037 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep; | ||
1038 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; | ||
1039 | } | ||
1018 | break; | 1040 | break; |
1019 | case SAA7134_BOARD_PHILIPS_TOUGH: | 1041 | case SAA7134_BOARD_PHILIPS_TOUGH: |
1020 | dev->dvb.frontend = tda10046_attach(&philips_tu1216_60_config, | 1042 | dev->dvb.frontend = tda10046_attach(&philips_tu1216_60_config, |
1021 | &dev->i2c_adap); | 1043 | &dev->i2c_adap); |
1044 | if (dev->dvb.frontend) { | ||
1045 | dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_60_init; | ||
1046 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tu1216_tuner_60_set_params; | ||
1047 | } | ||
1022 | break; | 1048 | break; |
1023 | case SAA7134_BOARD_FLYDVBTDUO: | 1049 | case SAA7134_BOARD_FLYDVBTDUO: |
1024 | dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, | 1050 | dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, |
1025 | &dev->i2c_adap); | 1051 | &dev->i2c_adap); |
1052 | if (dev->dvb.frontend) { | ||
1053 | dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init; | ||
1054 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep; | ||
1055 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params; | ||
1056 | } | ||
1026 | break; | 1057 | break; |
1027 | case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: | 1058 | case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: |
1028 | dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, | 1059 | dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, |
1029 | &dev->i2c_adap); | 1060 | &dev->i2c_adap); |
1061 | if (dev->dvb.frontend) { | ||
1062 | dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init; | ||
1063 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep; | ||
1064 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params; | ||
1065 | } | ||
1030 | break; | 1066 | break; |
1031 | case SAA7134_BOARD_PHILIPS_EUROPA: | 1067 | case SAA7134_BOARD_PHILIPS_EUROPA: |
1032 | dev->dvb.frontend = tda10046_attach(&philips_europa_config, | 1068 | dev->dvb.frontend = tda10046_attach(&philips_europa_config, |
1033 | &dev->i2c_adap); | 1069 | &dev->i2c_adap); |
1070 | if (dev->dvb.frontend) { | ||
1071 | dev->original_demod_sleep = dev->dvb.frontend->ops.sleep; | ||
1072 | dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep; | ||
1073 | dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init; | ||
1074 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep; | ||
1075 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; | ||
1076 | } | ||
1034 | break; | 1077 | break; |
1035 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: | 1078 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: |
1036 | dev->dvb.frontend = tda10046_attach(&philips_europa_config, | 1079 | dev->dvb.frontend = tda10046_attach(&philips_europa_config, |
1037 | &dev->i2c_adap); | 1080 | &dev->i2c_adap); |
1081 | if (dev->dvb.frontend) { | ||
1082 | dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init; | ||
1083 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep; | ||
1084 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; | ||
1085 | } | ||
1038 | break; | 1086 | break; |
1039 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: | 1087 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: |
1040 | dev->dvb.frontend = tda10046_attach(&philips_tu1216_61_config, | 1088 | dev->dvb.frontend = tda10046_attach(&philips_tu1216_61_config, |
1041 | &dev->i2c_adap); | 1089 | &dev->i2c_adap); |
1090 | if (dev->dvb.frontend) { | ||
1091 | dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_61_init; | ||
1092 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tu1216_tuner_61_set_params; | ||
1093 | } | ||
1042 | break; | 1094 | break; |
1043 | case SAA7134_BOARD_PHILIPS_TIGER: | 1095 | case SAA7134_BOARD_PHILIPS_TIGER: |
1044 | dev->dvb.frontend = tda10046_attach(&philips_tiger_config, | 1096 | dev->dvb.frontend = tda10046_attach(&philips_tiger_config, |
1045 | &dev->i2c_adap); | 1097 | &dev->i2c_adap); |
1098 | if (dev->dvb.frontend) { | ||
1099 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; | ||
1100 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; | ||
1101 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | ||
1102 | } | ||
1046 | break; | 1103 | break; |
1047 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | 1104 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: |
1048 | dev->dvb.frontend = tda10046_attach(&philips_tiger_config, | 1105 | dev->dvb.frontend = tda10046_attach(&philips_tiger_config, |
1049 | &dev->i2c_adap); | 1106 | &dev->i2c_adap); |
1107 | if (dev->dvb.frontend) { | ||
1108 | dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; | ||
1109 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; | ||
1110 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; | ||
1111 | } | ||
1050 | break; | 1112 | break; |
1051 | case SAA7134_BOARD_FLYDVBT_LR301: | 1113 | case SAA7134_BOARD_FLYDVBT_LR301: |
1052 | dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, | 1114 | dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, |
1053 | &dev->i2c_adap); | 1115 | &dev->i2c_adap); |
1116 | if (dev->dvb.frontend) { | ||
1117 | dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init; | ||
1118 | dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep; | ||
1119 | dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params; | ||
1120 | } | ||
1054 | break; | 1121 | break; |
1055 | case SAA7134_BOARD_FLYDVB_TRIO: | 1122 | case SAA7134_BOARD_FLYDVB_TRIO: |
1056 | dev->dvb.frontend = tda10046_attach(&lifeview_trio_config, | 1123 | dev->dvb.frontend = tda10046_attach(&lifeview_trio_config, |
1057 | &dev->i2c_adap); | 1124 | &dev->i2c_adap); |
1125 | if (dev->dvb.frontend) { | ||
1126 | dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep; | ||
1127 | dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params; | ||
1128 | } | ||
1058 | break; | 1129 | break; |
1059 | case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: | 1130 | case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: |
1060 | dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config, | 1131 | dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config, |
1061 | &dev->i2c_adap); | 1132 | &dev->i2c_adap); |
1133 | if (dev->dvb.frontend) { | ||
1134 | dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init; | ||
1135 | dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep; | ||
1136 | dev->dvb.frontend->ops.tuner_ops.set_params = ads_duo_tuner_set_params; | ||
1137 | } | ||
1062 | break; | 1138 | break; |
1063 | case SAA7134_BOARD_TEVION_DVBT_220RF: | 1139 | case SAA7134_BOARD_TEVION_DVBT_220RF: |
1064 | dev->dvb.frontend = tda10046_attach(&tevion_dvbt220rf_config, | 1140 | dev->dvb.frontend = tda10046_attach(&tevion_dvbt220rf_config, |
1065 | &dev->i2c_adap); | 1141 | &dev->i2c_adap); |
1142 | if (dev->dvb.frontend) { | ||
1143 | dev->dvb.frontend->ops.tuner_ops.sleep = tevion_dvb220rf_tuner_sleep; | ||
1144 | dev->dvb.frontend->ops.tuner_ops.set_params = tevion_dvb220rf_tuner_set_params; | ||
1145 | } | ||
1066 | break; | 1146 | break; |
1067 | case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS: | 1147 | case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS: |
1068 | dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config, | 1148 | dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config, |
1069 | &dev->i2c_adap); | 1149 | &dev->i2c_adap); |
1150 | if (dev->dvb.frontend) { | ||
1151 | dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init; | ||
1152 | dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep; | ||
1153 | dev->dvb.frontend->ops.tuner_ops.set_params = ads_duo_tuner_set_params; | ||
1154 | } | ||
1070 | break; | 1155 | break; |
1071 | #endif | 1156 | #endif |
1072 | #ifdef HAVE_NXT200X | 1157 | #ifdef HAVE_NXT200X |
1073 | case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: | 1158 | case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: |
1074 | dev->dvb.frontend = nxt200x_attach(&avertvhda180, &dev->i2c_adap); | 1159 | dev->dvb.frontend = nxt200x_attach(&avertvhda180, &dev->i2c_adap); |
1160 | if (dev->dvb.frontend) { | ||
1161 | dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tdhu2); | ||
1162 | } | ||
1075 | break; | 1163 | break; |
1076 | case SAA7134_BOARD_KWORLD_ATSC110: | 1164 | case SAA7134_BOARD_KWORLD_ATSC110: |
1077 | dev->dvb.frontend = nxt200x_attach(&kworldatsc110, &dev->i2c_adap); | 1165 | dev->dvb.frontend = nxt200x_attach(&kworldatsc110, &dev->i2c_adap); |
1166 | if (dev->dvb.frontend) { | ||
1167 | dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tuv1236d); | ||
1168 | } | ||
1078 | break; | 1169 | break; |
1079 | #endif | 1170 | #endif |
1080 | default: | 1171 | default: |
@@ -1088,7 +1179,7 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1088 | } | 1179 | } |
1089 | 1180 | ||
1090 | /* register everything else */ | 1181 | /* register everything else */ |
1091 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); | 1182 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev); |
1092 | } | 1183 | } |
1093 | 1184 | ||
1094 | static int dvb_fini(struct saa7134_dev *dev) | 1185 | static int dvb_fini(struct saa7134_dev *dev) |
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 1d972edb3be6..65d044086ce9 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c | |||
@@ -64,8 +64,10 @@ static void ts_reset_encoder(struct saa7134_dev* dev) | |||
64 | 64 | ||
65 | static int ts_init_encoder(struct saa7134_dev* dev) | 65 | static int ts_init_encoder(struct saa7134_dev* dev) |
66 | { | 66 | { |
67 | struct v4l2_ext_controls ctrls = { V4L2_CTRL_CLASS_MPEG, 0 }; | ||
68 | |||
67 | ts_reset_encoder(dev); | 69 | ts_reset_encoder(dev); |
68 | saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, NULL); | 70 | saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, &ctrls); |
69 | dev->empress_started = 1; | 71 | dev->empress_started = 1; |
70 | return 0; | 72 | return 0; |
71 | } | 73 | } |
@@ -162,6 +164,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, | |||
162 | unsigned int cmd, void *arg) | 164 | unsigned int cmd, void *arg) |
163 | { | 165 | { |
164 | struct saa7134_dev *dev = file->private_data; | 166 | struct saa7134_dev *dev = file->private_data; |
167 | struct v4l2_ext_controls *ctrls = arg; | ||
165 | 168 | ||
166 | if (debug > 1) | 169 | if (debug > 1) |
167 | v4l_print_ioctl(dev->name,cmd); | 170 | v4l_print_ioctl(dev->name,cmd); |
@@ -278,12 +281,31 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, | |||
278 | return saa7134_common_ioctl(dev, cmd, arg); | 281 | return saa7134_common_ioctl(dev, cmd, arg); |
279 | 282 | ||
280 | case VIDIOC_S_MPEGCOMP: | 283 | case VIDIOC_S_MPEGCOMP: |
284 | printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. " | ||
285 | "Replace with VIDIOC_S_EXT_CTRLS!"); | ||
281 | saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, arg); | 286 | saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, arg); |
282 | ts_init_encoder(dev); | 287 | ts_init_encoder(dev); |
283 | return 0; | 288 | return 0; |
284 | case VIDIOC_G_MPEGCOMP: | 289 | case VIDIOC_G_MPEGCOMP: |
290 | printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. " | ||
291 | "Replace with VIDIOC_G_EXT_CTRLS!"); | ||
285 | saa7134_i2c_call_clients(dev, VIDIOC_G_MPEGCOMP, arg); | 292 | saa7134_i2c_call_clients(dev, VIDIOC_G_MPEGCOMP, arg); |
286 | return 0; | 293 | return 0; |
294 | case VIDIOC_S_EXT_CTRLS: | ||
295 | /* count == 0 is abused in saa6752hs.c, so that special | ||
296 | case is handled here explicitly. */ | ||
297 | if (ctrls->count == 0) | ||
298 | return 0; | ||
299 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | ||
300 | return -EINVAL; | ||
301 | saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, arg); | ||
302 | ts_init_encoder(dev); | ||
303 | return 0; | ||
304 | case VIDIOC_G_EXT_CTRLS: | ||
305 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | ||
306 | return -EINVAL; | ||
307 | saa7134_i2c_call_clients(dev, VIDIOC_G_EXT_CTRLS, arg); | ||
308 | return 0; | ||
287 | 309 | ||
288 | default: | 310 | default: |
289 | return -ENOIOCTLCMD; | 311 | return -ENOIOCTLCMD; |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 1426e4c8602f..7c595492c56b 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -37,6 +37,10 @@ static unsigned int ir_debug = 0; | |||
37 | module_param(ir_debug, int, 0644); | 37 | module_param(ir_debug, int, 0644); |
38 | MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); | 38 | MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); |
39 | 39 | ||
40 | static int pinnacle_remote = 0; | ||
41 | module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ | ||
42 | MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); | ||
43 | |||
40 | #define dprintk(fmt, arg...) if (ir_debug) \ | 44 | #define dprintk(fmt, arg...) if (ir_debug) \ |
41 | printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) | 45 | printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) |
42 | #define i2cdprintk(fmt, arg...) if (ir_debug) \ | 46 | #define i2cdprintk(fmt, arg...) if (ir_debug) \ |
@@ -316,8 +320,13 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) | |||
316 | switch (dev->board) { | 320 | switch (dev->board) { |
317 | case SAA7134_BOARD_PINNACLE_PCTV_110i: | 321 | case SAA7134_BOARD_PINNACLE_PCTV_110i: |
318 | snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); | 322 | snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); |
319 | ir->get_key = get_key_pinnacle; | 323 | if (pinnacle_remote == 0) { |
320 | ir->ir_codes = ir_codes_pinnacle; | 324 | ir->get_key = get_key_pinnacle_color; |
325 | ir->ir_codes = ir_codes_pinnacle_color; | ||
326 | } else { | ||
327 | ir->get_key = get_key_pinnacle_grey; | ||
328 | ir->ir_codes = ir_codes_pinnacle_grey; | ||
329 | } | ||
321 | break; | 330 | break; |
322 | case SAA7134_BOARD_UPMOST_PURPLE_TV: | 331 | case SAA7134_BOARD_UPMOST_PURPLE_TV: |
323 | snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV"); | 332 | snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV"); |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 353af3a8b766..d5ee99c574cc 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -33,6 +33,7 @@ | |||
33 | 33 | ||
34 | #include <asm/io.h> | 34 | #include <asm/io.h> |
35 | 35 | ||
36 | #include <media/v4l2-common.h> | ||
36 | #include <media/tuner.h> | 37 | #include <media/tuner.h> |
37 | #include <media/ir-common.h> | 38 | #include <media/ir-common.h> |
38 | #include <media/ir-kbd-i2c.h> | 39 | #include <media/ir-kbd-i2c.h> |
@@ -221,6 +222,7 @@ struct saa7134_format { | |||
221 | #define SAA7134_BOARD_AVERMEDIA_A169_B1 92 | 222 | #define SAA7134_BOARD_AVERMEDIA_A169_B1 92 |
222 | #define SAA7134_BOARD_MD7134_BRIDGE_2 93 | 223 | #define SAA7134_BOARD_MD7134_BRIDGE_2 93 |
223 | #define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94 | 224 | #define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94 |
225 | #define SAA7134_BOARD_FLYVIDEO3000_NTSC 95 | ||
224 | 226 | ||
225 | #define SAA7134_MAXBOARDS 8 | 227 | #define SAA7134_MAXBOARDS 8 |
226 | #define SAA7134_INPUT_MAX 8 | 228 | #define SAA7134_INPUT_MAX 8 |
@@ -531,6 +533,7 @@ struct saa7134_dev { | |||
531 | 533 | ||
532 | /* SAA7134_MPEG_DVB only */ | 534 | /* SAA7134_MPEG_DVB only */ |
533 | struct videobuf_dvb dvb; | 535 | struct videobuf_dvb dvb; |
536 | int (*original_demod_sleep)(struct dvb_frontend* fe); | ||
534 | }; | 537 | }; |
535 | 538 | ||
536 | /* ----------------------------------------------------------- */ | 539 | /* ----------------------------------------------------------- */ |
diff --git a/drivers/media/video/se401.h b/drivers/media/video/se401.h index a7a216bd4413..c0891b3e0018 100644 --- a/drivers/media/video/se401.h +++ b/drivers/media/video/se401.h | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | #include <asm/uaccess.h> | 5 | #include <asm/uaccess.h> |
6 | #include <linux/videodev.h> | 6 | #include <linux/videodev.h> |
7 | #include <media/v4l2-common.h> | ||
7 | #include <linux/smp_lock.h> | 8 | #include <linux/smp_lock.h> |
8 | #include <linux/mutex.h> | 9 | #include <linux/mutex.h> |
9 | 10 | ||
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index ea4394dc9415..48d138a7c723 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c | |||
@@ -2608,11 +2608,9 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
2608 | case VIDIOC_G_CTRL: | 2608 | case VIDIOC_G_CTRL: |
2609 | return sn9c102_vidioc_g_ctrl(cam, arg); | 2609 | return sn9c102_vidioc_g_ctrl(cam, arg); |
2610 | 2610 | ||
2611 | case VIDIOC_S_CTRL_OLD: | ||
2612 | case VIDIOC_S_CTRL: | 2611 | case VIDIOC_S_CTRL: |
2613 | return sn9c102_vidioc_s_ctrl(cam, arg); | 2612 | return sn9c102_vidioc_s_ctrl(cam, arg); |
2614 | 2613 | ||
2615 | case VIDIOC_CROPCAP_OLD: | ||
2616 | case VIDIOC_CROPCAP: | 2614 | case VIDIOC_CROPCAP: |
2617 | return sn9c102_vidioc_cropcap(cam, arg); | 2615 | return sn9c102_vidioc_cropcap(cam, arg); |
2618 | 2616 | ||
@@ -2659,7 +2657,6 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
2659 | case VIDIOC_G_PARM: | 2657 | case VIDIOC_G_PARM: |
2660 | return sn9c102_vidioc_g_parm(cam, arg); | 2658 | return sn9c102_vidioc_g_parm(cam, arg); |
2661 | 2659 | ||
2662 | case VIDIOC_S_PARM_OLD: | ||
2663 | case VIDIOC_S_PARM: | 2660 | case VIDIOC_S_PARM: |
2664 | return sn9c102_vidioc_s_parm(cam, arg); | 2661 | return sn9c102_vidioc_s_parm(cam, arg); |
2665 | 2662 | ||
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 07476c71174a..6be9c1131e1f 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
43 | #include <linux/vmalloc.h> | 43 | #include <linux/vmalloc.h> |
44 | #include <linux/videodev.h> | 44 | #include <linux/videodev.h> |
45 | #include <media/v4l2-common.h> | ||
45 | 46 | ||
46 | #include "saa7146.h" | 47 | #include "saa7146.h" |
47 | #include "saa7146reg.h" | 48 | #include "saa7146reg.h" |
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index b38bda83a7c5..351b182d921f 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c | |||
@@ -66,6 +66,7 @@ | |||
66 | #include <linux/pagemap.h> | 66 | #include <linux/pagemap.h> |
67 | #include <linux/errno.h> | 67 | #include <linux/errno.h> |
68 | #include <linux/videodev.h> | 68 | #include <linux/videodev.h> |
69 | #include <media/v4l2-common.h> | ||
69 | #include <linux/usb.h> | 70 | #include <linux/usb.h> |
70 | #include <linux/mutex.h> | 71 | #include <linux/mutex.h> |
71 | 72 | ||
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 103ccb919292..827633b3bb43 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/videodev.h> | 28 | #include <linux/videodev.h> |
29 | #include <media/v4l2-common.h> | ||
29 | #include <linux/i2c.h> | 30 | #include <linux/i2c.h> |
30 | #include <linux/i2c-algo-bit.h> | 31 | #include <linux/i2c-algo-bit.h> |
31 | #include <linux/init.h> | 32 | #include <linux/init.h> |
@@ -163,7 +164,7 @@ static void do_tda9875_init(struct i2c_client *client) | |||
163 | struct tda9875 *t = i2c_get_clientdata(client); | 164 | struct tda9875 *t = i2c_get_clientdata(client); |
164 | dprintk("In tda9875_init\n"); | 165 | dprintk("In tda9875_init\n"); |
165 | tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/ | 166 | tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/ |
166 | tda9875_write(client, TDA9875_MSR, 0x03 ); /* Monitor 0b00000XXX*/ | 167 | tda9875_write(client, TDA9875_MSR, 0x03 ); /* Monitor 0b00000XXX*/ |
167 | tda9875_write(client, TDA9875_C1MSB, 0x00 ); /*Car1(FM) MSB XMHz*/ | 168 | tda9875_write(client, TDA9875_C1MSB, 0x00 ); /*Car1(FM) MSB XMHz*/ |
168 | tda9875_write(client, TDA9875_C1MIB, 0x00 ); /*Car1(FM) MIB XMHz*/ | 169 | tda9875_write(client, TDA9875_C1MIB, 0x00 ); /*Car1(FM) MIB XMHz*/ |
169 | tda9875_write(client, TDA9875_C1LSB, 0x00 ); /*Car1(FM) LSB XMHz*/ | 170 | tda9875_write(client, TDA9875_C1LSB, 0x00 ); /*Car1(FM) LSB XMHz*/ |
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 0d54f6c1982b..b6ae969563b2 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c | |||
@@ -18,49 +18,21 @@ | |||
18 | TDA9886 (PAL, SECAM, NTSC) | 18 | TDA9886 (PAL, SECAM, NTSC) |
19 | TDA9887 (PAL, SECAM, NTSC, FM Radio) | 19 | TDA9887 (PAL, SECAM, NTSC, FM Radio) |
20 | 20 | ||
21 | found on: | 21 | Used as part of several tuners |
22 | - Pinnacle PCTV (Jul.2002 Version with MT2032, bttv) | ||
23 | TDA9887 (world), TDA9885 (USA) | ||
24 | Note: OP2 of tda988x must be set to 1, else MT2032 is disabled! | ||
25 | - KNC One TV-Station RDS (saa7134) | ||
26 | - Hauppauge PVR-150/500 (possibly more) | ||
27 | */ | 22 | */ |
28 | 23 | ||
24 | #define tda9887_info(fmt, arg...) do {\ | ||
25 | printk(KERN_INFO "%s %d-%04x (tda9887): " fmt, t->i2c.name, \ | ||
26 | i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) | ||
27 | #define tda9887_dbg(fmt, arg...) do {\ | ||
28 | if (tuner_debug) \ | ||
29 | printk(KERN_INFO "%s %d-%04x (tda9887): " fmt, t->i2c.name, \ | ||
30 | i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) | ||
29 | 31 | ||
30 | /* Addresses to scan */ | ||
31 | static unsigned short normal_i2c[] = { | ||
32 | 0x84 >>1, | ||
33 | 0x86 >>1, | ||
34 | 0x96 >>1, | ||
35 | I2C_CLIENT_END, | ||
36 | }; | ||
37 | I2C_CLIENT_INSMOD; | ||
38 | |||
39 | /* insmod options */ | ||
40 | static unsigned int debug = 0; | ||
41 | module_param(debug, int, 0644); | ||
42 | MODULE_LICENSE("GPL"); | ||
43 | 32 | ||
44 | /* ---------------------------------------------------------------------- */ | 33 | /* ---------------------------------------------------------------------- */ |
45 | 34 | ||
46 | #define UNSET (-1U) | 35 | #define UNSET (-1U) |
47 | #define tda9887_info(fmt, arg...) do {\ | ||
48 | printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ | ||
49 | i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) | ||
50 | #define tda9887_dbg(fmt, arg...) do {\ | ||
51 | if (debug) \ | ||
52 | printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ | ||
53 | i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) | ||
54 | |||
55 | struct tda9887 { | ||
56 | struct i2c_client client; | ||
57 | v4l2_std_id std; | ||
58 | enum tuner_mode mode; | ||
59 | unsigned int config; | ||
60 | unsigned int using_v4l2; | ||
61 | unsigned int radio_mode; | ||
62 | unsigned char data[4]; | ||
63 | }; | ||
64 | 36 | ||
65 | struct tvnorm { | 37 | struct tvnorm { |
66 | v4l2_std_id std; | 38 | v4l2_std_id std; |
@@ -70,9 +42,6 @@ struct tvnorm { | |||
70 | unsigned char e; | 42 | unsigned char e; |
71 | }; | 43 | }; |
72 | 44 | ||
73 | static struct i2c_driver driver; | ||
74 | static struct i2c_client client_template; | ||
75 | |||
76 | /* ---------------------------------------------------------------------- */ | 45 | /* ---------------------------------------------------------------------- */ |
77 | 46 | ||
78 | // | 47 | // |
@@ -281,7 +250,7 @@ static struct tvnorm radio_mono = { | |||
281 | 250 | ||
282 | /* ---------------------------------------------------------------------- */ | 251 | /* ---------------------------------------------------------------------- */ |
283 | 252 | ||
284 | static void dump_read_message(struct tda9887 *t, unsigned char *buf) | 253 | static void dump_read_message(struct tuner *t, unsigned char *buf) |
285 | { | 254 | { |
286 | static char *afc[16] = { | 255 | static char *afc[16] = { |
287 | "- 12.5 kHz", | 256 | "- 12.5 kHz", |
@@ -309,7 +278,7 @@ static void dump_read_message(struct tda9887 *t, unsigned char *buf) | |||
309 | tda9887_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); | 278 | tda9887_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); |
310 | } | 279 | } |
311 | 280 | ||
312 | static void dump_write_message(struct tda9887 *t, unsigned char *buf) | 281 | static void dump_write_message(struct tuner *t, unsigned char *buf) |
313 | { | 282 | { |
314 | static char *sound[4] = { | 283 | static char *sound[4] = { |
315 | "AM/TV", | 284 | "AM/TV", |
@@ -405,13 +374,13 @@ static void dump_write_message(struct tda9887 *t, unsigned char *buf) | |||
405 | 374 | ||
406 | /* ---------------------------------------------------------------------- */ | 375 | /* ---------------------------------------------------------------------- */ |
407 | 376 | ||
408 | static int tda9887_set_tvnorm(struct tda9887 *t, char *buf) | 377 | static int tda9887_set_tvnorm(struct tuner *t, char *buf) |
409 | { | 378 | { |
410 | struct tvnorm *norm = NULL; | 379 | struct tvnorm *norm = NULL; |
411 | int i; | 380 | int i; |
412 | 381 | ||
413 | if (t->mode == T_RADIO) { | 382 | if (t->mode == V4L2_TUNER_RADIO) { |
414 | if (t->radio_mode == V4L2_TUNER_MODE_MONO) | 383 | if (t->audmode == V4L2_TUNER_MODE_MONO) |
415 | norm = &radio_mono; | 384 | norm = &radio_mono; |
416 | else | 385 | else |
417 | norm = &radio_stereo; | 386 | norm = &radio_stereo; |
@@ -445,7 +414,7 @@ module_param(port2, int, 0644); | |||
445 | module_param(qss, int, 0644); | 414 | module_param(qss, int, 0644); |
446 | module_param(adjust, int, 0644); | 415 | module_param(adjust, int, 0644); |
447 | 416 | ||
448 | static int tda9887_set_insmod(struct tda9887 *t, char *buf) | 417 | static int tda9887_set_insmod(struct tuner *t, char *buf) |
449 | { | 418 | { |
450 | if (UNSET != port1) { | 419 | if (UNSET != port1) { |
451 | if (port1) | 420 | if (port1) |
@@ -474,27 +443,27 @@ static int tda9887_set_insmod(struct tda9887 *t, char *buf) | |||
474 | return 0; | 443 | return 0; |
475 | } | 444 | } |
476 | 445 | ||
477 | static int tda9887_set_config(struct tda9887 *t, char *buf) | 446 | static int tda9887_set_config(struct tuner *t, char *buf) |
478 | { | 447 | { |
479 | if (t->config & TDA9887_PORT1_ACTIVE) | 448 | if (t->tda9887_config & TDA9887_PORT1_ACTIVE) |
480 | buf[1] &= ~cOutputPort1Inactive; | 449 | buf[1] &= ~cOutputPort1Inactive; |
481 | if (t->config & TDA9887_PORT1_INACTIVE) | 450 | if (t->tda9887_config & TDA9887_PORT1_INACTIVE) |
482 | buf[1] |= cOutputPort1Inactive; | 451 | buf[1] |= cOutputPort1Inactive; |
483 | if (t->config & TDA9887_PORT2_ACTIVE) | 452 | if (t->tda9887_config & TDA9887_PORT2_ACTIVE) |
484 | buf[1] &= ~cOutputPort2Inactive; | 453 | buf[1] &= ~cOutputPort2Inactive; |
485 | if (t->config & TDA9887_PORT2_INACTIVE) | 454 | if (t->tda9887_config & TDA9887_PORT2_INACTIVE) |
486 | buf[1] |= cOutputPort2Inactive; | 455 | buf[1] |= cOutputPort2Inactive; |
487 | 456 | ||
488 | if (t->config & TDA9887_QSS) | 457 | if (t->tda9887_config & TDA9887_QSS) |
489 | buf[1] |= cQSS; | 458 | buf[1] |= cQSS; |
490 | if (t->config & TDA9887_INTERCARRIER) | 459 | if (t->tda9887_config & TDA9887_INTERCARRIER) |
491 | buf[1] &= ~cQSS; | 460 | buf[1] &= ~cQSS; |
492 | 461 | ||
493 | if (t->config & TDA9887_AUTOMUTE) | 462 | if (t->tda9887_config & TDA9887_AUTOMUTE) |
494 | buf[1] |= cAutoMuteFmActive; | 463 | buf[1] |= cAutoMuteFmActive; |
495 | if (t->config & TDA9887_DEEMPHASIS_MASK) { | 464 | if (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) { |
496 | buf[2] &= ~0x60; | 465 | buf[2] &= ~0x60; |
497 | switch (t->config & TDA9887_DEEMPHASIS_MASK) { | 466 | switch (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) { |
498 | case TDA9887_DEEMPHASIS_NONE: | 467 | case TDA9887_DEEMPHASIS_NONE: |
499 | buf[2] |= cDeemphasisOFF; | 468 | buf[2] |= cDeemphasisOFF; |
500 | break; | 469 | break; |
@@ -506,153 +475,36 @@ static int tda9887_set_config(struct tda9887 *t, char *buf) | |||
506 | break; | 475 | break; |
507 | } | 476 | } |
508 | } | 477 | } |
509 | if (t->config & TDA9887_TOP_SET) { | 478 | if (t->tda9887_config & TDA9887_TOP_SET) { |
510 | buf[2] &= ~cTopMask; | 479 | buf[2] &= ~cTopMask; |
511 | buf[2] |= (t->config >> 8) & cTopMask; | 480 | buf[2] |= (t->tda9887_config >> 8) & cTopMask; |
512 | } | 481 | } |
513 | if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) | 482 | if ((t->tda9887_config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) |
514 | buf[1] &= ~cQSS; | 483 | buf[1] &= ~cQSS; |
515 | return 0; | 484 | return 0; |
516 | } | 485 | } |
517 | 486 | ||
518 | /* ---------------------------------------------------------------------- */ | 487 | /* ---------------------------------------------------------------------- */ |
519 | 488 | ||
520 | static char pal[] = "--"; | 489 | static int tda9887_status(struct tuner *t) |
521 | static char secam[] = "--"; | ||
522 | static char ntsc[] = "-"; | ||
523 | |||
524 | module_param_string(pal, pal, sizeof(pal), 0644); | ||
525 | module_param_string(secam, secam, sizeof(secam), 0644); | ||
526 | module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); | ||
527 | |||
528 | static int tda9887_fixup_std(struct tda9887 *t) | ||
529 | { | ||
530 | /* get more precise norm info from insmod option */ | ||
531 | if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) { | ||
532 | switch (pal[0]) { | ||
533 | case 'b': | ||
534 | case 'B': | ||
535 | case 'g': | ||
536 | case 'G': | ||
537 | case 'h': | ||
538 | case 'H': | ||
539 | case 'n': | ||
540 | case 'N': | ||
541 | if (pal[1] == 'c' || pal[1] == 'C') { | ||
542 | tda9887_dbg("insmod fixup: PAL => PAL-Nc\n"); | ||
543 | t->std = V4L2_STD_PAL_Nc; | ||
544 | } else { | ||
545 | tda9887_dbg("insmod fixup: PAL => PAL-BGHN\n"); | ||
546 | t->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N; | ||
547 | } | ||
548 | break; | ||
549 | case 'i': | ||
550 | case 'I': | ||
551 | tda9887_dbg("insmod fixup: PAL => PAL-I\n"); | ||
552 | t->std = V4L2_STD_PAL_I; | ||
553 | break; | ||
554 | case 'd': | ||
555 | case 'D': | ||
556 | case 'k': | ||
557 | case 'K': | ||
558 | tda9887_dbg("insmod fixup: PAL => PAL-DK\n"); | ||
559 | t->std = V4L2_STD_PAL_DK; | ||
560 | break; | ||
561 | case 'm': | ||
562 | case 'M': | ||
563 | tda9887_dbg("insmod fixup: PAL => PAL-M\n"); | ||
564 | t->std = V4L2_STD_PAL_M; | ||
565 | break; | ||
566 | case '-': | ||
567 | /* default parameter, do nothing */ | ||
568 | break; | ||
569 | default: | ||
570 | tda9887_info("pal= argument not recognised\n"); | ||
571 | break; | ||
572 | } | ||
573 | } | ||
574 | if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { | ||
575 | switch (secam[0]) { | ||
576 | case 'b': | ||
577 | case 'B': | ||
578 | case 'g': | ||
579 | case 'G': | ||
580 | case 'h': | ||
581 | case 'H': | ||
582 | tda9887_dbg("insmod fixup: SECAM => SECAM-BGH\n"); | ||
583 | t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; | ||
584 | break; | ||
585 | case 'd': | ||
586 | case 'D': | ||
587 | case 'k': | ||
588 | case 'K': | ||
589 | tda9887_dbg("insmod fixup: SECAM => SECAM-DK\n"); | ||
590 | t->std = V4L2_STD_SECAM_DK; | ||
591 | break; | ||
592 | case 'l': | ||
593 | case 'L': | ||
594 | if (secam[1] == 'c' || secam[1] == 'C') { | ||
595 | tda9887_dbg("insmod fixup: SECAM => SECAM-L'\n"); | ||
596 | t->std = V4L2_STD_SECAM_LC; | ||
597 | } else { | ||
598 | tda9887_dbg("insmod fixup: SECAM => SECAM-L\n"); | ||
599 | t->std = V4L2_STD_SECAM_L; | ||
600 | } | ||
601 | break; | ||
602 | case '-': | ||
603 | /* default parameter, do nothing */ | ||
604 | break; | ||
605 | default: | ||
606 | tda9887_info("secam= argument not recognised\n"); | ||
607 | break; | ||
608 | } | ||
609 | } | ||
610 | if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) { | ||
611 | switch (ntsc[0]) { | ||
612 | case 'm': | ||
613 | case 'M': | ||
614 | tda9887_dbg("insmod fixup: NTSC => NTSC-M\n"); | ||
615 | t->std = V4L2_STD_NTSC_M; | ||
616 | break; | ||
617 | case 'j': | ||
618 | case 'J': | ||
619 | tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); | ||
620 | t->std = V4L2_STD_NTSC_M_JP; | ||
621 | break; | ||
622 | case 'k': | ||
623 | case 'K': | ||
624 | tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n"); | ||
625 | t->std = V4L2_STD_NTSC_M_KR; | ||
626 | break; | ||
627 | case '-': | ||
628 | /* default parameter, do nothing */ | ||
629 | break; | ||
630 | default: | ||
631 | tda9887_info("ntsc= argument not recognised\n"); | ||
632 | break; | ||
633 | } | ||
634 | } | ||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | static int tda9887_status(struct tda9887 *t) | ||
639 | { | 490 | { |
640 | unsigned char buf[1]; | 491 | unsigned char buf[1]; |
641 | int rc; | 492 | int rc; |
642 | 493 | ||
643 | memset(buf,0,sizeof(buf)); | 494 | memset(buf,0,sizeof(buf)); |
644 | if (1 != (rc = i2c_master_recv(&t->client,buf,1))) | 495 | if (1 != (rc = i2c_master_recv(&t->i2c,buf,1))) |
645 | tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); | 496 | tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); |
646 | dump_read_message(t, buf); | 497 | dump_read_message(t, buf); |
647 | return 0; | 498 | return 0; |
648 | } | 499 | } |
649 | 500 | ||
650 | static int tda9887_configure(struct tda9887 *t) | 501 | static void tda9887_configure(struct i2c_client *client) |
651 | { | 502 | { |
503 | struct tuner *t = i2c_get_clientdata(client); | ||
652 | int rc; | 504 | int rc; |
653 | 505 | ||
654 | memset(t->data,0,sizeof(t->data)); | 506 | memset(t->tda9887_data,0,sizeof(t->tda9887_data)); |
655 | tda9887_set_tvnorm(t,t->data); | 507 | tda9887_set_tvnorm(t,t->tda9887_data); |
656 | 508 | ||
657 | /* A note on the port settings: | 509 | /* A note on the port settings: |
658 | These settings tend to depend on the specifics of the board. | 510 | These settings tend to depend on the specifics of the board. |
@@ -667,249 +519,84 @@ static int tda9887_configure(struct tda9887 *t) | |||
667 | the ports should be set to active (0), but, again, that may | 519 | the ports should be set to active (0), but, again, that may |
668 | differ depending on the precise hardware configuration. | 520 | differ depending on the precise hardware configuration. |
669 | */ | 521 | */ |
670 | t->data[1] |= cOutputPort1Inactive; | 522 | t->tda9887_data[1] |= cOutputPort1Inactive; |
671 | t->data[1] |= cOutputPort2Inactive; | 523 | t->tda9887_data[1] |= cOutputPort2Inactive; |
672 | 524 | ||
673 | tda9887_set_config(t,t->data); | 525 | tda9887_set_config(t,t->tda9887_data); |
674 | tda9887_set_insmod(t,t->data); | 526 | tda9887_set_insmod(t,t->tda9887_data); |
675 | 527 | ||
676 | if (t->mode == T_STANDBY) { | 528 | if (t->mode == T_STANDBY) { |
677 | t->data[1] |= cForcedMuteAudioON; | 529 | t->tda9887_data[1] |= cForcedMuteAudioON; |
678 | } | 530 | } |
679 | 531 | ||
680 | tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", | 532 | tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", |
681 | t->data[1],t->data[2],t->data[3]); | 533 | t->tda9887_data[1],t->tda9887_data[2],t->tda9887_data[3]); |
682 | if (debug > 1) | 534 | if (tuner_debug > 1) |
683 | dump_write_message(t, t->data); | 535 | dump_write_message(t, t->tda9887_data); |
684 | 536 | ||
685 | if (4 != (rc = i2c_master_send(&t->client,t->data,4))) | 537 | if (4 != (rc = i2c_master_send(&t->i2c,t->tda9887_data,4))) |
686 | tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); | 538 | tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); |
687 | 539 | ||
688 | if (debug > 2) { | 540 | if (tuner_debug > 2) { |
689 | msleep_interruptible(1000); | 541 | msleep_interruptible(1000); |
690 | tda9887_status(t); | 542 | tda9887_status(t); |
691 | } | 543 | } |
692 | return 0; | ||
693 | } | 544 | } |
694 | 545 | ||
695 | /* ---------------------------------------------------------------------- */ | 546 | /* ---------------------------------------------------------------------- */ |
696 | 547 | ||
697 | static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) | 548 | static void tda9887_tuner_status(struct i2c_client *client) |
698 | { | 549 | { |
699 | struct tda9887 *t; | 550 | struct tuner *t = i2c_get_clientdata(client); |
700 | 551 | tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->tda9887_data[1], t->tda9887_data[2], t->tda9887_data[3]); | |
701 | client_template.adapter = adap; | ||
702 | client_template.addr = addr; | ||
703 | |||
704 | if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL))) | ||
705 | return -ENOMEM; | ||
706 | |||
707 | t->client = client_template; | ||
708 | t->std = 0; | ||
709 | t->radio_mode = V4L2_TUNER_MODE_STEREO; | ||
710 | |||
711 | tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name); | ||
712 | |||
713 | i2c_set_clientdata(&t->client, t); | ||
714 | i2c_attach_client(&t->client); | ||
715 | |||
716 | return 0; | ||
717 | } | 552 | } |
718 | 553 | ||
719 | static int tda9887_probe(struct i2c_adapter *adap) | 554 | static int tda9887_get_afc(struct i2c_client *client) |
720 | { | 555 | { |
721 | if (adap->class & I2C_CLASS_TV_ANALOG) | 556 | struct tuner *t = i2c_get_clientdata(client); |
722 | return i2c_probe(adap, &addr_data, tda9887_attach); | 557 | static int AFC_BITS_2_kHz[] = { |
723 | return 0; | 558 | -12500, -37500, -62500, -97500, |
724 | } | 559 | -112500, -137500, -162500, -187500, |
560 | 187500, 162500, 137500, 112500, | ||
561 | 97500 , 62500, 37500 , 12500 | ||
562 | }; | ||
563 | int afc=0; | ||
564 | __u8 reg = 0; | ||
725 | 565 | ||
726 | static int tda9887_detach(struct i2c_client *client) | 566 | if (1 == i2c_master_recv(&t->i2c,®,1)) |
727 | { | 567 | afc = AFC_BITS_2_kHz[(reg>>1)&0x0f]; |
728 | struct tda9887 *t = i2c_get_clientdata(client); | ||
729 | 568 | ||
730 | i2c_detach_client(client); | 569 | return afc; |
731 | kfree(t); | ||
732 | return 0; | ||
733 | } | 570 | } |
734 | 571 | ||
735 | #define SWITCH_V4L2 if (!t->using_v4l2 && debug) \ | 572 | static void tda9887_standby(struct i2c_client *client) |
736 | tda9887_info("switching to v4l2\n"); \ | ||
737 | t->using_v4l2 = 1; | ||
738 | #define CHECK_V4L2 if (t->using_v4l2) { if (debug) \ | ||
739 | tda9887_info("ignore v4l1 call\n"); \ | ||
740 | return 0; } | ||
741 | |||
742 | static int | ||
743 | tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) | ||
744 | { | 573 | { |
745 | struct tda9887 *t = i2c_get_clientdata(client); | 574 | tda9887_configure(client); |
746 | |||
747 | switch (cmd) { | ||
748 | |||
749 | /* --- configuration --- */ | ||
750 | case AUDC_SET_RADIO: | ||
751 | { | ||
752 | t->mode = T_RADIO; | ||
753 | tda9887_configure(t); | ||
754 | break; | ||
755 | } | ||
756 | case TUNER_SET_STANDBY: | ||
757 | { | ||
758 | t->mode = T_STANDBY; | ||
759 | tda9887_configure(t); | ||
760 | break; | ||
761 | } | ||
762 | case TDA9887_SET_CONFIG: | ||
763 | { | ||
764 | int *i = arg; | ||
765 | |||
766 | t->config = *i; | ||
767 | tda9887_configure(t); | ||
768 | break; | ||
769 | } | ||
770 | /* --- v4l ioctls --- */ | ||
771 | /* take care: bttv does userspace copying, we'll get a | ||
772 | kernel pointer here... */ | ||
773 | case VIDIOCSCHAN: | ||
774 | { | ||
775 | static const v4l2_std_id map[] = { | ||
776 | [ VIDEO_MODE_PAL ] = V4L2_STD_PAL, | ||
777 | [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M, | ||
778 | [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM, | ||
779 | [ 4 /* bttv */ ] = V4L2_STD_PAL_M, | ||
780 | [ 5 /* bttv */ ] = V4L2_STD_PAL_N, | ||
781 | [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, | ||
782 | }; | ||
783 | struct video_channel *vc = arg; | ||
784 | |||
785 | CHECK_V4L2; | ||
786 | t->mode = T_ANALOG_TV; | ||
787 | if (vc->norm < ARRAY_SIZE(map)) | ||
788 | t->std = map[vc->norm]; | ||
789 | tda9887_fixup_std(t); | ||
790 | tda9887_configure(t); | ||
791 | break; | ||
792 | } | ||
793 | case VIDIOC_S_STD: | ||
794 | { | ||
795 | v4l2_std_id *id = arg; | ||
796 | |||
797 | SWITCH_V4L2; | ||
798 | t->mode = T_ANALOG_TV; | ||
799 | t->std = *id; | ||
800 | tda9887_fixup_std(t); | ||
801 | tda9887_configure(t); | ||
802 | break; | ||
803 | } | ||
804 | case VIDIOC_S_FREQUENCY: | ||
805 | { | ||
806 | struct v4l2_frequency *f = arg; | ||
807 | |||
808 | SWITCH_V4L2; | ||
809 | if (V4L2_TUNER_ANALOG_TV == f->type) { | ||
810 | if (t->mode == T_ANALOG_TV) | ||
811 | return 0; | ||
812 | t->mode = T_ANALOG_TV; | ||
813 | } | ||
814 | if (V4L2_TUNER_RADIO == f->type) { | ||
815 | if (t->mode == T_RADIO) | ||
816 | return 0; | ||
817 | t->mode = T_RADIO; | ||
818 | } | ||
819 | tda9887_configure(t); | ||
820 | break; | ||
821 | } | ||
822 | case VIDIOC_G_TUNER: | ||
823 | { | ||
824 | static int AFC_BITS_2_kHz[] = { | ||
825 | -12500, -37500, -62500, -97500, | ||
826 | -112500, -137500, -162500, -187500, | ||
827 | 187500, 162500, 137500, 112500, | ||
828 | 97500 , 62500, 37500 , 12500 | ||
829 | }; | ||
830 | struct v4l2_tuner* tuner = arg; | ||
831 | |||
832 | if (t->mode == T_RADIO) { | ||
833 | __u8 reg = 0; | ||
834 | tuner->afc=0; | ||
835 | if (1 == i2c_master_recv(&t->client,®,1)) | ||
836 | tuner->afc = AFC_BITS_2_kHz[(reg>>1)&0x0f]; | ||
837 | } | ||
838 | break; | ||
839 | } | ||
840 | case VIDIOC_S_TUNER: | ||
841 | { | ||
842 | struct v4l2_tuner* tuner = arg; | ||
843 | |||
844 | if (t->mode == T_RADIO) { | ||
845 | t->radio_mode = tuner->audmode; | ||
846 | tda9887_configure (t); | ||
847 | } | ||
848 | break; | ||
849 | } | ||
850 | case VIDIOC_LOG_STATUS: | ||
851 | { | ||
852 | tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->data[1], t->data[2], t->data[3]); | ||
853 | break; | ||
854 | } | ||
855 | default: | ||
856 | /* nothing */ | ||
857 | break; | ||
858 | } | ||
859 | return 0; | ||
860 | } | 575 | } |
861 | 576 | ||
862 | static int tda9887_suspend(struct device * dev, pm_message_t state) | 577 | static void tda9887_set_freq(struct i2c_client *client, unsigned int freq) |
863 | { | 578 | { |
864 | struct i2c_client *c = container_of(dev, struct i2c_client, dev); | 579 | tda9887_configure(client); |
865 | struct tda9887 *t = i2c_get_clientdata(c); | ||
866 | |||
867 | tda9887_dbg("suspend\n"); | ||
868 | return 0; | ||
869 | } | 580 | } |
870 | 581 | ||
871 | static int tda9887_resume(struct device * dev) | 582 | int tda9887_tuner_init(struct i2c_client *c) |
872 | { | 583 | { |
873 | struct i2c_client *c = container_of(dev, struct i2c_client, dev); | 584 | struct tuner *t = i2c_get_clientdata(c); |
874 | struct tda9887 *t = i2c_get_clientdata(c); | ||
875 | 585 | ||
876 | tda9887_dbg("resume\n"); | 586 | strlcpy(c->name, "tda9887", sizeof(c->name)); |
877 | tda9887_configure(t); | ||
878 | return 0; | ||
879 | } | ||
880 | 587 | ||
881 | /* ----------------------------------------------------------------------- */ | 588 | tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr, |
882 | 589 | t->i2c.driver->driver.name); | |
883 | static struct i2c_driver driver = { | ||
884 | .id = I2C_DRIVERID_TDA9887, | ||
885 | .attach_adapter = tda9887_probe, | ||
886 | .detach_client = tda9887_detach, | ||
887 | .command = tda9887_command, | ||
888 | .driver = { | ||
889 | .name = "tda9887", | ||
890 | .suspend = tda9887_suspend, | ||
891 | .resume = tda9887_resume, | ||
892 | }, | ||
893 | }; | ||
894 | static struct i2c_client client_template = | ||
895 | { | ||
896 | .name = "tda9887", | ||
897 | .driver = &driver, | ||
898 | }; | ||
899 | 590 | ||
900 | static int __init tda9887_init_module(void) | 591 | t->set_tv_freq = tda9887_set_freq; |
901 | { | 592 | t->set_radio_freq = tda9887_set_freq; |
902 | return i2c_add_driver(&driver); | 593 | t->standby = tda9887_standby; |
903 | } | 594 | t->tuner_status=tda9887_tuner_status; |
595 | t->get_afc=tda9887_get_afc; | ||
904 | 596 | ||
905 | static void __exit tda9887_cleanup_module(void) | 597 | return 0; |
906 | { | ||
907 | i2c_del_driver(&driver); | ||
908 | } | 598 | } |
909 | 599 | ||
910 | module_init(tda9887_init_module); | ||
911 | module_exit(tda9887_cleanup_module); | ||
912 | |||
913 | /* | 600 | /* |
914 | * Overrides for Emacs so that we follow Linus's tabbing style. | 601 | * Overrides for Emacs so that we follow Linus's tabbing style. |
915 | * --------------------------------------------------------------------------- | 602 | * --------------------------------------------------------------------------- |
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index c2b98f81c192..d1c41781ccc4 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * I2C address is allways 0xC0. | 3 | * I2C address is allways 0xC0. |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br) | 6 | * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@infradead.org) |
7 | * This code is placed under the terms of the GNU General Public License | 7 | * This code is placed under the terms of the GNU General Public License |
8 | * | 8 | * |
9 | * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa | 9 | * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa |
diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c new file mode 100644 index 000000000000..76b2e96429d9 --- /dev/null +++ b/drivers/media/video/tlv320aic23b.c | |||
@@ -0,0 +1,217 @@ | |||
1 | /* | ||
2 | * tlv320aic23b - driver version 0.0.1 | ||
3 | * | ||
4 | * Copyright (C) 2006 Scott Alfter <salfter@ssai.us> | ||
5 | * | ||
6 | * Based on wm8775 driver | ||
7 | * | ||
8 | * Copyright (C) 2004 Ulf Eklund <ivtv at eklund.to> | ||
9 | * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> | ||
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/module.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/ioctl.h> | ||
29 | #include <asm/uaccess.h> | ||
30 | #include <linux/i2c.h> | ||
31 | #include <linux/i2c-id.h> | ||
32 | #include <linux/videodev.h> | ||
33 | #include <media/v4l2-common.h> | ||
34 | |||
35 | MODULE_DESCRIPTION("tlv320aic23b driver"); | ||
36 | MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil"); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END }; | ||
40 | |||
41 | |||
42 | I2C_CLIENT_INSMOD; | ||
43 | |||
44 | /* ----------------------------------------------------------------------- */ | ||
45 | |||
46 | struct tlv320aic23b_state { | ||
47 | u8 muted; | ||
48 | }; | ||
49 | |||
50 | static int tlv320aic23b_write(struct i2c_client *client, int reg, u16 val) | ||
51 | { | ||
52 | int i; | ||
53 | |||
54 | if ((reg < 0 || reg > 9) && (reg != 15)) { | ||
55 | v4l_err(client, "Invalid register R%d\n", reg); | ||
56 | return -1; | ||
57 | } | ||
58 | |||
59 | for (i = 0; i < 3; i++) { | ||
60 | if (i2c_smbus_write_byte_data(client, (reg << 1) | | ||
61 | (val >> 8), val & 0xff) == 0) { | ||
62 | return 0; | ||
63 | } | ||
64 | } | ||
65 | v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg); | ||
66 | return -1; | ||
67 | } | ||
68 | |||
69 | static int tlv320aic23b_command(struct i2c_client *client, unsigned int cmd, | ||
70 | void *arg) | ||
71 | { | ||
72 | struct tlv320aic23b_state *state = i2c_get_clientdata(client); | ||
73 | struct v4l2_control *ctrl = arg; | ||
74 | u32* freq = arg; | ||
75 | |||
76 | switch (cmd) { | ||
77 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | ||
78 | switch (*freq) { | ||
79 | case 32000: /* set sample rate to 32 kHz */ | ||
80 | tlv320aic23b_write(client, 8, 0x018); | ||
81 | break; | ||
82 | case 44100: /* set sample rate to 44.1 kHz */ | ||
83 | tlv320aic23b_write(client, 8, 0x022); | ||
84 | break; | ||
85 | case 48000: /* set sample rate to 48 kHz */ | ||
86 | tlv320aic23b_write(client, 8, 0x000); | ||
87 | break; | ||
88 | default: | ||
89 | return -EINVAL; | ||
90 | } | ||
91 | break; | ||
92 | |||
93 | case VIDIOC_G_CTRL: | ||
94 | if (ctrl->id != V4L2_CID_AUDIO_MUTE) | ||
95 | return -EINVAL; | ||
96 | ctrl->value = state->muted; | ||
97 | break; | ||
98 | |||
99 | case VIDIOC_S_CTRL: | ||
100 | if (ctrl->id != V4L2_CID_AUDIO_MUTE) | ||
101 | return -EINVAL; | ||
102 | state->muted = ctrl->value; | ||
103 | tlv320aic23b_write(client, 0, 0x180); /* mute both channels */ | ||
104 | /* set gain on both channels to +3.0 dB */ | ||
105 | if (!state->muted) | ||
106 | tlv320aic23b_write(client, 0, 0x119); | ||
107 | break; | ||
108 | |||
109 | case VIDIOC_LOG_STATUS: | ||
110 | v4l_info(client, "Input: %s\n", | ||
111 | state->muted ? "muted" : "active"); | ||
112 | break; | ||
113 | |||
114 | default: | ||
115 | return -EINVAL; | ||
116 | } | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | /* ----------------------------------------------------------------------- */ | ||
121 | |||
122 | /* i2c implementation */ | ||
123 | |||
124 | /* | ||
125 | * Generic i2c probe | ||
126 | * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' | ||
127 | */ | ||
128 | |||
129 | static struct i2c_driver i2c_driver; | ||
130 | |||
131 | static int tlv320aic23b_attach(struct i2c_adapter *adapter, int address, int kind) | ||
132 | { | ||
133 | struct i2c_client *client; | ||
134 | struct tlv320aic23b_state *state; | ||
135 | |||
136 | /* Check if the adapter supports the needed features */ | ||
137 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
138 | return 0; | ||
139 | |||
140 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
141 | if (client == 0) | ||
142 | return -ENOMEM; | ||
143 | |||
144 | client->addr = address; | ||
145 | client->adapter = adapter; | ||
146 | client->driver = &i2c_driver; | ||
147 | snprintf(client->name, sizeof(client->name) - 1, "tlv320aic23b"); | ||
148 | |||
149 | v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); | ||
150 | |||
151 | state = kmalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL); | ||
152 | if (state == NULL) { | ||
153 | kfree(client); | ||
154 | return -ENOMEM; | ||
155 | } | ||
156 | state->muted = 0; | ||
157 | i2c_set_clientdata(client, state); | ||
158 | |||
159 | /* initialize tlv320aic23b */ | ||
160 | tlv320aic23b_write(client, 15, 0x000); /* RESET */ | ||
161 | tlv320aic23b_write(client, 6, 0x00A); /* turn off DAC & mic input */ | ||
162 | tlv320aic23b_write(client, 7, 0x049); /* left-justified, 24-bit, master mode */ | ||
163 | tlv320aic23b_write(client, 0, 0x119); /* set gain on both channels to +3.0 dB */ | ||
164 | tlv320aic23b_write(client, 8, 0x000); /* set sample rate to 48 kHz */ | ||
165 | tlv320aic23b_write(client, 9, 0x001); /* activate digital interface */ | ||
166 | |||
167 | i2c_attach_client(client); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int tlv320aic23b_probe(struct i2c_adapter *adapter) | ||
173 | { | ||
174 | if (adapter->class & I2C_CLASS_TV_ANALOG) | ||
175 | return i2c_probe(adapter, &addr_data, tlv320aic23b_attach); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int tlv320aic23b_detach(struct i2c_client *client) | ||
180 | { | ||
181 | int err; | ||
182 | |||
183 | err = i2c_detach_client(client); | ||
184 | if (err) { | ||
185 | return err; | ||
186 | } | ||
187 | kfree(client); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | /* ----------------------------------------------------------------------- */ | ||
193 | |||
194 | /* i2c implementation */ | ||
195 | static struct i2c_driver i2c_driver = { | ||
196 | .driver = { | ||
197 | .name = "tlv320aic23b", | ||
198 | }, | ||
199 | .id = I2C_DRIVERID_TLV320AIC23B, | ||
200 | .attach_adapter = tlv320aic23b_probe, | ||
201 | .detach_client = tlv320aic23b_detach, | ||
202 | .command = tlv320aic23b_command, | ||
203 | }; | ||
204 | |||
205 | |||
206 | static int __init tlv320aic23b_init_module(void) | ||
207 | { | ||
208 | return i2c_add_driver(&i2c_driver); | ||
209 | } | ||
210 | |||
211 | static void __exit tlv320aic23b_cleanup_module(void) | ||
212 | { | ||
213 | i2c_del_driver(&i2c_driver); | ||
214 | } | ||
215 | |||
216 | module_init(tlv320aic23b_init_module); | ||
217 | module_exit(tlv320aic23b_cleanup_module); | ||
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c index 74ab48c09c6a..bdf506e6ae27 100644 --- a/drivers/media/video/tuner-3036.c +++ b/drivers/media/video/tuner-3036.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
27 | #include <linux/videodev.h> | 27 | #include <linux/videodev.h> |
28 | #include <media/v4l2-common.h> | ||
28 | 29 | ||
29 | #include <media/tuner.h> | 30 | #include <media/tuner.h> |
30 | 31 | ||
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 1013b4de89a2..e95792fd70f8 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -199,7 +199,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
199 | i2c_master_send(c, buffer, 4); | 199 | i2c_master_send(c, buffer, 4); |
200 | default_tuner_init(c); | 200 | default_tuner_init(c); |
201 | break; | 201 | break; |
202 | case TUNER_LG_TDVS_H062F: | 202 | case TUNER_LG_TDVS_H06XF: |
203 | /* Set the Auxiliary Byte. */ | 203 | /* Set the Auxiliary Byte. */ |
204 | buffer[2] &= ~0x20; | 204 | buffer[2] &= ~0x20; |
205 | buffer[2] |= 0x18; | 205 | buffer[2] |= 0x18; |
@@ -215,6 +215,9 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
215 | i2c_master_send(c,buffer,4); | 215 | i2c_master_send(c,buffer,4); |
216 | default_tuner_init(c); | 216 | default_tuner_init(c); |
217 | break; | 217 | break; |
218 | case TUNER_TDA9887: | ||
219 | tda9887_tuner_init(c); | ||
220 | break; | ||
218 | default: | 221 | default: |
219 | default_tuner_init(c); | 222 | default_tuner_init(c); |
220 | break; | 223 | break; |
@@ -241,6 +244,8 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup) | |||
241 | { | 244 | { |
242 | struct tuner *t = i2c_get_clientdata(c); | 245 | struct tuner *t = i2c_get_clientdata(c); |
243 | 246 | ||
247 | tuner_dbg("set addr for type %i\n", t->type); | ||
248 | |||
244 | if ( t->type == UNSET && ((tun_setup->addr == ADDR_UNSET && | 249 | if ( t->type == UNSET && ((tun_setup->addr == ADDR_UNSET && |
245 | (t->mode_mask & tun_setup->mode_mask)) || | 250 | (t->mode_mask & tun_setup->mode_mask)) || |
246 | tun_setup->addr == c->addr)) { | 251 | tun_setup->addr == c->addr)) { |
@@ -436,6 +441,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
436 | t->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ | 441 | t->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ |
437 | t->audmode = V4L2_TUNER_MODE_STEREO; | 442 | t->audmode = V4L2_TUNER_MODE_STEREO; |
438 | t->mode_mask = T_UNINITIALIZED; | 443 | t->mode_mask = T_UNINITIALIZED; |
444 | t->tuner_status = tuner_status; | ||
439 | if (tuner_debug_old) { | 445 | if (tuner_debug_old) { |
440 | tuner_debug = tuner_debug_old; | 446 | tuner_debug = tuner_debug_old; |
441 | printk(KERN_ERR "tuner: tuner_debug is deprecated and will be removed in 2.6.17.\n"); | 447 | printk(KERN_ERR "tuner: tuner_debug is deprecated and will be removed in 2.6.17.\n"); |
@@ -462,10 +468,14 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
462 | case 0x4b: | 468 | case 0x4b: |
463 | /* If chip is not tda8290, don't register. | 469 | /* If chip is not tda8290, don't register. |
464 | since it can be tda9887*/ | 470 | since it can be tda9887*/ |
465 | if (tda8290_probe(&t->i2c) != 0) { | 471 | if (tda8290_probe(&t->i2c) == 0) { |
466 | tuner_dbg("chip at addr %x is not a tda8290\n", addr); | 472 | tuner_dbg("chip at addr %x is a tda8290\n", addr); |
467 | kfree(t); | 473 | } else { |
468 | return 0; | 474 | /* Default is being tda9887 */ |
475 | t->type = TUNER_TDA9887; | ||
476 | t->mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; | ||
477 | t->mode = T_STANDBY; | ||
478 | goto register_client; | ||
469 | } | 479 | } |
470 | break; | 480 | break; |
471 | case 0x60: | 481 | case 0x60: |
@@ -592,6 +602,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
592 | case TUNER_SET_STANDBY: | 602 | case TUNER_SET_STANDBY: |
593 | if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) | 603 | if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) |
594 | return 0; | 604 | return 0; |
605 | t->mode = T_STANDBY; | ||
595 | if (t->standby) | 606 | if (t->standby) |
596 | t->standby (client); | 607 | t->standby (client); |
597 | break; | 608 | break; |
@@ -604,6 +615,14 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
604 | /* Should be implemented, since bttv calls it */ | 615 | /* Should be implemented, since bttv calls it */ |
605 | tuner_dbg("VIDIOCSAUDIO not implemented.\n"); | 616 | tuner_dbg("VIDIOCSAUDIO not implemented.\n"); |
606 | break; | 617 | break; |
618 | case TDA9887_SET_CONFIG: | ||
619 | { | ||
620 | int *i = arg; | ||
621 | |||
622 | t->tda9887_config = *i; | ||
623 | set_freq(client, t->tv_freq); | ||
624 | break; | ||
625 | } | ||
607 | /* --- v4l ioctls --- */ | 626 | /* --- v4l ioctls --- */ |
608 | /* take care: bttv does userspace copying, we'll get a | 627 | /* take care: bttv does userspace copying, we'll get a |
609 | kernel pointer here... */ | 628 | kernel pointer here... */ |
@@ -744,6 +763,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
744 | switch_v4l2(); | 763 | switch_v4l2(); |
745 | 764 | ||
746 | tuner->type = t->mode; | 765 | tuner->type = t->mode; |
766 | if (t->get_afc) | ||
767 | tuner->afc=t->get_afc(client); | ||
747 | if (t->mode == V4L2_TUNER_ANALOG_TV) | 768 | if (t->mode == V4L2_TUNER_ANALOG_TV) |
748 | tuner->capability |= V4L2_TUNER_CAP_NORM; | 769 | tuner->capability |= V4L2_TUNER_CAP_NORM; |
749 | if (t->mode != V4L2_TUNER_RADIO) { | 770 | if (t->mode != V4L2_TUNER_RADIO) { |
@@ -787,7 +808,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
787 | break; | 808 | break; |
788 | } | 809 | } |
789 | case VIDIOC_LOG_STATUS: | 810 | case VIDIOC_LOG_STATUS: |
790 | tuner_status(client); | 811 | if (t->tuner_status) |
812 | t->tuner_status(client); | ||
791 | break; | 813 | break; |
792 | } | 814 | } |
793 | 815 | ||
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 5d7abed71674..6da6f82b8c88 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c | |||
@@ -105,7 +105,7 @@ static int tuner_stereo(struct i2c_client *c) | |||
105 | 105 | ||
106 | switch (t->type) { | 106 | switch (t->type) { |
107 | case TUNER_PHILIPS_FM1216ME_MK3: | 107 | case TUNER_PHILIPS_FM1216ME_MK3: |
108 | case TUNER_PHILIPS_FM1236_MK3: | 108 | case TUNER_PHILIPS_FM1236_MK3: |
109 | case TUNER_PHILIPS_FM1256_IH3: | 109 | case TUNER_PHILIPS_FM1256_IH3: |
110 | stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); | 110 | stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); |
111 | break; | 111 | break; |
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index a1ae036b44ec..9d9226cb6393 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c | |||
@@ -874,7 +874,7 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = { | |||
874 | }; | 874 | }; |
875 | 875 | ||
876 | 876 | ||
877 | /* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */ | 877 | /* ------ TUNER_LG_TDVS_H06XF - LG INNOTEK / INFINEON ATSC ----- */ |
878 | 878 | ||
879 | static struct tuner_range tuner_tua6034_ntsc_ranges[] = { | 879 | static struct tuner_range tuner_tua6034_ntsc_ranges[] = { |
880 | { 16 * 165.00 /*MHz*/, 0x8e, 0x01 }, | 880 | { 16 * 165.00 /*MHz*/, 0x8e, 0x01 }, |
@@ -883,7 +883,7 @@ static struct tuner_range tuner_tua6034_ntsc_ranges[] = { | |||
883 | }; | 883 | }; |
884 | 884 | ||
885 | 885 | ||
886 | static struct tuner_params tuner_tua6034_params[] = { | 886 | static struct tuner_params tuner_lg_tdvs_h06xf_params[] = { |
887 | { | 887 | { |
888 | .type = TUNER_PARAM_TYPE_NTSC, | 888 | .type = TUNER_PARAM_TYPE_NTSC, |
889 | .ranges = tuner_tua6034_ntsc_ranges, | 889 | .ranges = tuner_tua6034_ntsc_ranges, |
@@ -1024,6 +1024,22 @@ static struct tuner_params tuner_thomson_fe6600_params[] = { | |||
1024 | }, | 1024 | }, |
1025 | }; | 1025 | }; |
1026 | 1026 | ||
1027 | /* ------------ TUNER_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */ | ||
1028 | |||
1029 | static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = { | ||
1030 | { 16 * 146.25 /*MHz*/, 0xce, 0x01, }, | ||
1031 | { 16 * 428.50 /*MHz*/, 0xce, 0x02, }, | ||
1032 | { 16 * 999.99 , 0xce, 0x08, }, | ||
1033 | }; | ||
1034 | |||
1035 | static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = { | ||
1036 | { | ||
1037 | .type = TUNER_PARAM_TYPE_PAL, | ||
1038 | .ranges = tuner_samsung_tcpg_6121p30a_pal_ranges, | ||
1039 | .count = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_pal_ranges), | ||
1040 | }, | ||
1041 | }; | ||
1042 | |||
1027 | /* --------------------------------------------------------------------- */ | 1043 | /* --------------------------------------------------------------------- */ |
1028 | 1044 | ||
1029 | struct tunertype tuners[] = { | 1045 | struct tunertype tuners[] = { |
@@ -1354,10 +1370,10 @@ struct tunertype tuners[] = { | |||
1354 | .params = tuner_philips_fmd1216me_mk3_params, | 1370 | .params = tuner_philips_fmd1216me_mk3_params, |
1355 | .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params), | 1371 | .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params), |
1356 | }, | 1372 | }, |
1357 | [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */ | 1373 | [TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */ |
1358 | .name = "LG TDVS-H062F/TUA6034", | 1374 | .name = "LG TDVS-H06xF", /* H061F, H062F & H064F */ |
1359 | .params = tuner_tua6034_params, | 1375 | .params = tuner_lg_tdvs_h06xf_params, |
1360 | .count = ARRAY_SIZE(tuner_tua6034_params), | 1376 | .count = ARRAY_SIZE(tuner_lg_tdvs_h06xf_params), |
1361 | }, | 1377 | }, |
1362 | [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ | 1378 | [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ |
1363 | .name = "Ymec TVF66T5-B/DFF", | 1379 | .name = "Ymec TVF66T5-B/DFF", |
@@ -1400,6 +1416,16 @@ struct tunertype tuners[] = { | |||
1400 | .params = tuner_thomson_fe6600_params, | 1416 | .params = tuner_thomson_fe6600_params, |
1401 | .count = ARRAY_SIZE(tuner_thomson_fe6600_params), | 1417 | .count = ARRAY_SIZE(tuner_thomson_fe6600_params), |
1402 | }, | 1418 | }, |
1419 | [TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */ | ||
1420 | .name = "Samsung TCPG 6121P30A", | ||
1421 | .params = tuner_samsung_tcpg_6121p30a_params, | ||
1422 | .count = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_params), | ||
1423 | }, | ||
1424 | [TUNER_TDA9887] = { /* Philips TDA 9887 IF PLL Demodulator. | ||
1425 | This chip is part of some modern tuners */ | ||
1426 | .name = "Philips TDA988[5,6,7] IF PLL Demodulator", | ||
1427 | /* see tda9887.c for details */ | ||
1428 | }, | ||
1403 | }; | 1429 | }; |
1404 | 1430 | ||
1405 | unsigned const int tuner_count = ARRAY_SIZE(tuners); | 1431 | unsigned const int tuner_count = ARRAY_SIZE(tuners); |
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index b463e996961a..30f8d80ddcaa 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
@@ -200,7 +200,7 @@ hauppauge_tuner[] = | |||
200 | { TUNER_ABSENT, "Philips FQ1286A MK4"}, | 200 | { TUNER_ABSENT, "Philips FQ1286A MK4"}, |
201 | { TUNER_ABSENT, "Philips FQ1216ME MK5"}, | 201 | { TUNER_ABSENT, "Philips FQ1216ME MK5"}, |
202 | { TUNER_ABSENT, "Philips FQ1236 MK5"}, | 202 | { TUNER_ABSENT, "Philips FQ1236 MK5"}, |
203 | { TUNER_ABSENT, "Samsung TCPG_6121P30A"}, | 203 | { TUNER_SAMSUNG_TCPG_6121P30A, "Samsung TCPG 6121P30A"}, |
204 | { TUNER_TCL_2002MB, "TCL 2002MB_3H"}, | 204 | { TUNER_TCL_2002MB, "TCL 2002MB_3H"}, |
205 | { TUNER_ABSENT, "TCL 2002MI_3H"}, | 205 | { TUNER_ABSENT, "TCL 2002MI_3H"}, |
206 | { TUNER_TCL_2002N, "TCL 2002N 5H"}, | 206 | { TUNER_TCL_2002N, "TCL 2002N 5H"}, |
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c index 9e86caeb96a7..1654576de10e 100644 --- a/drivers/media/video/tvmixer.c +++ b/drivers/media/video/tvmixer.c | |||
@@ -198,10 +198,6 @@ static int tvmixer_open(struct inode *inode, struct file *file) | |||
198 | 198 | ||
199 | /* lock bttv in memory while the mixer is in use */ | 199 | /* lock bttv in memory while the mixer is in use */ |
200 | file->private_data = mix; | 200 | file->private_data = mix; |
201 | #ifndef I2C_PEC | ||
202 | if (client->adapter->inc_use) | ||
203 | client->adapter->inc_use(client->adapter); | ||
204 | #endif | ||
205 | if (client->adapter->owner) | 201 | if (client->adapter->owner) |
206 | try_module_get(client->adapter->owner); | 202 | try_module_get(client->adapter->owner); |
207 | return 0; | 203 | return 0; |
@@ -217,10 +213,6 @@ static int tvmixer_release(struct inode *inode, struct file *file) | |||
217 | return -ENODEV; | 213 | return -ENODEV; |
218 | } | 214 | } |
219 | 215 | ||
220 | #ifndef I2C_PEC | ||
221 | if (client->adapter->dec_use) | ||
222 | client->adapter->dec_use(client->adapter); | ||
223 | #endif | ||
224 | if (client->adapter->owner) | 216 | if (client->adapter->owner) |
225 | module_put(client->adapter->owner); | 217 | module_put(client->adapter->owner); |
226 | return 0; | 218 | return 0; |
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index dab4973bcf82..b167ffab2520 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
11 | #include <linux/video_decoder.h> | 11 | #include <linux/video_decoder.h> |
12 | #include <media/v4l2-common.h> | 12 | #include <media/v4l2-common.h> |
13 | #include <media/tvp5150.h> | ||
13 | 14 | ||
14 | #include "tvp5150_reg.h" | 15 | #include "tvp5150_reg.h" |
15 | 16 | ||
@@ -89,7 +90,7 @@ struct tvp5150 { | |||
89 | struct i2c_client *client; | 90 | struct i2c_client *client; |
90 | 91 | ||
91 | v4l2_std_id norm; /* Current set standard */ | 92 | v4l2_std_id norm; /* Current set standard */ |
92 | int input; | 93 | struct v4l2_routing route; |
93 | int enable; | 94 | int enable; |
94 | int bright; | 95 | int bright; |
95 | int contrast; | 96 | int contrast; |
@@ -283,29 +284,26 @@ static void dump_reg(struct i2c_client *c) | |||
283 | /**************************************************************************** | 284 | /**************************************************************************** |
284 | Basic functions | 285 | Basic functions |
285 | ****************************************************************************/ | 286 | ****************************************************************************/ |
286 | enum tvp5150_input { | ||
287 | TVP5150_ANALOG_CH0 = 0, | ||
288 | TVP5150_SVIDEO = 1, | ||
289 | TVP5150_ANALOG_CH1 = 2, | ||
290 | TVP5150_BLACK_SCREEN = 8 | ||
291 | }; | ||
292 | 287 | ||
293 | static inline void tvp5150_selmux(struct i2c_client *c, | 288 | static inline void tvp5150_selmux(struct i2c_client *c) |
294 | enum tvp5150_input input) | ||
295 | { | 289 | { |
296 | int opmode=0; | 290 | int opmode=0; |
297 | |||
298 | struct tvp5150 *decoder = i2c_get_clientdata(c); | 291 | struct tvp5150 *decoder = i2c_get_clientdata(c); |
292 | int input = 0; | ||
299 | 293 | ||
300 | if (!decoder->enable) | 294 | if ((decoder->route.output & TVP5150_BLACK_SCREEN) || !decoder->enable) |
301 | input |= TVP5150_BLACK_SCREEN; | 295 | input = 8; |
302 | 296 | ||
303 | switch (input) { | 297 | switch (input) { |
304 | case TVP5150_ANALOG_CH0: | 298 | case TVP5150_COMPOSITE1: |
305 | case TVP5150_ANALOG_CH1: | 299 | input |= 2; |
300 | /* fall through */ | ||
301 | case TVP5150_COMPOSITE0: | ||
306 | opmode=0x30; /* TV Mode */ | 302 | opmode=0x30; /* TV Mode */ |
307 | break; | 303 | break; |
304 | case TVP5150_SVIDEO: | ||
308 | default: | 305 | default: |
306 | input |= 1; | ||
309 | opmode=0; /* Auto Mode */ | 307 | opmode=0; /* Auto Mode */ |
310 | break; | 308 | break; |
311 | } | 309 | } |
@@ -790,7 +788,7 @@ static inline void tvp5150_reset(struct i2c_client *c) | |||
790 | tvp5150_vdp_init(c, vbi_ram_default); | 788 | tvp5150_vdp_init(c, vbi_ram_default); |
791 | 789 | ||
792 | /* Selects decoder input */ | 790 | /* Selects decoder input */ |
793 | tvp5150_selmux(c, decoder->input); | 791 | tvp5150_selmux(c); |
794 | 792 | ||
795 | /* Initializes TVP5150 to stream enabled values */ | 793 | /* Initializes TVP5150 to stream enabled values */ |
796 | tvp5150_write_inittab(c, tvp5150_init_enable); | 794 | tvp5150_write_inittab(c, tvp5150_init_enable); |
@@ -860,6 +858,21 @@ static int tvp5150_command(struct i2c_client *c, | |||
860 | case VIDIOC_INT_RESET: | 858 | case VIDIOC_INT_RESET: |
861 | tvp5150_reset(c); | 859 | tvp5150_reset(c); |
862 | break; | 860 | break; |
861 | case VIDIOC_INT_G_VIDEO_ROUTING: | ||
862 | { | ||
863 | struct v4l2_routing *route = arg; | ||
864 | |||
865 | *route = decoder->route; | ||
866 | break; | ||
867 | } | ||
868 | case VIDIOC_INT_S_VIDEO_ROUTING: | ||
869 | { | ||
870 | struct v4l2_routing *route = arg; | ||
871 | |||
872 | decoder->route = *route; | ||
873 | tvp5150_selmux(c); | ||
874 | break; | ||
875 | } | ||
863 | case VIDIOC_S_STD: | 876 | case VIDIOC_S_STD: |
864 | if (decoder->norm == *(v4l2_std_id *)arg) | 877 | if (decoder->norm == *(v4l2_std_id *)arg) |
865 | break; | 878 | break; |
@@ -1063,7 +1076,7 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter, | |||
1063 | rv = i2c_attach_client(c); | 1076 | rv = i2c_attach_client(c); |
1064 | 1077 | ||
1065 | core->norm = V4L2_STD_ALL; /* Default is autodetect */ | 1078 | core->norm = V4L2_STD_ALL; /* Default is autodetect */ |
1066 | core->input = 2; | 1079 | core->route.input = TVP5150_COMPOSITE1; |
1067 | core->enable = 1; | 1080 | core->enable = 1; |
1068 | core->bright = 32768; | 1081 | core->bright = 32768; |
1069 | core->contrast = 32768; | 1082 | core->contrast = 32768; |
diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig index 39269a2c5635..59fb899f31f3 100644 --- a/drivers/media/video/usbvideo/Kconfig +++ b/drivers/media/video/usbvideo/Kconfig | |||
@@ -36,3 +36,15 @@ config USB_KONICAWC | |||
36 | 36 | ||
37 | To compile this driver as a module, choose M here: the | 37 | To compile this driver as a module, choose M here: the |
38 | module will be called konicawc. | 38 | module will be called konicawc. |
39 | |||
40 | config USB_QUICKCAM_MESSENGER | ||
41 | tristate "USB Logitech Quickcam Messenger" | ||
42 | depends on USB && VIDEO_DEV | ||
43 | select VIDEO_USBVIDEO | ||
44 | ---help--- | ||
45 | Say Y or M here to enable support for the USB Logitech Quickcam | ||
46 | Messenger webcam. | ||
47 | |||
48 | To compile this driver as a module, choose M here: the | ||
49 | module will be called quickcam_messenger. | ||
50 | |||
diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile index bb52eb8dc2f9..4a1b144bee4d 100644 --- a/drivers/media/video/usbvideo/Makefile +++ b/drivers/media/video/usbvideo/Makefile | |||
@@ -2,3 +2,4 @@ obj-$(CONFIG_VIDEO_USBVIDEO) += usbvideo.o | |||
2 | obj-$(CONFIG_USB_IBMCAM) += ibmcam.o ultracam.o | 2 | obj-$(CONFIG_USB_IBMCAM) += ibmcam.o ultracam.o |
3 | obj-$(CONFIG_USB_KONICAWC) += konicawc.o | 3 | obj-$(CONFIG_USB_KONICAWC) += konicawc.o |
4 | obj-$(CONFIG_USB_VICAM) += vicam.o | 4 | obj-$(CONFIG_USB_VICAM) += vicam.o |
5 | obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += quickcam_messenger.o | ||
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c new file mode 100644 index 000000000000..3f3182a24da1 --- /dev/null +++ b/drivers/media/video/usbvideo/quickcam_messenger.c | |||
@@ -0,0 +1,1120 @@ | |||
1 | /* | ||
2 | * Driver for Logitech Quickcam Messenger usb video camera | ||
3 | * Copyright (C) Jaya Kumar | ||
4 | * | ||
5 | * This work was sponsored by CIS(M) Sdn Bhd. | ||
6 | * History: | ||
7 | * 05/08/2006 - Jaya Kumar | ||
8 | * I wrote this based on the konicawc by Simon Evans. | ||
9 | * - | ||
10 | * Full credit for reverse engineering and creating an initial | ||
11 | * working linux driver for the VV6422 goes to the qce-ga project by | ||
12 | * Tuukka Toivonen, Jochen Hoenicke, Peter McConnell, | ||
13 | * Cristiano De Michele, Georg Acher, Jean-Frederic Clere as well as | ||
14 | * others. | ||
15 | * --- | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, write to the Free Software | ||
28 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/input.h> | ||
36 | #include <linux/usb_input.h> | ||
37 | |||
38 | #include "usbvideo.h" | ||
39 | #include "quickcam_messenger.h" | ||
40 | |||
41 | /* | ||
42 | * Version Information | ||
43 | */ | ||
44 | |||
45 | #ifdef CONFIG_USB_DEBUG | ||
46 | static int debug; | ||
47 | #define DEBUG(n, format, arg...) \ | ||
48 | if (n <= debug) { \ | ||
49 | printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \ | ||
50 | } | ||
51 | #else | ||
52 | #define DEBUG(n, arg...) | ||
53 | static const int debug = 0; | ||
54 | #endif | ||
55 | |||
56 | #define DRIVER_VERSION "v0.01" | ||
57 | #define DRIVER_DESC "Logitech Quickcam Messenger USB" | ||
58 | |||
59 | #define USB_LOGITECH_VENDOR_ID 0x046D | ||
60 | #define USB_QCM_PRODUCT_ID 0x08F0 | ||
61 | |||
62 | #define MAX_CAMERAS 1 | ||
63 | |||
64 | #define MAX_COLOUR 32768 | ||
65 | #define MAX_HUE 32768 | ||
66 | #define MAX_BRIGHTNESS 32768 | ||
67 | #define MAX_CONTRAST 32768 | ||
68 | #define MAX_WHITENESS 32768 | ||
69 | |||
70 | static int size = SIZE_320X240; | ||
71 | static int colour = MAX_COLOUR; | ||
72 | static int hue = MAX_HUE; | ||
73 | static int brightness = MAX_BRIGHTNESS; | ||
74 | static int contrast = MAX_CONTRAST; | ||
75 | static int whiteness = MAX_WHITENESS; | ||
76 | |||
77 | static struct usbvideo *cams; | ||
78 | |||
79 | static struct usb_device_id qcm_table [] = { | ||
80 | { USB_DEVICE(USB_LOGITECH_VENDOR_ID, USB_QCM_PRODUCT_ID) }, | ||
81 | { } | ||
82 | }; | ||
83 | MODULE_DEVICE_TABLE(usb, qcm_table); | ||
84 | |||
85 | #ifdef CONFIG_INPUT | ||
86 | static void qcm_register_input(struct qcm *cam, struct usb_device *dev) | ||
87 | { | ||
88 | struct input_dev *input_dev; | ||
89 | |||
90 | usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); | ||
91 | strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); | ||
92 | |||
93 | cam->input = input_dev = input_allocate_device(); | ||
94 | if (!input_dev) { | ||
95 | warn("insufficient mem for cam input device"); | ||
96 | return; | ||
97 | } | ||
98 | |||
99 | input_dev->name = "QCM button"; | ||
100 | input_dev->phys = cam->input_physname; | ||
101 | usb_to_input_id(dev, &input_dev->id); | ||
102 | input_dev->cdev.dev = &dev->dev; | ||
103 | |||
104 | input_dev->evbit[0] = BIT(EV_KEY); | ||
105 | input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); | ||
106 | |||
107 | input_dev->private = cam; | ||
108 | |||
109 | input_register_device(cam->input); | ||
110 | } | ||
111 | |||
112 | static void qcm_unregister_input(struct qcm *cam) | ||
113 | { | ||
114 | if (cam->input) { | ||
115 | input_unregister_device(cam->input); | ||
116 | cam->input = NULL; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | static void qcm_report_buttonstat(struct qcm *cam) | ||
121 | { | ||
122 | if (cam->input) { | ||
123 | input_report_key(cam->input, BTN_0, cam->button_sts); | ||
124 | input_sync(cam->input); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | static void qcm_int_irq(struct urb *urb, struct pt_regs *regs) | ||
129 | { | ||
130 | int ret; | ||
131 | struct uvd *uvd = urb->context; | ||
132 | struct qcm *cam; | ||
133 | |||
134 | if (!CAMERA_IS_OPERATIONAL(uvd)) | ||
135 | return; | ||
136 | |||
137 | if (!uvd->streaming) | ||
138 | return; | ||
139 | |||
140 | uvd->stats.urb_count++; | ||
141 | |||
142 | if (urb->status < 0) | ||
143 | uvd->stats.iso_err_count++; | ||
144 | else { | ||
145 | if (urb->actual_length > 0 ) { | ||
146 | cam = (struct qcm *) uvd->user_data; | ||
147 | if (cam->button_sts_buf == 0x88) | ||
148 | cam->button_sts = 0x0; | ||
149 | else if (cam->button_sts_buf == 0x80) | ||
150 | cam->button_sts = 0x1; | ||
151 | qcm_report_buttonstat(cam); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
156 | if (ret < 0) | ||
157 | err("usb_submit_urb error (%d)", ret); | ||
158 | } | ||
159 | |||
160 | static int qcm_setup_input_int(struct qcm *cam, struct uvd *uvd) | ||
161 | { | ||
162 | int errflag; | ||
163 | usb_fill_int_urb(cam->button_urb, uvd->dev, | ||
164 | usb_rcvintpipe(uvd->dev, uvd->video_endp + 1), | ||
165 | &cam->button_sts_buf, | ||
166 | 1, | ||
167 | qcm_int_irq, | ||
168 | uvd, 16); | ||
169 | |||
170 | errflag = usb_submit_urb(cam->button_urb, GFP_KERNEL); | ||
171 | if (errflag) | ||
172 | err ("usb_submit_int ret %d", errflag); | ||
173 | return errflag; | ||
174 | } | ||
175 | |||
176 | static void qcm_stop_int_data(struct qcm *cam) | ||
177 | { | ||
178 | usb_kill_urb(cam->button_urb); | ||
179 | } | ||
180 | |||
181 | static int qcm_alloc_int_urb(struct qcm *cam) | ||
182 | { | ||
183 | cam->button_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
184 | |||
185 | if (!cam->button_urb) | ||
186 | return -ENOMEM; | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static void qcm_free_int(struct qcm *cam) | ||
192 | { | ||
193 | if (cam->button_urb) | ||
194 | usb_free_urb(cam->button_urb); | ||
195 | } | ||
196 | #endif /* CONFIG_INPUT */ | ||
197 | |||
198 | static int qcm_stv_setb(struct usb_device *dev, u16 reg, u8 val) | ||
199 | { | ||
200 | int ret; | ||
201 | |||
202 | /* we'll wait up to 3 slices but no more */ | ||
203 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
204 | 0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, | ||
205 | reg, 0, &val, 1, 3*HZ); | ||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | static int qcm_stv_setw(struct usb_device *dev, u16 reg, u16 val) | ||
210 | { | ||
211 | int ret; | ||
212 | |||
213 | /* we'll wait up to 3 slices but no more */ | ||
214 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
215 | 0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, | ||
216 | reg, 0, &val, 2, 3*HZ); | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | static int qcm_stv_getw(struct usb_device *dev, unsigned short reg, | ||
221 | __le16 *val) | ||
222 | { | ||
223 | int ret; | ||
224 | |||
225 | /* we'll wait up to 3 slices but no more */ | ||
226 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
227 | 0x04, USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, | ||
228 | reg, 0, val, 2, 3*HZ); | ||
229 | return ret; | ||
230 | } | ||
231 | |||
232 | static int qcm_camera_on(struct uvd *uvd) | ||
233 | { | ||
234 | int ret; | ||
235 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x01)); | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int qcm_camera_off(struct uvd *uvd) | ||
240 | { | ||
241 | int ret; | ||
242 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00)); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static void qcm_hsv2rgb(u16 hue, u16 sat, u16 val, u16 *r, u16 *g, u16 *b) | ||
247 | { | ||
248 | unsigned int segment, valsat; | ||
249 | signed int h = (signed int) hue; | ||
250 | unsigned int s = (sat - 32768) * 2; /* rescale */ | ||
251 | unsigned int v = val; | ||
252 | unsigned int p; | ||
253 | |||
254 | /* | ||
255 | the registers controling gain are 8 bit of which | ||
256 | we affect only the last 4 bits with our gain. | ||
257 | we know that if saturation is 0, (unsaturated) then | ||
258 | we're grayscale (center axis of the colour cone) so | ||
259 | we set rgb=value. we use a formula obtained from | ||
260 | wikipedia to map the cone to the RGB plane. it's | ||
261 | as follows for the human value case of h=0..360, | ||
262 | s=0..1, v=0..1 | ||
263 | h_i = h/60 % 6 , f = h/60 - h_i , p = v(1-s) | ||
264 | q = v(1 - f*s) , t = v(1 - (1-f)s) | ||
265 | h_i==0 => r=v , g=t, b=p | ||
266 | h_i==1 => r=q , g=v, b=p | ||
267 | h_i==2 => r=p , g=v, b=t | ||
268 | h_i==3 => r=p , g=q, b=v | ||
269 | h_i==4 => r=t , g=p, b=v | ||
270 | h_i==5 => r=v , g=p, b=q | ||
271 | the bottom side (the point) and the stuff just up | ||
272 | of that is black so we simplify those two cases. | ||
273 | */ | ||
274 | if (sat < 32768) { | ||
275 | /* anything less than this is unsaturated */ | ||
276 | *r = val; | ||
277 | *g = val; | ||
278 | *b = val; | ||
279 | return; | ||
280 | } | ||
281 | if (val <= (0xFFFF/8)) { | ||
282 | /* anything less than this is black */ | ||
283 | *r = 0; | ||
284 | *g = 0; | ||
285 | *b = 0; | ||
286 | return; | ||
287 | } | ||
288 | |||
289 | /* the rest of this code is copying tukkat's | ||
290 | implementation of the hsv2rgb conversion as taken | ||
291 | from qc-usb-messenger code. the 10923 is 0xFFFF/6 | ||
292 | to divide the cone into 6 sectors. */ | ||
293 | |||
294 | segment = (h + 10923) & 0xFFFF; | ||
295 | segment = segment*3 >> 16; /* 0..2: 0=R, 1=G, 2=B */ | ||
296 | hue -= segment * 21845; /* -10923..10923 */ | ||
297 | h = hue; | ||
298 | h *= 3; | ||
299 | valsat = v*s >> 16; /* 0..65534 */ | ||
300 | p = v - valsat; | ||
301 | if (h >= 0) { | ||
302 | unsigned int t = v - (valsat * (32769 - h) >> 15); | ||
303 | switch (segment) { | ||
304 | case 0: /* R-> */ | ||
305 | *r = v; | ||
306 | *g = t; | ||
307 | *b = p; | ||
308 | break; | ||
309 | case 1: /* G-> */ | ||
310 | *r = p; | ||
311 | *g = v; | ||
312 | *b = t; | ||
313 | break; | ||
314 | case 2: /* B-> */ | ||
315 | *r = t; | ||
316 | *g = p; | ||
317 | *b = v; | ||
318 | break; | ||
319 | } | ||
320 | } else { | ||
321 | unsigned int q = v - (valsat * (32769 + h) >> 15); | ||
322 | switch (segment) { | ||
323 | case 0: /* ->R */ | ||
324 | *r = v; | ||
325 | *g = p; | ||
326 | *b = q; | ||
327 | break; | ||
328 | case 1: /* ->G */ | ||
329 | *r = q; | ||
330 | *g = v; | ||
331 | *b = p; | ||
332 | break; | ||
333 | case 2: /* ->B */ | ||
334 | *r = p; | ||
335 | *g = q; | ||
336 | *b = v; | ||
337 | break; | ||
338 | } | ||
339 | } | ||
340 | } | ||
341 | |||
342 | static int qcm_sensor_set_gains(struct uvd *uvd, u16 hue, | ||
343 | u16 saturation, u16 value) | ||
344 | { | ||
345 | int ret; | ||
346 | u16 r=0,g=0,b=0; | ||
347 | |||
348 | /* this code is based on qc-usb-messenger */ | ||
349 | qcm_hsv2rgb(hue, saturation, value, &r, &g, &b); | ||
350 | |||
351 | r >>= 12; | ||
352 | g >>= 12; | ||
353 | b >>= 12; | ||
354 | |||
355 | /* min val is 8 */ | ||
356 | r = max((u16) 8, r); | ||
357 | g = max((u16) 8, g); | ||
358 | b = max((u16) 8, b); | ||
359 | |||
360 | r |= 0x30; | ||
361 | g |= 0x30; | ||
362 | b |= 0x30; | ||
363 | |||
364 | /* set the r,g,b gain registers */ | ||
365 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x0509, r)); | ||
366 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050A, g)); | ||
367 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050B, b)); | ||
368 | |||
369 | /* doing as qc-usb did */ | ||
370 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050C, 0x2A)); | ||
371 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050D, 0x01)); | ||
372 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01)); | ||
373 | |||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static int qcm_sensor_set_exposure(struct uvd *uvd, int exposure) | ||
378 | { | ||
379 | int ret; | ||
380 | int formedval; | ||
381 | |||
382 | /* calculation was from qc-usb-messenger driver */ | ||
383 | formedval = ( exposure >> 12 ); | ||
384 | |||
385 | /* max value for formedval is 14 */ | ||
386 | formedval = min(formedval, 14); | ||
387 | |||
388 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, | ||
389 | 0x143A, 0xF0 | formedval)); | ||
390 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01)); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static int qcm_sensor_setlevels(struct uvd *uvd, int brightness, int contrast, | ||
395 | int hue, int colour) | ||
396 | { | ||
397 | int ret; | ||
398 | /* brightness is exposure, contrast is gain, colour is saturation */ | ||
399 | CHECK_RET(ret, | ||
400 | qcm_sensor_set_exposure(uvd, brightness)); | ||
401 | CHECK_RET(ret, qcm_sensor_set_gains(uvd, hue, colour, contrast)); | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int qcm_sensor_setsize(struct uvd *uvd, u8 size) | ||
407 | { | ||
408 | int ret; | ||
409 | |||
410 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x1505, size)); | ||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static int qcm_sensor_set_shutter(struct uvd *uvd, int whiteness) | ||
415 | { | ||
416 | int ret; | ||
417 | /* some rescaling as done by the qc-usb-messenger code */ | ||
418 | if (whiteness > 0xC000) | ||
419 | whiteness = 0xC000 + (whiteness & 0x3FFF)*8; | ||
420 | |||
421 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143D, | ||
422 | (whiteness >> 8) & 0xFF)); | ||
423 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143E, | ||
424 | (whiteness >> 16) & 0x03)); | ||
425 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01)); | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static int qcm_sensor_init(struct uvd *uvd) | ||
431 | { | ||
432 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
433 | int ret; | ||
434 | int i; | ||
435 | |||
436 | for (i=0; i < sizeof(regval_table)/sizeof(regval_table[0]) ; i++) { | ||
437 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, | ||
438 | regval_table[i].reg, | ||
439 | regval_table[i].val)); | ||
440 | } | ||
441 | |||
442 | CHECK_RET(ret, qcm_stv_setw(uvd->dev, 0x15c1, | ||
443 | cpu_to_le16(ISOC_PACKET_SIZE))); | ||
444 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x15c3, 0x08)); | ||
445 | CHECK_RET(ret, ret = qcm_stv_setb(uvd->dev, 0x143f, 0x01)); | ||
446 | |||
447 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00)); | ||
448 | |||
449 | CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd)); | ||
450 | |||
451 | CHECK_RET(ret, qcm_sensor_setlevels(uvd, uvd->vpic.brightness, | ||
452 | uvd->vpic.contrast, uvd->vpic.hue, uvd->vpic.colour)); | ||
453 | |||
454 | CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness)); | ||
455 | CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd)); | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int qcm_set_camera_size(struct uvd *uvd) | ||
461 | { | ||
462 | int ret; | ||
463 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
464 | |||
465 | CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd)); | ||
466 | cam->width = camera_sizes[cam->size].width; | ||
467 | cam->height = camera_sizes[cam->size].height; | ||
468 | uvd->videosize = VIDEOSIZE(cam->width, cam->height); | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static int qcm_setup_on_open(struct uvd *uvd) | ||
474 | { | ||
475 | int ret; | ||
476 | |||
477 | CHECK_RET(ret, qcm_sensor_set_gains(uvd, uvd->vpic.hue, | ||
478 | uvd->vpic.colour, uvd->vpic.contrast)); | ||
479 | CHECK_RET(ret, qcm_sensor_set_exposure(uvd, uvd->vpic.brightness)); | ||
480 | CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness)); | ||
481 | CHECK_RET(ret, qcm_set_camera_size(uvd)); | ||
482 | CHECK_RET(ret, qcm_camera_on(uvd)); | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | static void qcm_adjust_picture(struct uvd *uvd) | ||
487 | { | ||
488 | int ret; | ||
489 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
490 | |||
491 | ret = qcm_camera_off(uvd); | ||
492 | if (ret) { | ||
493 | err("can't turn camera off. abandoning pic adjustment"); | ||
494 | return; | ||
495 | } | ||
496 | |||
497 | /* if there's been a change in contrast, hue, or | ||
498 | colour then we need to recalculate hsv in order | ||
499 | to update gains */ | ||
500 | if ((cam->contrast != uvd->vpic.contrast) || | ||
501 | (cam->hue != uvd->vpic.hue) || | ||
502 | (cam->colour != uvd->vpic.colour)) { | ||
503 | cam->contrast = uvd->vpic.contrast; | ||
504 | cam->hue = uvd->vpic.hue; | ||
505 | cam->colour = uvd->vpic.colour; | ||
506 | ret = qcm_sensor_set_gains(uvd, cam->hue, cam->colour, | ||
507 | cam->contrast); | ||
508 | if (ret) { | ||
509 | err("can't set gains. abandoning pic adjustment"); | ||
510 | return; | ||
511 | } | ||
512 | } | ||
513 | |||
514 | if (cam->brightness != uvd->vpic.brightness) { | ||
515 | cam->brightness = uvd->vpic.brightness; | ||
516 | ret = qcm_sensor_set_exposure(uvd, cam->brightness); | ||
517 | if (ret) { | ||
518 | err("can't set exposure. abandoning pic adjustment"); | ||
519 | return; | ||
520 | } | ||
521 | } | ||
522 | |||
523 | if (cam->whiteness != uvd->vpic.whiteness) { | ||
524 | cam->whiteness = uvd->vpic.whiteness; | ||
525 | qcm_sensor_set_shutter(uvd, cam->whiteness); | ||
526 | if (ret) { | ||
527 | err("can't set shutter. abandoning pic adjustment"); | ||
528 | return; | ||
529 | } | ||
530 | } | ||
531 | |||
532 | ret = qcm_camera_on(uvd); | ||
533 | if (ret) { | ||
534 | err("can't reenable camera. pic adjustment failed"); | ||
535 | return; | ||
536 | } | ||
537 | } | ||
538 | |||
539 | static int qcm_process_frame(struct uvd *uvd, u8 *cdata, int framelen) | ||
540 | { | ||
541 | int datalen; | ||
542 | int totaldata; | ||
543 | struct framehdr { | ||
544 | __be16 id; | ||
545 | __be16 len; | ||
546 | }; | ||
547 | struct framehdr *fhdr; | ||
548 | |||
549 | totaldata = 0; | ||
550 | while (framelen) { | ||
551 | fhdr = (struct framehdr *) cdata; | ||
552 | datalen = be16_to_cpu(fhdr->len); | ||
553 | framelen -= 4; | ||
554 | cdata += 4; | ||
555 | |||
556 | if ((fhdr->id) == cpu_to_be16(0x8001)) { | ||
557 | RingQueue_Enqueue(&uvd->dp, marker, 4); | ||
558 | totaldata += 4; | ||
559 | continue; | ||
560 | } | ||
561 | if ((fhdr->id & cpu_to_be16(0xFF00)) == cpu_to_be16(0x0200)) { | ||
562 | RingQueue_Enqueue(&uvd->dp, cdata, datalen); | ||
563 | totaldata += datalen; | ||
564 | } | ||
565 | framelen -= datalen; | ||
566 | cdata += datalen; | ||
567 | } | ||
568 | return totaldata; | ||
569 | } | ||
570 | |||
571 | static int qcm_compress_iso(struct uvd *uvd, struct urb *dataurb) | ||
572 | { | ||
573 | int totlen; | ||
574 | int i; | ||
575 | unsigned char *cdata; | ||
576 | |||
577 | totlen=0; | ||
578 | for (i = 0; i < dataurb->number_of_packets; i++) { | ||
579 | int n = dataurb->iso_frame_desc[i].actual_length; | ||
580 | int st = dataurb->iso_frame_desc[i].status; | ||
581 | |||
582 | cdata = dataurb->transfer_buffer + | ||
583 | dataurb->iso_frame_desc[i].offset; | ||
584 | |||
585 | if (st < 0) { | ||
586 | warn("Data error: packet=%d. len=%d. status=%d.", | ||
587 | i, n, st); | ||
588 | uvd->stats.iso_err_count++; | ||
589 | continue; | ||
590 | } | ||
591 | if (!n) | ||
592 | continue; | ||
593 | |||
594 | totlen += qcm_process_frame(uvd, cdata, n); | ||
595 | } | ||
596 | return totlen; | ||
597 | } | ||
598 | |||
599 | static void resubmit_urb(struct uvd *uvd, struct urb *urb) | ||
600 | { | ||
601 | int ret; | ||
602 | |||
603 | urb->dev = uvd->dev; | ||
604 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
605 | if (ret) | ||
606 | err("usb_submit_urb error (%d)", ret); | ||
607 | } | ||
608 | |||
609 | static void qcm_isoc_irq(struct urb *urb, struct pt_regs *regs) | ||
610 | { | ||
611 | int len; | ||
612 | struct uvd *uvd = urb->context; | ||
613 | |||
614 | if (!CAMERA_IS_OPERATIONAL(uvd)) | ||
615 | return; | ||
616 | |||
617 | if (!uvd->streaming) | ||
618 | return; | ||
619 | |||
620 | uvd->stats.urb_count++; | ||
621 | |||
622 | if (!urb->actual_length) { | ||
623 | resubmit_urb(uvd, urb); | ||
624 | return; | ||
625 | } | ||
626 | |||
627 | len = qcm_compress_iso(uvd, urb); | ||
628 | resubmit_urb(uvd, urb); | ||
629 | uvd->stats.urb_length = len; | ||
630 | uvd->stats.data_count += len; | ||
631 | if (len) | ||
632 | RingQueue_WakeUpInterruptible(&uvd->dp); | ||
633 | } | ||
634 | |||
635 | static int qcm_start_data(struct uvd *uvd) | ||
636 | { | ||
637 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
638 | int i; | ||
639 | int errflag; | ||
640 | int pktsz; | ||
641 | int err; | ||
642 | |||
643 | pktsz = uvd->iso_packet_len; | ||
644 | if (!CAMERA_IS_OPERATIONAL(uvd)) { | ||
645 | err("Camera is not operational"); | ||
646 | return -EFAULT; | ||
647 | } | ||
648 | |||
649 | err = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltActive); | ||
650 | if (err < 0) { | ||
651 | err("usb_set_interface error"); | ||
652 | uvd->last_error = err; | ||
653 | return -EBUSY; | ||
654 | } | ||
655 | |||
656 | for (i=0; i < USBVIDEO_NUMSBUF; i++) { | ||
657 | int j, k; | ||
658 | struct urb *urb = uvd->sbuf[i].urb; | ||
659 | urb->dev = uvd->dev; | ||
660 | urb->context = uvd; | ||
661 | urb->pipe = usb_rcvisocpipe(uvd->dev, uvd->video_endp); | ||
662 | urb->interval = 1; | ||
663 | urb->transfer_flags = URB_ISO_ASAP; | ||
664 | urb->transfer_buffer = uvd->sbuf[i].data; | ||
665 | urb->complete = qcm_isoc_irq; | ||
666 | urb->number_of_packets = FRAMES_PER_DESC; | ||
667 | urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC; | ||
668 | for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) { | ||
669 | urb->iso_frame_desc[j].offset = k; | ||
670 | urb->iso_frame_desc[j].length = pktsz; | ||
671 | } | ||
672 | } | ||
673 | |||
674 | uvd->streaming = 1; | ||
675 | uvd->curframe = -1; | ||
676 | for (i=0; i < USBVIDEO_NUMSBUF; i++) { | ||
677 | errflag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); | ||
678 | if (errflag) | ||
679 | err ("usb_submit_isoc(%d) ret %d", i, errflag); | ||
680 | } | ||
681 | |||
682 | CHECK_RET(err, qcm_setup_input_int(cam, uvd)); | ||
683 | CHECK_RET(err, qcm_camera_on(uvd)); | ||
684 | return 0; | ||
685 | } | ||
686 | |||
687 | static void qcm_stop_data(struct uvd *uvd) | ||
688 | { | ||
689 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
690 | int i, j; | ||
691 | int ret; | ||
692 | |||
693 | if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) | ||
694 | return; | ||
695 | |||
696 | ret = qcm_camera_off(uvd); | ||
697 | if (ret) | ||
698 | warn("couldn't turn the cam off."); | ||
699 | |||
700 | uvd->streaming = 0; | ||
701 | |||
702 | /* Unschedule all of the iso td's */ | ||
703 | for (i=0; i < USBVIDEO_NUMSBUF; i++) | ||
704 | usb_kill_urb(uvd->sbuf[i].urb); | ||
705 | |||
706 | qcm_stop_int_data(cam); | ||
707 | |||
708 | if (!uvd->remove_pending) { | ||
709 | /* Set packet size to 0 */ | ||
710 | j = usb_set_interface(uvd->dev, uvd->iface, | ||
711 | uvd->ifaceAltInactive); | ||
712 | if (j < 0) { | ||
713 | err("usb_set_interface() error %d.", j); | ||
714 | uvd->last_error = j; | ||
715 | } | ||
716 | } | ||
717 | } | ||
718 | |||
719 | static void qcm_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) | ||
720 | { | ||
721 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
722 | int x; | ||
723 | struct rgb *rgbL0; | ||
724 | struct rgb *rgbL1; | ||
725 | struct bayL0 *bayL0; | ||
726 | struct bayL1 *bayL1; | ||
727 | int hor,ver,hordel,verdel; | ||
728 | assert(frame != NULL); | ||
729 | |||
730 | switch (cam->size) { | ||
731 | case SIZE_160X120: | ||
732 | hor = 162; ver = 124; hordel = 1; verdel = 2; | ||
733 | break; | ||
734 | case SIZE_320X240: | ||
735 | default: | ||
736 | hor = 324; ver = 248; hordel = 2; verdel = 4; | ||
737 | break; | ||
738 | } | ||
739 | |||
740 | if (frame->scanstate == ScanState_Scanning) { | ||
741 | while (RingQueue_GetLength(&uvd->dp) >= | ||
742 | 4 + (hor*verdel + hordel)) { | ||
743 | if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && | ||
744 | (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) && | ||
745 | (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) && | ||
746 | (RING_QUEUE_PEEK(&uvd->dp, 3) == 0xff)) { | ||
747 | frame->curline = 0; | ||
748 | frame->scanstate = ScanState_Lines; | ||
749 | frame->frameState = FrameState_Grabbing; | ||
750 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4); | ||
751 | /* | ||
752 | * if we're starting, we need to discard the first | ||
753 | * 4 lines of y bayer data | ||
754 | * and the first 2 gr elements of x bayer data | ||
755 | */ | ||
756 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, | ||
757 | (hor*verdel + hordel)); | ||
758 | break; | ||
759 | } | ||
760 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); | ||
761 | } | ||
762 | } | ||
763 | |||
764 | if (frame->scanstate == ScanState_Scanning) | ||
765 | return; | ||
766 | |||
767 | /* now we can start processing bayer data so long as we have at least | ||
768 | * 2 lines worth of data. this is the simplest demosaicing method that | ||
769 | * I could think of. I use each 2x2 bayer element without interpolation | ||
770 | * to generate 4 rgb pixels. | ||
771 | */ | ||
772 | while ( frame->curline < cam->height && | ||
773 | (RingQueue_GetLength(&uvd->dp) >= hor*2)) { | ||
774 | /* get 2 lines of bayer for demosaicing | ||
775 | * into 2 lines of RGB */ | ||
776 | RingQueue_Dequeue(&uvd->dp, cam->scratch, hor*2); | ||
777 | bayL0 = (struct bayL0 *) cam->scratch; | ||
778 | bayL1 = (struct bayL1 *) (cam->scratch + hor); | ||
779 | /* frame->curline is the rgb y line */ | ||
780 | rgbL0 = (struct rgb *) | ||
781 | ( frame->data + (cam->width*3*frame->curline)); | ||
782 | /* w/2 because we're already doing 2 pixels */ | ||
783 | rgbL1 = rgbL0 + (cam->width/2); | ||
784 | |||
785 | for (x=0; x < cam->width; x+=2) { | ||
786 | rgbL0->r = bayL0->r; | ||
787 | rgbL0->g = bayL0->g; | ||
788 | rgbL0->b = bayL1->b; | ||
789 | |||
790 | rgbL0->r2 = bayL0->r; | ||
791 | rgbL0->g2 = bayL1->g; | ||
792 | rgbL0->b2 = bayL1->b; | ||
793 | |||
794 | rgbL1->r = bayL0->r; | ||
795 | rgbL1->g = bayL1->g; | ||
796 | rgbL1->b = bayL1->b; | ||
797 | |||
798 | rgbL1->r2 = bayL0->r; | ||
799 | rgbL1->g2 = bayL1->g; | ||
800 | rgbL1->b2 = bayL1->b; | ||
801 | |||
802 | rgbL0++; | ||
803 | rgbL1++; | ||
804 | |||
805 | bayL0++; | ||
806 | bayL1++; | ||
807 | } | ||
808 | |||
809 | frame->seqRead_Length += cam->width*3*2; | ||
810 | frame->curline += 2; | ||
811 | } | ||
812 | /* See if we filled the frame */ | ||
813 | if (frame->curline == cam->height) { | ||
814 | frame->frameState = FrameState_Done_Hold; | ||
815 | frame->curline = 0; | ||
816 | uvd->curframe = -1; | ||
817 | uvd->stats.frame_num++; | ||
818 | } | ||
819 | } | ||
820 | |||
821 | /* taken from konicawc */ | ||
822 | static int qcm_set_video_mode(struct uvd *uvd, struct video_window *vw) | ||
823 | { | ||
824 | int ret; | ||
825 | int newsize; | ||
826 | int oldsize; | ||
827 | int x = vw->width; | ||
828 | int y = vw->height; | ||
829 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
830 | |||
831 | if (x > 0 && y > 0) { | ||
832 | DEBUG(2, "trying to find size %d,%d", x, y); | ||
833 | for (newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) { | ||
834 | if ((camera_sizes[newsize].width == x) && | ||
835 | (camera_sizes[newsize].height == y)) | ||
836 | break; | ||
837 | } | ||
838 | } else | ||
839 | newsize = cam->size; | ||
840 | |||
841 | if (newsize > MAX_FRAME_SIZE) { | ||
842 | DEBUG(1, "couldn't find size %d,%d", x, y); | ||
843 | return -EINVAL; | ||
844 | } | ||
845 | |||
846 | if (newsize == cam->size) { | ||
847 | DEBUG(1, "Nothing to do"); | ||
848 | return 0; | ||
849 | } | ||
850 | |||
851 | qcm_stop_data(uvd); | ||
852 | |||
853 | if (cam->size != newsize) { | ||
854 | oldsize = cam->size; | ||
855 | cam->size = newsize; | ||
856 | ret = qcm_set_camera_size(uvd); | ||
857 | if (ret) { | ||
858 | err("Couldn't set camera size, err=%d",ret); | ||
859 | /* restore the original size */ | ||
860 | cam->size = oldsize; | ||
861 | return ret; | ||
862 | } | ||
863 | } | ||
864 | |||
865 | /* Flush the input queue and clear any current frame in progress */ | ||
866 | |||
867 | RingQueue_Flush(&uvd->dp); | ||
868 | if (uvd->curframe != -1) { | ||
869 | uvd->frame[uvd->curframe].curline = 0; | ||
870 | uvd->frame[uvd->curframe].seqRead_Length = 0; | ||
871 | uvd->frame[uvd->curframe].seqRead_Index = 0; | ||
872 | } | ||
873 | |||
874 | CHECK_RET(ret, qcm_start_data(uvd)); | ||
875 | return 0; | ||
876 | } | ||
877 | |||
878 | static int qcm_configure_video(struct uvd *uvd) | ||
879 | { | ||
880 | int ret; | ||
881 | memset(&uvd->vpic, 0, sizeof(uvd->vpic)); | ||
882 | memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); | ||
883 | |||
884 | uvd->vpic.colour = colour; | ||
885 | uvd->vpic.hue = hue; | ||
886 | uvd->vpic.brightness = brightness; | ||
887 | uvd->vpic.contrast = contrast; | ||
888 | uvd->vpic.whiteness = whiteness; | ||
889 | uvd->vpic.depth = 24; | ||
890 | uvd->vpic.palette = VIDEO_PALETTE_RGB24; | ||
891 | |||
892 | memset(&uvd->vcap, 0, sizeof(uvd->vcap)); | ||
893 | strcpy(uvd->vcap.name, "QCM USB Camera"); | ||
894 | uvd->vcap.type = VID_TYPE_CAPTURE; | ||
895 | uvd->vcap.channels = 1; | ||
896 | uvd->vcap.audios = 0; | ||
897 | |||
898 | uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width; | ||
899 | uvd->vcap.minheight = camera_sizes[SIZE_160X120].height; | ||
900 | uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width; | ||
901 | uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height; | ||
902 | |||
903 | memset(&uvd->vchan, 0, sizeof(uvd->vchan)); | ||
904 | uvd->vchan.flags = 0 ; | ||
905 | uvd->vchan.tuners = 0; | ||
906 | uvd->vchan.channel = 0; | ||
907 | uvd->vchan.type = VIDEO_TYPE_CAMERA; | ||
908 | strcpy(uvd->vchan.name, "Camera"); | ||
909 | |||
910 | CHECK_RET(ret, qcm_sensor_init(uvd)); | ||
911 | return 0; | ||
912 | } | ||
913 | |||
914 | static int qcm_probe(struct usb_interface *intf, | ||
915 | const struct usb_device_id *devid) | ||
916 | { | ||
917 | int err; | ||
918 | struct uvd *uvd; | ||
919 | struct usb_device *dev = interface_to_usbdev(intf); | ||
920 | struct qcm *cam; | ||
921 | size_t buffer_size; | ||
922 | unsigned char video_ep; | ||
923 | struct usb_host_interface *interface; | ||
924 | struct usb_endpoint_descriptor *endpoint; | ||
925 | int i,j; | ||
926 | unsigned int ifacenum, ifacenum_inact=0; | ||
927 | __le16 sensor_id; | ||
928 | |||
929 | /* we don't support multiconfig cams */ | ||
930 | if (dev->descriptor.bNumConfigurations != 1) | ||
931 | return -ENODEV; | ||
932 | |||
933 | /* first check for the video interface and not | ||
934 | * the audio interface */ | ||
935 | interface = &intf->cur_altsetting[0]; | ||
936 | if ((interface->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) | ||
937 | || (interface->desc.bInterfaceSubClass != | ||
938 | USB_CLASS_VENDOR_SPEC)) | ||
939 | return -ENODEV; | ||
940 | |||
941 | /* | ||
942 | walk through each endpoint in each setting in the interface | ||
943 | stop when we find the one that's an isochronous IN endpoint. | ||
944 | */ | ||
945 | for (i=0; i < intf->num_altsetting; i++) { | ||
946 | interface = &intf->cur_altsetting[i]; | ||
947 | ifacenum = interface->desc.bAlternateSetting; | ||
948 | /* walk the end points */ | ||
949 | for (j=0; j < interface->desc.bNumEndpoints; j++) { | ||
950 | endpoint = &interface->endpoint[j].desc; | ||
951 | |||
952 | if ((endpoint->bEndpointAddress & | ||
953 | USB_ENDPOINT_DIR_MASK) != USB_DIR_IN) | ||
954 | continue; /* not input then not good */ | ||
955 | |||
956 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | ||
957 | if (!buffer_size) { | ||
958 | ifacenum_inact = ifacenum; | ||
959 | continue; /* 0 pkt size is not what we want */ | ||
960 | } | ||
961 | |||
962 | if ((endpoint->bmAttributes & | ||
963 | USB_ENDPOINT_XFERTYPE_MASK) == | ||
964 | USB_ENDPOINT_XFER_ISOC) { | ||
965 | video_ep = endpoint->bEndpointAddress; | ||
966 | /* break out of the search */ | ||
967 | goto good_videoep; | ||
968 | } | ||
969 | } | ||
970 | } | ||
971 | /* failed out since nothing useful was found */ | ||
972 | err("No suitable endpoint was found\n"); | ||
973 | return -ENODEV; | ||
974 | |||
975 | good_videoep: | ||
976 | /* disable isochronous stream before doing anything else */ | ||
977 | err = qcm_stv_setb(dev, STV_ISO_ENABLE, 0); | ||
978 | if (err < 0) { | ||
979 | err("Failed to disable sensor stream"); | ||
980 | return -EIO; | ||
981 | } | ||
982 | |||
983 | /* | ||
984 | Check that this is the same unknown sensor that is known to work. This | ||
985 | sensor is suspected to be the ST VV6422C001. I'll check the same value | ||
986 | that the qc-usb driver checks. This value is probably not even the | ||
987 | sensor ID since it matches the USB dev ID. Oh well. If it doesn't | ||
988 | match, it's probably a diff sensor so exit and apologize. | ||
989 | */ | ||
990 | err = qcm_stv_getw(dev, CMOS_SENSOR_IDREV, &sensor_id); | ||
991 | if (err < 0) { | ||
992 | err("Couldn't read sensor values. Err %d\n",err); | ||
993 | return err; | ||
994 | } | ||
995 | if (sensor_id != cpu_to_le16(0x08F0)) { | ||
996 | err("Sensor ID %x != %x. Unsupported. Sorry\n", | ||
997 | le16_to_cpu(sensor_id), (0x08F0)); | ||
998 | return -ENODEV; | ||
999 | } | ||
1000 | |||
1001 | uvd = usbvideo_AllocateDevice(cams); | ||
1002 | if (!uvd) | ||
1003 | return -ENOMEM; | ||
1004 | |||
1005 | cam = (struct qcm *) uvd->user_data; | ||
1006 | |||
1007 | /* buf for doing demosaicing */ | ||
1008 | cam->scratch = kmalloc(324*2, GFP_KERNEL); | ||
1009 | if (!cam->scratch) /* uvd freed in dereg */ | ||
1010 | return -ENOMEM; | ||
1011 | |||
1012 | /* yes, if we fail after here, cam->scratch gets freed | ||
1013 | by qcm_free_uvd */ | ||
1014 | |||
1015 | err = qcm_alloc_int_urb(cam); | ||
1016 | if (err < 0) | ||
1017 | return err; | ||
1018 | |||
1019 | /* yes, if we fail after here, int urb gets freed | ||
1020 | by qcm_free_uvd */ | ||
1021 | |||
1022 | RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240); | ||
1023 | cam->width = camera_sizes[size].width; | ||
1024 | cam->height = camera_sizes[size].height; | ||
1025 | cam->size = size; | ||
1026 | |||
1027 | uvd->debug = debug; | ||
1028 | uvd->flags = 0; | ||
1029 | uvd->dev = dev; | ||
1030 | uvd->iface = intf->altsetting->desc.bInterfaceNumber; | ||
1031 | uvd->ifaceAltActive = ifacenum; | ||
1032 | uvd->ifaceAltInactive = ifacenum_inact; | ||
1033 | uvd->video_endp = video_ep; | ||
1034 | uvd->iso_packet_len = buffer_size; | ||
1035 | uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; | ||
1036 | uvd->defaultPalette = VIDEO_PALETTE_RGB24; | ||
1037 | uvd->canvas = VIDEOSIZE(320, 240); | ||
1038 | uvd->videosize = VIDEOSIZE(cam->width, cam->height); | ||
1039 | err = qcm_configure_video(uvd); | ||
1040 | if (err) { | ||
1041 | err("failed to configure video settings"); | ||
1042 | return err; | ||
1043 | } | ||
1044 | |||
1045 | err = usbvideo_RegisterVideoDevice(uvd); | ||
1046 | if (err) { /* the uvd gets freed in Deregister */ | ||
1047 | err("usbvideo_RegisterVideoDevice() failed."); | ||
1048 | return err; | ||
1049 | } | ||
1050 | |||
1051 | uvd->max_frame_size = (320 * 240 * 3); | ||
1052 | qcm_register_input(cam, dev); | ||
1053 | usb_set_intfdata(intf, uvd); | ||
1054 | return 0; | ||
1055 | } | ||
1056 | |||
1057 | static void qcm_free_uvd(struct uvd *uvd) | ||
1058 | { | ||
1059 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
1060 | |||
1061 | kfree(cam->scratch); | ||
1062 | qcm_unregister_input(cam); | ||
1063 | qcm_free_int(cam); | ||
1064 | } | ||
1065 | |||
1066 | static struct usbvideo_cb qcm_driver = { | ||
1067 | .probe = qcm_probe, | ||
1068 | .setupOnOpen = qcm_setup_on_open, | ||
1069 | .processData = qcm_process_isoc, | ||
1070 | .setVideoMode = qcm_set_video_mode, | ||
1071 | .startDataPump = qcm_start_data, | ||
1072 | .stopDataPump = qcm_stop_data, | ||
1073 | .adjustPicture = qcm_adjust_picture, | ||
1074 | .userFree = qcm_free_uvd | ||
1075 | }; | ||
1076 | |||
1077 | static int __init qcm_init(void) | ||
1078 | { | ||
1079 | info(DRIVER_DESC " " DRIVER_VERSION); | ||
1080 | |||
1081 | return usbvideo_register( | ||
1082 | &cams, | ||
1083 | MAX_CAMERAS, | ||
1084 | sizeof(struct qcm), | ||
1085 | "QCM", | ||
1086 | &qcm_driver, | ||
1087 | THIS_MODULE, | ||
1088 | qcm_table); | ||
1089 | } | ||
1090 | |||
1091 | static void __exit qcm_exit(void) | ||
1092 | { | ||
1093 | usbvideo_Deregister(&cams); | ||
1094 | } | ||
1095 | |||
1096 | module_param(size, int, 0); | ||
1097 | MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 320x240"); | ||
1098 | module_param(colour, int, 0); | ||
1099 | MODULE_PARM_DESC(colour, "Initial colour"); | ||
1100 | module_param(hue, int, 0); | ||
1101 | MODULE_PARM_DESC(hue, "Initial hue"); | ||
1102 | module_param(brightness, int, 0); | ||
1103 | MODULE_PARM_DESC(brightness, "Initial brightness"); | ||
1104 | module_param(contrast, int, 0); | ||
1105 | MODULE_PARM_DESC(contrast, "Initial contrast"); | ||
1106 | module_param(whiteness, int, 0); | ||
1107 | MODULE_PARM_DESC(whiteness, "Initial whiteness"); | ||
1108 | |||
1109 | #ifdef CONFIG_USB_DEBUG | ||
1110 | module_param(debug, int, S_IRUGO | S_IWUSR); | ||
1111 | MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); | ||
1112 | #endif | ||
1113 | |||
1114 | module_init(qcm_init); | ||
1115 | module_exit(qcm_exit); | ||
1116 | |||
1117 | MODULE_LICENSE("GPL"); | ||
1118 | MODULE_AUTHOR("Jaya Kumar"); | ||
1119 | MODULE_DESCRIPTION("QCM USB Camera"); | ||
1120 | MODULE_SUPPORTED_DEVICE("QCM USB Camera"); | ||
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.h b/drivers/media/video/usbvideo/quickcam_messenger.h new file mode 100644 index 000000000000..baab9c081b52 --- /dev/null +++ b/drivers/media/video/usbvideo/quickcam_messenger.h | |||
@@ -0,0 +1,126 @@ | |||
1 | #ifndef quickcam_messenger_h | ||
2 | #define quickcam_messenger_h | ||
3 | |||
4 | #ifndef CONFIG_INPUT | ||
5 | /* if we're not using input we dummy out these functions */ | ||
6 | #define qcm_register_input(...) | ||
7 | #define qcm_unregister_input(...) | ||
8 | #define qcm_report_buttonstat(...) | ||
9 | #define qcm_setup_input_int(...) 0 | ||
10 | #define qcm_stop_int_data(...) | ||
11 | #define qcm_alloc_int_urb(...) 0 | ||
12 | #define qcm_free_int(...) | ||
13 | #endif | ||
14 | |||
15 | |||
16 | #define CHECK_RET(ret, expr) \ | ||
17 | if ((ret = expr) < 0) return ret | ||
18 | |||
19 | /* Control Registers for the STVV6422 ASIC | ||
20 | * - this define is taken from the qc-usb-messenger code | ||
21 | */ | ||
22 | #define STV_ISO_ENABLE 0x1440 | ||
23 | #define ISOC_PACKET_SIZE 1023 | ||
24 | |||
25 | /* Chip identification number including revision indicator */ | ||
26 | #define CMOS_SENSOR_IDREV 0xE00A | ||
27 | |||
28 | struct rgb { | ||
29 | u8 b; | ||
30 | u8 g; | ||
31 | u8 r; | ||
32 | u8 b2; | ||
33 | u8 g2; | ||
34 | u8 r2; | ||
35 | }; | ||
36 | |||
37 | struct bayL0 { | ||
38 | #ifdef __BIG_ENDIAN | ||
39 | u8 r; | ||
40 | u8 g; | ||
41 | #elif __LITTLE_ENDIAN | ||
42 | u8 g; | ||
43 | u8 r; | ||
44 | #else | ||
45 | #error not byte order defined | ||
46 | #endif | ||
47 | }; | ||
48 | |||
49 | struct bayL1 { | ||
50 | #ifdef __BIG_ENDIAN | ||
51 | u8 g; | ||
52 | u8 b; | ||
53 | #elif __LITTLE_ENDIAN | ||
54 | u8 b; | ||
55 | u8 g; | ||
56 | #else | ||
57 | #error not byte order defined | ||
58 | #endif | ||
59 | }; | ||
60 | |||
61 | struct cam_size { | ||
62 | u16 width; | ||
63 | u16 height; | ||
64 | u8 cmd; | ||
65 | }; | ||
66 | |||
67 | static const struct cam_size camera_sizes[] = { | ||
68 | { 160, 120, 0xf }, | ||
69 | { 320, 240, 0x2 }, | ||
70 | }; | ||
71 | |||
72 | enum frame_sizes { | ||
73 | SIZE_160X120 = 0, | ||
74 | SIZE_320X240 = 1, | ||
75 | }; | ||
76 | |||
77 | #define MAX_FRAME_SIZE SIZE_320X240 | ||
78 | |||
79 | struct qcm { | ||
80 | u16 colour; | ||
81 | u16 hue; | ||
82 | u16 brightness; | ||
83 | u16 contrast; | ||
84 | u16 whiteness; | ||
85 | |||
86 | u8 size; | ||
87 | int height; | ||
88 | int width; | ||
89 | u8 *scratch; | ||
90 | struct urb *button_urb; | ||
91 | u8 button_sts; | ||
92 | u8 button_sts_buf; | ||
93 | |||
94 | #ifdef CONFIG_INPUT | ||
95 | struct input_dev *input; | ||
96 | char input_physname[64]; | ||
97 | #endif | ||
98 | }; | ||
99 | |||
100 | struct regval { | ||
101 | u16 reg; | ||
102 | u8 val; | ||
103 | }; | ||
104 | /* this table is derived from the | ||
105 | qc-usb-messenger code */ | ||
106 | static const struct regval regval_table[] = { | ||
107 | { STV_ISO_ENABLE, 0x00 }, | ||
108 | { 0x1436, 0x00 }, { 0x1432, 0x03 }, | ||
109 | { 0x143a, 0xF9 }, { 0x0509, 0x38 }, | ||
110 | { 0x050a, 0x38 }, { 0x050b, 0x38 }, | ||
111 | { 0x050c, 0x2A }, { 0x050d, 0x01 }, | ||
112 | { 0x1431, 0x00 }, { 0x1433, 0x34 }, | ||
113 | { 0x1438, 0x18 }, { 0x1439, 0x00 }, | ||
114 | { 0x143b, 0x05 }, { 0x143c, 0x00 }, | ||
115 | { 0x143e, 0x01 }, { 0x143d, 0x00 }, | ||
116 | { 0x1442, 0xe2 }, { 0x1500, 0xd0 }, | ||
117 | { 0x1500, 0xd0 }, { 0x1500, 0x50 }, | ||
118 | { 0x1501, 0xaf }, { 0x1502, 0xc2 }, | ||
119 | { 0x1503, 0x45 }, { 0x1505, 0x02 }, | ||
120 | { 0x150e, 0x8e }, { 0x150f, 0x37 }, | ||
121 | { 0x15c0, 0x00 }, | ||
122 | }; | ||
123 | |||
124 | static const unsigned char marker[] = { 0x00, 0xff, 0x00, 0xFF }; | ||
125 | |||
126 | #endif /* quickcam_messenger_h */ | ||
diff --git a/drivers/media/video/usbvideo/usbvideo.h b/drivers/media/video/usbvideo/usbvideo.h index 3cbf4fc499a3..49dbee5f5628 100644 --- a/drivers/media/video/usbvideo/usbvideo.h +++ b/drivers/media/video/usbvideo/usbvideo.h | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/config.h> | 19 | #include <linux/config.h> |
20 | #include <linux/videodev.h> | 20 | #include <linux/videodev.h> |
21 | #include <media/v4l2-common.h> | ||
21 | #include <linux/usb.h> | 22 | #include <linux/usb.h> |
22 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
23 | 24 | ||
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 474a29bc1760..19d3c20dc7ef 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/errno.h> | 32 | #include <linux/errno.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/videodev.h> | 34 | #include <linux/videodev.h> |
35 | #include <media/v4l2-common.h> | ||
35 | 36 | ||
36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
37 | #include <asm/system.h> | 38 | #include <asm/system.h> |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index d330fa985bcc..14e523471354 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <asm/io.h> | 59 | #include <asm/io.h> |
60 | #include <asm/div64.h> | 60 | #include <asm/div64.h> |
61 | #include <linux/video_decoder.h> | 61 | #include <linux/video_decoder.h> |
62 | #define __OLD_VIDIOC_ /* To allow fixing old calls*/ | ||
62 | #include <media/v4l2-common.h> | 63 | #include <media/v4l2-common.h> |
63 | 64 | ||
64 | #ifdef CONFIG_KMOD | 65 | #ifdef CONFIG_KMOD |
@@ -293,7 +294,10 @@ static const char *v4l2_ioctls[] = { | |||
293 | #if 1 | 294 | #if 1 |
294 | [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP", | 295 | [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP", |
295 | #endif | 296 | #endif |
296 | [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS" | 297 | [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS", |
298 | [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS", | ||
299 | [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS", | ||
300 | [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS" | ||
297 | }; | 301 | }; |
298 | #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) | 302 | #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) |
299 | 303 | ||
@@ -331,7 +335,8 @@ static const char *v4l2_int_ioctls[] = { | |||
331 | [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING", | 335 | [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING", |
332 | [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING", | 336 | [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING", |
333 | [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING", | 337 | [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING", |
334 | [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING" | 338 | [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING", |
339 | [_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)] = "VIDIOC_INT_S_CRYSTAL_FREQ" | ||
335 | }; | 340 | }; |
336 | #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls) | 341 | #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls) |
337 | 342 | ||
@@ -423,7 +428,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) | |||
423 | case TUNER_SET_TYPE_ADDR: | 428 | case TUNER_SET_TYPE_ADDR: |
424 | case TUNER_SET_STANDBY: | 429 | case TUNER_SET_STANDBY: |
425 | case TDA9887_SET_CONFIG: | 430 | case TDA9887_SET_CONFIG: |
431 | #ifdef __OLD_VIDIOC_ | ||
426 | case VIDIOC_OVERLAY_OLD: | 432 | case VIDIOC_OVERLAY_OLD: |
433 | #endif | ||
427 | case VIDIOC_STREAMOFF: | 434 | case VIDIOC_STREAMOFF: |
428 | case VIDIOC_G_OUTPUT: | 435 | case VIDIOC_G_OUTPUT: |
429 | case VIDIOC_S_OUTPUT: | 436 | case VIDIOC_S_OUTPUT: |
@@ -439,7 +446,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) | |||
439 | case VIDIOC_G_AUDIO: | 446 | case VIDIOC_G_AUDIO: |
440 | case VIDIOC_S_AUDIO: | 447 | case VIDIOC_S_AUDIO: |
441 | case VIDIOC_ENUMAUDIO: | 448 | case VIDIOC_ENUMAUDIO: |
449 | #ifdef __OLD_VIDIOC_ | ||
442 | case VIDIOC_G_AUDIO_OLD: | 450 | case VIDIOC_G_AUDIO_OLD: |
451 | #endif | ||
443 | { | 452 | { |
444 | struct v4l2_audio *p=arg; | 453 | struct v4l2_audio *p=arg; |
445 | 454 | ||
@@ -450,7 +459,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) | |||
450 | case VIDIOC_G_AUDOUT: | 459 | case VIDIOC_G_AUDOUT: |
451 | case VIDIOC_S_AUDOUT: | 460 | case VIDIOC_S_AUDOUT: |
452 | case VIDIOC_ENUMAUDOUT: | 461 | case VIDIOC_ENUMAUDOUT: |
462 | #ifdef __OLD_VIDIOC_ | ||
453 | case VIDIOC_G_AUDOUT_OLD: | 463 | case VIDIOC_G_AUDOUT_OLD: |
464 | #endif | ||
454 | { | 465 | { |
455 | struct v4l2_audioout *p=arg; | 466 | struct v4l2_audioout *p=arg; |
456 | printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", s, | 467 | printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", s, |
@@ -478,9 +489,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) | |||
478 | prt_names(p->memory,v4l2_memory_names), | 489 | prt_names(p->memory,v4l2_memory_names), |
479 | p->m.userptr); | 490 | p->m.userptr); |
480 | printk ("%s: timecode= %02d:%02d:%02d type=%d, " | 491 | printk ("%s: timecode= %02d:%02d:%02d type=%d, " |
481 | "flags=0x%08x, frames=%d, userbits=0x%p\n", | 492 | "flags=0x%08x, frames=%d, userbits=0x%08x\n", |
482 | s,tc->hours,tc->minutes,tc->seconds, | 493 | s,tc->hours,tc->minutes,tc->seconds, |
483 | tc->type, tc->flags, tc->frames, tc->userbits); | 494 | tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits); |
484 | break; | 495 | break; |
485 | } | 496 | } |
486 | case VIDIOC_QUERYCAP: | 497 | case VIDIOC_QUERYCAP: |
@@ -495,12 +506,31 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) | |||
495 | } | 506 | } |
496 | case VIDIOC_G_CTRL: | 507 | case VIDIOC_G_CTRL: |
497 | case VIDIOC_S_CTRL: | 508 | case VIDIOC_S_CTRL: |
509 | #ifdef __OLD_VIDIOC_ | ||
498 | case VIDIOC_S_CTRL_OLD: | 510 | case VIDIOC_S_CTRL_OLD: |
511 | #endif | ||
499 | { | 512 | { |
500 | struct v4l2_control *p=arg; | 513 | struct v4l2_control *p=arg; |
501 | printk ("%s: id=%d, value=%d\n", s, p->id, p->value); | 514 | printk ("%s: id=%d, value=%d\n", s, p->id, p->value); |
502 | break; | 515 | break; |
503 | } | 516 | } |
517 | case VIDIOC_G_EXT_CTRLS: | ||
518 | case VIDIOC_S_EXT_CTRLS: | ||
519 | case VIDIOC_TRY_EXT_CTRLS: | ||
520 | { | ||
521 | struct v4l2_ext_controls *p = arg; | ||
522 | int i; | ||
523 | |||
524 | printk("%s: ctrl_class=%d, count=%d\n", s, p->ctrl_class, p->count); | ||
525 | for (i = 0; i < p->count; i++) { | ||
526 | struct v4l2_ext_control *c = &p->controls[i]; | ||
527 | if (cmd == VIDIOC_G_EXT_CTRLS) | ||
528 | printk("%s: id=%d\n", s, c->id); | ||
529 | else | ||
530 | printk("%s: id=%d, value=%d\n", s, c->id, c->value); | ||
531 | } | ||
532 | break; | ||
533 | } | ||
504 | case VIDIOC_G_CROP: | 534 | case VIDIOC_G_CROP: |
505 | case VIDIOC_S_CROP: | 535 | case VIDIOC_S_CROP: |
506 | { | 536 | { |
@@ -510,7 +540,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) | |||
510 | break; | 540 | break; |
511 | } | 541 | } |
512 | case VIDIOC_CROPCAP: | 542 | case VIDIOC_CROPCAP: |
543 | #ifdef __OLD_VIDIOC_ | ||
513 | case VIDIOC_CROPCAP_OLD: | 544 | case VIDIOC_CROPCAP_OLD: |
545 | #endif | ||
514 | { | 546 | { |
515 | struct v4l2_cropcap *p=arg; | 547 | struct v4l2_cropcap *p=arg; |
516 | /*FIXME: Should also show rect structs */ | 548 | /*FIXME: Should also show rect structs */ |
@@ -667,6 +699,12 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) | |||
667 | printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output); | 699 | printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output); |
668 | break; | 700 | break; |
669 | } | 701 | } |
702 | case VIDIOC_INT_S_CRYSTAL_FREQ: | ||
703 | { | ||
704 | struct v4l2_crystal_freq *p=arg; | ||
705 | printk ("%s: freq=%u, flags=0x%x\n", s, p->freq, p->flags); | ||
706 | break; | ||
707 | } | ||
670 | case VIDIOC_G_SLICED_VBI_CAP: | 708 | case VIDIOC_G_SLICED_VBI_CAP: |
671 | { | 709 | { |
672 | struct v4l2_sliced_vbi_cap *p=arg; | 710 | struct v4l2_sliced_vbi_cap *p=arg; |
@@ -696,7 +734,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) | |||
696 | } | 734 | } |
697 | case VIDIOC_G_PARM: | 735 | case VIDIOC_G_PARM: |
698 | case VIDIOC_S_PARM: | 736 | case VIDIOC_S_PARM: |
737 | #ifdef __OLD_VIDIOC_ | ||
699 | case VIDIOC_S_PARM_OLD: | 738 | case VIDIOC_S_PARM_OLD: |
739 | #endif | ||
700 | { | 740 | { |
701 | struct v4l2_streamparm *p=arg; | 741 | struct v4l2_streamparm *p=arg; |
702 | printk ("%s: type=%d\n", s, p->type); | 742 | printk ("%s: type=%d\n", s, p->type); |
@@ -915,6 +955,484 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) | |||
915 | 955 | ||
916 | /* ----------------------------------------------------------------- */ | 956 | /* ----------------------------------------------------------------- */ |
917 | 957 | ||
958 | /* Helper functions for control handling */ | ||
959 | |||
960 | /* Check for correctness of the ctrl's value based on the data from | ||
961 | struct v4l2_queryctrl and the available menu items. Note that | ||
962 | menu_items may be NULL, in that case it is ignored. */ | ||
963 | int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, | ||
964 | const char **menu_items) | ||
965 | { | ||
966 | if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED) | ||
967 | return -EINVAL; | ||
968 | if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED) | ||
969 | return -EBUSY; | ||
970 | if (qctrl->type == V4L2_CTRL_TYPE_BUTTON || | ||
971 | qctrl->type == V4L2_CTRL_TYPE_INTEGER64 || | ||
972 | qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS) | ||
973 | return 0; | ||
974 | if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum) | ||
975 | return -ERANGE; | ||
976 | if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) { | ||
977 | if (menu_items[ctrl->value] == NULL || | ||
978 | menu_items[ctrl->value][0] == '\0') | ||
979 | return -EINVAL; | ||
980 | } | ||
981 | return 0; | ||
982 | } | ||
983 | |||
984 | /* Returns NULL or a character pointer array containing the menu for | ||
985 | the given control ID. The pointer array ends with a NULL pointer. | ||
986 | An empty string signifies a menu entry that is invalid. This allows | ||
987 | drivers to disable certain options if it is not supported. */ | ||
988 | const char **v4l2_ctrl_get_menu(u32 id) | ||
989 | { | ||
990 | static const char *mpeg_audio_sampling_freq[] = { | ||
991 | "44.1 kHz", | ||
992 | "48 kHz", | ||
993 | "32 kHz", | ||
994 | NULL | ||
995 | }; | ||
996 | static const char *mpeg_audio_encoding[] = { | ||
997 | "Layer I", | ||
998 | "Layer II", | ||
999 | "Layer III", | ||
1000 | NULL | ||
1001 | }; | ||
1002 | static const char *mpeg_audio_l1_bitrate[] = { | ||
1003 | "32 kbps", | ||
1004 | "64 kbps", | ||
1005 | "96 kbps", | ||
1006 | "128 kbps", | ||
1007 | "160 kbps", | ||
1008 | "192 kbps", | ||
1009 | "224 kbps", | ||
1010 | "256 kbps", | ||
1011 | "288 kbps", | ||
1012 | "320 kbps", | ||
1013 | "352 kbps", | ||
1014 | "384 kbps", | ||
1015 | "416 kbps", | ||
1016 | "448 kbps", | ||
1017 | NULL | ||
1018 | }; | ||
1019 | static const char *mpeg_audio_l2_bitrate[] = { | ||
1020 | "32 kbps", | ||
1021 | "48 kbps", | ||
1022 | "56 kbps", | ||
1023 | "64 kbps", | ||
1024 | "80 kbps", | ||
1025 | "96 kbps", | ||
1026 | "112 kbps", | ||
1027 | "128 kbps", | ||
1028 | "160 kbps", | ||
1029 | "192 kbps", | ||
1030 | "224 kbps", | ||
1031 | "256 kbps", | ||
1032 | "320 kbps", | ||
1033 | "384 kbps", | ||
1034 | NULL | ||
1035 | }; | ||
1036 | static const char *mpeg_audio_l3_bitrate[] = { | ||
1037 | "32 kbps", | ||
1038 | "40 kbps", | ||
1039 | "48 kbps", | ||
1040 | "56 kbps", | ||
1041 | "64 kbps", | ||
1042 | "80 kbps", | ||
1043 | "96 kbps", | ||
1044 | "112 kbps", | ||
1045 | "128 kbps", | ||
1046 | "160 kbps", | ||
1047 | "192 kbps", | ||
1048 | "224 kbps", | ||
1049 | "256 kbps", | ||
1050 | "320 kbps", | ||
1051 | NULL | ||
1052 | }; | ||
1053 | static const char *mpeg_audio_mode[] = { | ||
1054 | "Stereo", | ||
1055 | "Joint Stereo", | ||
1056 | "Dual", | ||
1057 | "Mono", | ||
1058 | NULL | ||
1059 | }; | ||
1060 | static const char *mpeg_audio_mode_extension[] = { | ||
1061 | "Bound 4", | ||
1062 | "Bound 8", | ||
1063 | "Bound 12", | ||
1064 | "Bound 16", | ||
1065 | NULL | ||
1066 | }; | ||
1067 | static const char *mpeg_audio_emphasis[] = { | ||
1068 | "No Emphasis", | ||
1069 | "50/15 us", | ||
1070 | "CCITT J17", | ||
1071 | NULL | ||
1072 | }; | ||
1073 | static const char *mpeg_audio_crc[] = { | ||
1074 | "No CRC", | ||
1075 | "16-bit CRC", | ||
1076 | NULL | ||
1077 | }; | ||
1078 | static const char *mpeg_video_encoding[] = { | ||
1079 | "MPEG-1", | ||
1080 | "MPEG-2", | ||
1081 | NULL | ||
1082 | }; | ||
1083 | static const char *mpeg_video_aspect[] = { | ||
1084 | "1x1", | ||
1085 | "4x3", | ||
1086 | "16x9", | ||
1087 | "2.21x1", | ||
1088 | NULL | ||
1089 | }; | ||
1090 | static const char *mpeg_video_bitrate_mode[] = { | ||
1091 | "Variable Bitrate", | ||
1092 | "Constant Bitrate", | ||
1093 | NULL | ||
1094 | }; | ||
1095 | static const char *mpeg_stream_type[] = { | ||
1096 | "MPEG-2 Program Stream", | ||
1097 | "MPEG-2 Transport Stream", | ||
1098 | "MPEG-1 System Stream", | ||
1099 | "MPEG-2 DVD-compatible Stream", | ||
1100 | "MPEG-1 VCD-compatible Stream", | ||
1101 | "MPEG-2 SVCD-compatible Stream", | ||
1102 | NULL | ||
1103 | }; | ||
1104 | |||
1105 | switch (id) { | ||
1106 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | ||
1107 | return mpeg_audio_sampling_freq; | ||
1108 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
1109 | return mpeg_audio_encoding; | ||
1110 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: | ||
1111 | return mpeg_audio_l1_bitrate; | ||
1112 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | ||
1113 | return mpeg_audio_l2_bitrate; | ||
1114 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: | ||
1115 | return mpeg_audio_l3_bitrate; | ||
1116 | case V4L2_CID_MPEG_AUDIO_MODE: | ||
1117 | return mpeg_audio_mode; | ||
1118 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | ||
1119 | return mpeg_audio_mode_extension; | ||
1120 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: | ||
1121 | return mpeg_audio_emphasis; | ||
1122 | case V4L2_CID_MPEG_AUDIO_CRC: | ||
1123 | return mpeg_audio_crc; | ||
1124 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
1125 | return mpeg_video_encoding; | ||
1126 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
1127 | return mpeg_video_aspect; | ||
1128 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
1129 | return mpeg_video_bitrate_mode; | ||
1130 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
1131 | return mpeg_stream_type; | ||
1132 | default: | ||
1133 | return NULL; | ||
1134 | } | ||
1135 | } | ||
1136 | |||
1137 | /* Fill in a struct v4l2_queryctrl */ | ||
1138 | int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) | ||
1139 | { | ||
1140 | const char *name; | ||
1141 | |||
1142 | qctrl->flags = 0; | ||
1143 | switch (qctrl->id) { | ||
1144 | /* USER controls */ | ||
1145 | case V4L2_CID_USER_CLASS: name = "User Controls"; break; | ||
1146 | case V4L2_CID_AUDIO_VOLUME: name = "Volume"; break; | ||
1147 | case V4L2_CID_AUDIO_MUTE: name = "Mute"; break; | ||
1148 | case V4L2_CID_AUDIO_BALANCE: name = "Balance"; break; | ||
1149 | case V4L2_CID_AUDIO_BASS: name = "Bass"; break; | ||
1150 | case V4L2_CID_AUDIO_TREBLE: name = "Treble"; break; | ||
1151 | case V4L2_CID_AUDIO_LOUDNESS: name = "Loudness"; break; | ||
1152 | case V4L2_CID_BRIGHTNESS: name = "Brightness"; break; | ||
1153 | case V4L2_CID_CONTRAST: name = "Contrast"; break; | ||
1154 | case V4L2_CID_SATURATION: name = "Saturation"; break; | ||
1155 | case V4L2_CID_HUE: name = "Hue"; break; | ||
1156 | |||
1157 | /* MPEG controls */ | ||
1158 | case V4L2_CID_MPEG_CLASS: name = "MPEG Encoder Controls"; break; | ||
1159 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: name = "Audio Sampling Frequency"; break; | ||
1160 | case V4L2_CID_MPEG_AUDIO_ENCODING: name = "Audio Encoding Layer"; break; | ||
1161 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: name = "Audio Layer I Bitrate"; break; | ||
1162 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: name = "Audio Layer II Bitrate"; break; | ||
1163 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: name = "Audio Layer III Bitrate"; break; | ||
1164 | case V4L2_CID_MPEG_AUDIO_MODE: name = "Audio Stereo Mode"; break; | ||
1165 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: name = "Audio Stereo Mode Extension"; break; | ||
1166 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: name = "Audio Emphasis"; break; | ||
1167 | case V4L2_CID_MPEG_AUDIO_CRC: name = "Audio CRC"; break; | ||
1168 | case V4L2_CID_MPEG_VIDEO_ENCODING: name = "Video Encoding"; break; | ||
1169 | case V4L2_CID_MPEG_VIDEO_ASPECT: name = "Video Aspect"; break; | ||
1170 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: name = "Video B Frames"; break; | ||
1171 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: name = "Video GOP Size"; break; | ||
1172 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: name = "Video GOP Closure"; break; | ||
1173 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: name = "Video Pulldown"; break; | ||
1174 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: name = "Video Bitrate Mode"; break; | ||
1175 | case V4L2_CID_MPEG_VIDEO_BITRATE: name = "Video Bitrate"; break; | ||
1176 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: name = "Video Peak Bitrate"; break; | ||
1177 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: name = "Video Temporal Decimation"; break; | ||
1178 | case V4L2_CID_MPEG_STREAM_TYPE: name = "Stream Type"; break; | ||
1179 | case V4L2_CID_MPEG_STREAM_PID_PMT: name = "Stream PMT Program ID"; break; | ||
1180 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: name = "Stream Audio Program ID"; break; | ||
1181 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: name = "Stream Video Program ID"; break; | ||
1182 | case V4L2_CID_MPEG_STREAM_PID_PCR: name = "Stream PCR Program ID"; break; | ||
1183 | case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: name = "Stream PES Audio ID"; break; | ||
1184 | case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: name = "Stream PES Video ID"; break; | ||
1185 | |||
1186 | default: | ||
1187 | return -EINVAL; | ||
1188 | } | ||
1189 | switch (qctrl->id) { | ||
1190 | case V4L2_CID_AUDIO_MUTE: | ||
1191 | case V4L2_CID_AUDIO_LOUDNESS: | ||
1192 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: | ||
1193 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: | ||
1194 | qctrl->type = V4L2_CTRL_TYPE_BOOLEAN; | ||
1195 | min = 0; | ||
1196 | max = step = 1; | ||
1197 | break; | ||
1198 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | ||
1199 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
1200 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: | ||
1201 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | ||
1202 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: | ||
1203 | case V4L2_CID_MPEG_AUDIO_MODE: | ||
1204 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | ||
1205 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: | ||
1206 | case V4L2_CID_MPEG_AUDIO_CRC: | ||
1207 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
1208 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
1209 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
1210 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
1211 | qctrl->type = V4L2_CTRL_TYPE_MENU; | ||
1212 | step = 1; | ||
1213 | break; | ||
1214 | case V4L2_CID_USER_CLASS: | ||
1215 | case V4L2_CID_MPEG_CLASS: | ||
1216 | qctrl->type = V4L2_CTRL_TYPE_CTRL_CLASS; | ||
1217 | qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||
1218 | min = max = step = def = 0; | ||
1219 | break; | ||
1220 | default: | ||
1221 | qctrl->type = V4L2_CTRL_TYPE_INTEGER; | ||
1222 | break; | ||
1223 | } | ||
1224 | switch (qctrl->id) { | ||
1225 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
1226 | case V4L2_CID_MPEG_AUDIO_MODE: | ||
1227 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
1228 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: | ||
1229 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
1230 | qctrl->flags |= V4L2_CTRL_FLAG_UPDATE; | ||
1231 | break; | ||
1232 | case V4L2_CID_AUDIO_VOLUME: | ||
1233 | case V4L2_CID_AUDIO_BALANCE: | ||
1234 | case V4L2_CID_AUDIO_BASS: | ||
1235 | case V4L2_CID_AUDIO_TREBLE: | ||
1236 | case V4L2_CID_BRIGHTNESS: | ||
1237 | case V4L2_CID_CONTRAST: | ||
1238 | case V4L2_CID_SATURATION: | ||
1239 | case V4L2_CID_HUE: | ||
1240 | qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; | ||
1241 | break; | ||
1242 | } | ||
1243 | qctrl->minimum = min; | ||
1244 | qctrl->maximum = max; | ||
1245 | qctrl->step = step; | ||
1246 | qctrl->default_value = def; | ||
1247 | qctrl->reserved[0] = qctrl->reserved[1] = 0; | ||
1248 | snprintf(qctrl->name, sizeof(qctrl->name), name); | ||
1249 | return 0; | ||
1250 | } | ||
1251 | |||
1252 | /* Fill in a struct v4l2_queryctrl with standard values based on | ||
1253 | the control ID. */ | ||
1254 | int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) | ||
1255 | { | ||
1256 | switch (qctrl->id) { | ||
1257 | /* USER controls */ | ||
1258 | case V4L2_CID_USER_CLASS: | ||
1259 | case V4L2_CID_MPEG_CLASS: | ||
1260 | return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); | ||
1261 | case V4L2_CID_AUDIO_VOLUME: | ||
1262 | return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 58880); | ||
1263 | case V4L2_CID_AUDIO_MUTE: | ||
1264 | case V4L2_CID_AUDIO_LOUDNESS: | ||
1265 | return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); | ||
1266 | case V4L2_CID_AUDIO_BALANCE: | ||
1267 | case V4L2_CID_AUDIO_BASS: | ||
1268 | case V4L2_CID_AUDIO_TREBLE: | ||
1269 | return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 32768); | ||
1270 | case V4L2_CID_BRIGHTNESS: | ||
1271 | return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128); | ||
1272 | case V4L2_CID_CONTRAST: | ||
1273 | case V4L2_CID_SATURATION: | ||
1274 | return v4l2_ctrl_query_fill(qctrl, 0, 127, 1, 64); | ||
1275 | case V4L2_CID_HUE: | ||
1276 | return v4l2_ctrl_query_fill(qctrl, -128, 127, 1, 0); | ||
1277 | |||
1278 | /* MPEG controls */ | ||
1279 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | ||
1280 | return v4l2_ctrl_query_fill(qctrl, | ||
1281 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100, | ||
1282 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1, | ||
1283 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); | ||
1284 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
1285 | return v4l2_ctrl_query_fill(qctrl, | ||
1286 | V4L2_MPEG_AUDIO_ENCODING_LAYER_1, | ||
1287 | V4L2_MPEG_AUDIO_ENCODING_LAYER_3, 1, | ||
1288 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | ||
1289 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: | ||
1290 | return v4l2_ctrl_query_fill(qctrl, | ||
1291 | V4L2_MPEG_AUDIO_L1_BITRATE_32K, | ||
1292 | V4L2_MPEG_AUDIO_L1_BITRATE_448K, 1, | ||
1293 | V4L2_MPEG_AUDIO_L1_BITRATE_256K); | ||
1294 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | ||
1295 | return v4l2_ctrl_query_fill(qctrl, | ||
1296 | V4L2_MPEG_AUDIO_L2_BITRATE_32K, | ||
1297 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, | ||
1298 | V4L2_MPEG_AUDIO_L2_BITRATE_224K); | ||
1299 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: | ||
1300 | return v4l2_ctrl_query_fill(qctrl, | ||
1301 | V4L2_MPEG_AUDIO_L3_BITRATE_32K, | ||
1302 | V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1, | ||
1303 | V4L2_MPEG_AUDIO_L3_BITRATE_192K); | ||
1304 | case V4L2_CID_MPEG_AUDIO_MODE: | ||
1305 | return v4l2_ctrl_query_fill(qctrl, | ||
1306 | V4L2_MPEG_AUDIO_MODE_STEREO, | ||
1307 | V4L2_MPEG_AUDIO_MODE_MONO, 1, | ||
1308 | V4L2_MPEG_AUDIO_MODE_STEREO); | ||
1309 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | ||
1310 | return v4l2_ctrl_query_fill(qctrl, | ||
1311 | V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, | ||
1312 | V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1, | ||
1313 | V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4); | ||
1314 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: | ||
1315 | return v4l2_ctrl_query_fill(qctrl, | ||
1316 | V4L2_MPEG_AUDIO_EMPHASIS_NONE, | ||
1317 | V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1, | ||
1318 | V4L2_MPEG_AUDIO_EMPHASIS_NONE); | ||
1319 | case V4L2_CID_MPEG_AUDIO_CRC: | ||
1320 | return v4l2_ctrl_query_fill(qctrl, | ||
1321 | V4L2_MPEG_AUDIO_CRC_NONE, | ||
1322 | V4L2_MPEG_AUDIO_CRC_CRC16, 1, | ||
1323 | V4L2_MPEG_AUDIO_CRC_NONE); | ||
1324 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
1325 | return v4l2_ctrl_query_fill(qctrl, | ||
1326 | V4L2_MPEG_VIDEO_ENCODING_MPEG_1, | ||
1327 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, | ||
1328 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2); | ||
1329 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
1330 | return v4l2_ctrl_query_fill(qctrl, | ||
1331 | V4L2_MPEG_VIDEO_ASPECT_1x1, | ||
1332 | V4L2_MPEG_VIDEO_ASPECT_221x100, 1, | ||
1333 | V4L2_MPEG_VIDEO_ASPECT_4x3); | ||
1334 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: | ||
1335 | return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2); | ||
1336 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: | ||
1337 | return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, 12); | ||
1338 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: | ||
1339 | return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1); | ||
1340 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: | ||
1341 | return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); | ||
1342 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
1343 | return v4l2_ctrl_query_fill(qctrl, | ||
1344 | V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, | ||
1345 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, | ||
1346 | V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); | ||
1347 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
1348 | return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); | ||
1349 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
1350 | return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); | ||
1351 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: | ||
1352 | return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); | ||
1353 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
1354 | return v4l2_ctrl_query_fill(qctrl, | ||
1355 | V4L2_MPEG_STREAM_TYPE_MPEG2_PS, | ||
1356 | V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1, | ||
1357 | V4L2_MPEG_STREAM_TYPE_MPEG2_PS); | ||
1358 | case V4L2_CID_MPEG_STREAM_PID_PMT: | ||
1359 | return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16); | ||
1360 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: | ||
1361 | return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260); | ||
1362 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: | ||
1363 | return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256); | ||
1364 | case V4L2_CID_MPEG_STREAM_PID_PCR: | ||
1365 | return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259); | ||
1366 | case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: | ||
1367 | return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); | ||
1368 | case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: | ||
1369 | return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); | ||
1370 | default: | ||
1371 | return -EINVAL; | ||
1372 | } | ||
1373 | } | ||
1374 | |||
1375 | /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and | ||
1376 | the menu. The qctrl pointer may be NULL, in which case it is ignored. */ | ||
1377 | int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, | ||
1378 | const char **menu_items) | ||
1379 | { | ||
1380 | int i; | ||
1381 | |||
1382 | if (menu_items == NULL || | ||
1383 | (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum))) | ||
1384 | return -EINVAL; | ||
1385 | for (i = 0; i < qmenu->index && menu_items[i]; i++) ; | ||
1386 | if (menu_items[i] == NULL || menu_items[i][0] == '\0') | ||
1387 | return -EINVAL; | ||
1388 | snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]); | ||
1389 | qmenu->reserved = 0; | ||
1390 | return 0; | ||
1391 | } | ||
1392 | |||
1393 | /* ctrl_classes points to an array of u32 pointers, the last element is | ||
1394 | a NULL pointer. Each u32 array is a 0-terminated array of control IDs. | ||
1395 | Each array must be sorted low to high and belong to the same control | ||
1396 | class. The array of u32 pointer must also be sorted, from low class IDs | ||
1397 | to high class IDs. | ||
1398 | |||
1399 | This function returns the first ID that follows after the given ID. | ||
1400 | When no more controls are available 0 is returned. */ | ||
1401 | u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) | ||
1402 | { | ||
1403 | u32 ctrl_class; | ||
1404 | const u32 *pctrl; | ||
1405 | |||
1406 | /* if no query is desired, then just return the control ID */ | ||
1407 | if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) | ||
1408 | return id; | ||
1409 | if (ctrl_classes == NULL) | ||
1410 | return 0; | ||
1411 | id &= V4L2_CTRL_ID_MASK; | ||
1412 | ctrl_class = V4L2_CTRL_ID2CLASS(id); | ||
1413 | id++; /* select next control */ | ||
1414 | /* find first class that matches (or is greater than) the class of | ||
1415 | the ID */ | ||
1416 | while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) < ctrl_class) | ||
1417 | ctrl_classes++; | ||
1418 | /* no more classes */ | ||
1419 | if (*ctrl_classes == NULL) | ||
1420 | return 0; | ||
1421 | pctrl = *ctrl_classes; | ||
1422 | /* find first ctrl within the class that is >= ID */ | ||
1423 | while (*pctrl && *pctrl < id) pctrl++; | ||
1424 | if (*pctrl) | ||
1425 | return *pctrl; | ||
1426 | /* we are at the end of the controls of the current class. */ | ||
1427 | /* continue with next class if available */ | ||
1428 | ctrl_classes++; | ||
1429 | if (*ctrl_classes == NULL) | ||
1430 | return 0; | ||
1431 | return **ctrl_classes; | ||
1432 | } | ||
1433 | |||
1434 | /* ----------------------------------------------------------------- */ | ||
1435 | |||
918 | EXPORT_SYMBOL(v4l2_video_std_construct); | 1436 | EXPORT_SYMBOL(v4l2_video_std_construct); |
919 | 1437 | ||
920 | EXPORT_SYMBOL(v4l2_prio_init); | 1438 | EXPORT_SYMBOL(v4l2_prio_init); |
@@ -929,6 +1447,13 @@ EXPORT_SYMBOL(v4l2_type_names); | |||
929 | EXPORT_SYMBOL(v4l_printk_ioctl); | 1447 | EXPORT_SYMBOL(v4l_printk_ioctl); |
930 | EXPORT_SYMBOL(v4l_printk_ioctl_arg); | 1448 | EXPORT_SYMBOL(v4l_printk_ioctl_arg); |
931 | 1449 | ||
1450 | EXPORT_SYMBOL(v4l2_ctrl_next); | ||
1451 | EXPORT_SYMBOL(v4l2_ctrl_check); | ||
1452 | EXPORT_SYMBOL(v4l2_ctrl_get_menu); | ||
1453 | EXPORT_SYMBOL(v4l2_ctrl_query_menu); | ||
1454 | EXPORT_SYMBOL(v4l2_ctrl_query_fill); | ||
1455 | EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); | ||
1456 | |||
932 | /* | 1457 | /* |
933 | * Local variables: | 1458 | * Local variables: |
934 | * c-basic-offset: 8 | 1459 | * c-basic-offset: 8 |
diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c index caf3e7e2f219..7ee8a53cd336 100644 --- a/drivers/media/video/video-buf-dvb.c +++ b/drivers/media/video/video-buf-dvb.c | |||
@@ -135,14 +135,15 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed) | |||
135 | 135 | ||
136 | int videobuf_dvb_register(struct videobuf_dvb *dvb, | 136 | int videobuf_dvb_register(struct videobuf_dvb *dvb, |
137 | struct module *module, | 137 | struct module *module, |
138 | void *adapter_priv) | 138 | void *adapter_priv, |
139 | struct device *device) | ||
139 | { | 140 | { |
140 | int result; | 141 | int result; |
141 | 142 | ||
142 | mutex_init(&dvb->lock); | 143 | mutex_init(&dvb->lock); |
143 | 144 | ||
144 | /* register adapter */ | 145 | /* register adapter */ |
145 | result = dvb_register_adapter(&dvb->adapter, dvb->name, module); | 146 | result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device); |
146 | if (result < 0) { | 147 | if (result < 0) { |
147 | printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", | 148 | printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", |
148 | dvb->name, result); | 149 | dvb->name, result); |
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 5f87dd5f1d0b..2dfa7f23d0ca 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c | |||
@@ -1,20 +1,31 @@ | |||
1 | /* | 1 | /* |
2 | * Video capture interface for Linux | 2 | * Video capture interface for Linux version 2 |
3 | * | 3 | * |
4 | * A generic video device interface for the LINUX operating system | 4 | * A generic video device interface for the LINUX operating system |
5 | * using a set of device structures/vectors for low level operations. | 5 | * using a set of device structures/vectors for low level operations. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License | 8 | * modify it under the terms of the GNU General Public License |
9 | * as published by the Free Software Foundation; either version | 9 | * as published by the Free Software Foundation; either version |
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | * | 11 | * |
12 | * Author: Alan Cox, <alan@redhat.com> | 12 | * Authors: Alan Cox, <alan@redhat.com> (version 1) |
13 | * Mauro Carvalho Chehab <mchehab@infradead.org> (version 2) | ||
13 | * | 14 | * |
14 | * Fixes: 20000516 Claudio Matsuoka <claudio@conectiva.com> | 15 | * Fixes: 20000516 Claudio Matsuoka <claudio@conectiva.com> |
15 | * - Added procfs support | 16 | * - Added procfs support |
16 | */ | 17 | */ |
17 | 18 | ||
19 | #define dbgarg(cmd, fmt, arg...) \ | ||
20 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \ | ||
21 | printk (KERN_DEBUG "%s: ", vfd->name); \ | ||
22 | v4l_printk_ioctl(cmd); \ | ||
23 | printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); | ||
24 | |||
25 | #define dbgarg2(fmt, arg...) \ | ||
26 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \ | ||
27 | printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); | ||
28 | |||
18 | #include <linux/module.h> | 29 | #include <linux/module.h> |
19 | #include <linux/types.h> | 30 | #include <linux/types.h> |
20 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
@@ -30,7 +41,13 @@ | |||
30 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
31 | #include <asm/system.h> | 42 | #include <asm/system.h> |
32 | 43 | ||
44 | #define __OLD_VIDIOC_ /* To allow fixing old calls*/ | ||
45 | #include <linux/videodev2.h> | ||
46 | |||
47 | #ifdef CONFIG_VIDEO_V4L1 | ||
33 | #include <linux/videodev.h> | 48 | #include <linux/videodev.h> |
49 | #endif | ||
50 | #include <media/v4l2-common.h> | ||
34 | 51 | ||
35 | #define VIDEO_NUM_DEVICES 256 | 52 | #define VIDEO_NUM_DEVICES 256 |
36 | #define VIDEO_NAME "video4linux" | 53 | #define VIDEO_NAME "video4linux" |
@@ -41,7 +58,8 @@ | |||
41 | 58 | ||
42 | static ssize_t show_name(struct class_device *cd, char *buf) | 59 | static ssize_t show_name(struct class_device *cd, char *buf) |
43 | { | 60 | { |
44 | struct video_device *vfd = container_of(cd, struct video_device, class_dev); | 61 | struct video_device *vfd = container_of(cd, struct video_device, |
62 | class_dev); | ||
45 | return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name); | 63 | return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name); |
46 | } | 64 | } |
47 | 65 | ||
@@ -62,7 +80,8 @@ void video_device_release(struct video_device *vfd) | |||
62 | 80 | ||
63 | static void video_release(struct class_device *cd) | 81 | static void video_release(struct class_device *cd) |
64 | { | 82 | { |
65 | struct video_device *vfd = container_of(cd, struct video_device, class_dev); | 83 | struct video_device *vfd = container_of(cd, struct video_device, |
84 | class_dev); | ||
66 | 85 | ||
67 | #if 1 | 86 | #if 1 |
68 | /* needed until all drivers are fixed */ | 87 | /* needed until all drivers are fixed */ |
@@ -90,7 +109,7 @@ struct video_device* video_devdata(struct file *file) | |||
90 | } | 109 | } |
91 | 110 | ||
92 | /* | 111 | /* |
93 | * Open a video device. | 112 | * Open a video device - FIXME: Obsoleted |
94 | */ | 113 | */ |
95 | static int video_open(struct inode *inode, struct file *file) | 114 | static int video_open(struct inode *inode, struct file *file) |
96 | { | 115 | { |
@@ -130,6 +149,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
130 | * helper function -- handles userspace copying for ioctl arguments | 149 | * helper function -- handles userspace copying for ioctl arguments |
131 | */ | 150 | */ |
132 | 151 | ||
152 | #ifdef __OLD_VIDIOC_ | ||
133 | static unsigned int | 153 | static unsigned int |
134 | video_fix_command(unsigned int cmd) | 154 | video_fix_command(unsigned int cmd) |
135 | { | 155 | { |
@@ -155,7 +175,11 @@ video_fix_command(unsigned int cmd) | |||
155 | } | 175 | } |
156 | return cmd; | 176 | return cmd; |
157 | } | 177 | } |
178 | #endif | ||
158 | 179 | ||
180 | /* | ||
181 | * Obsolete usercopy function - Should be removed soon | ||
182 | */ | ||
159 | int | 183 | int |
160 | video_usercopy(struct inode *inode, struct file *file, | 184 | video_usercopy(struct inode *inode, struct file *file, |
161 | unsigned int cmd, unsigned long arg, | 185 | unsigned int cmd, unsigned long arg, |
@@ -166,8 +190,15 @@ video_usercopy(struct inode *inode, struct file *file, | |||
166 | void *mbuf = NULL; | 190 | void *mbuf = NULL; |
167 | void *parg = NULL; | 191 | void *parg = NULL; |
168 | int err = -EINVAL; | 192 | int err = -EINVAL; |
193 | int is_ext_ctrl; | ||
194 | size_t ctrls_size = 0; | ||
195 | void __user *user_ptr = NULL; | ||
169 | 196 | ||
197 | #ifdef __OLD_VIDIOC_ | ||
170 | cmd = video_fix_command(cmd); | 198 | cmd = video_fix_command(cmd); |
199 | #endif | ||
200 | is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS || | ||
201 | cmd == VIDIOC_TRY_EXT_CTRLS); | ||
171 | 202 | ||
172 | /* Copy arguments into temp kernel buffer */ | 203 | /* Copy arguments into temp kernel buffer */ |
173 | switch (_IOC_DIR(cmd)) { | 204 | switch (_IOC_DIR(cmd)) { |
@@ -193,14 +224,43 @@ video_usercopy(struct inode *inode, struct file *file, | |||
193 | goto out; | 224 | goto out; |
194 | break; | 225 | break; |
195 | } | 226 | } |
227 | if (is_ext_ctrl) { | ||
228 | struct v4l2_ext_controls *p = parg; | ||
229 | |||
230 | /* In case of an error, tell the caller that it wasn't | ||
231 | a specific control that caused it. */ | ||
232 | p->error_idx = p->count; | ||
233 | user_ptr = (void __user *)p->controls; | ||
234 | if (p->count) { | ||
235 | ctrls_size = sizeof(struct v4l2_ext_control) * p->count; | ||
236 | /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */ | ||
237 | mbuf = kmalloc(ctrls_size, GFP_KERNEL); | ||
238 | err = -ENOMEM; | ||
239 | if (NULL == mbuf) | ||
240 | goto out_ext_ctrl; | ||
241 | err = -EFAULT; | ||
242 | if (copy_from_user(mbuf, user_ptr, ctrls_size)) | ||
243 | goto out_ext_ctrl; | ||
244 | p->controls = mbuf; | ||
245 | } | ||
246 | } | ||
196 | 247 | ||
197 | /* call driver */ | 248 | /* call driver */ |
198 | err = func(inode, file, cmd, parg); | 249 | err = func(inode, file, cmd, parg); |
199 | if (err == -ENOIOCTLCMD) | 250 | if (err == -ENOIOCTLCMD) |
200 | err = -EINVAL; | 251 | err = -EINVAL; |
252 | if (is_ext_ctrl) { | ||
253 | struct v4l2_ext_controls *p = parg; | ||
254 | |||
255 | p->controls = (void *)user_ptr; | ||
256 | if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size)) | ||
257 | err = -EFAULT; | ||
258 | goto out_ext_ctrl; | ||
259 | } | ||
201 | if (err < 0) | 260 | if (err < 0) |
202 | goto out; | 261 | goto out; |
203 | 262 | ||
263 | out_ext_ctrl: | ||
204 | /* Copy results into user buffer */ | 264 | /* Copy results into user buffer */ |
205 | switch (_IOC_DIR(cmd)) | 265 | switch (_IOC_DIR(cmd)) |
206 | { | 266 | { |
@@ -218,6 +278,7 @@ out: | |||
218 | 278 | ||
219 | /* | 279 | /* |
220 | * open/release helper functions -- handle exclusive opens | 280 | * open/release helper functions -- handle exclusive opens |
281 | * Should be removed soon | ||
221 | */ | 282 | */ |
222 | int video_exclusive_open(struct inode *inode, struct file *file) | 283 | int video_exclusive_open(struct inode *inode, struct file *file) |
223 | { | 284 | { |
@@ -242,6 +303,1184 @@ int video_exclusive_release(struct inode *inode, struct file *file) | |||
242 | return 0; | 303 | return 0; |
243 | } | 304 | } |
244 | 305 | ||
306 | static char *v4l2_memory_names[] = { | ||
307 | [V4L2_MEMORY_MMAP] = "mmap", | ||
308 | [V4L2_MEMORY_USERPTR] = "userptr", | ||
309 | [V4L2_MEMORY_OVERLAY] = "overlay", | ||
310 | }; | ||
311 | |||
312 | |||
313 | /* FIXME: Those stuff are replicated also on v4l2-common.c */ | ||
314 | static char *v4l2_type_names_FIXME[] = { | ||
315 | [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", | ||
316 | [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", | ||
317 | [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", | ||
318 | [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", | ||
319 | [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", | ||
320 | [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out", | ||
321 | [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-capture", | ||
322 | [V4L2_BUF_TYPE_PRIVATE] = "private", | ||
323 | }; | ||
324 | |||
325 | static char *v4l2_field_names_FIXME[] = { | ||
326 | [V4L2_FIELD_ANY] = "any", | ||
327 | [V4L2_FIELD_NONE] = "none", | ||
328 | [V4L2_FIELD_TOP] = "top", | ||
329 | [V4L2_FIELD_BOTTOM] = "bottom", | ||
330 | [V4L2_FIELD_INTERLACED] = "interlaced", | ||
331 | [V4L2_FIELD_SEQ_TB] = "seq-tb", | ||
332 | [V4L2_FIELD_SEQ_BT] = "seq-bt", | ||
333 | [V4L2_FIELD_ALTERNATE] = "alternate", | ||
334 | }; | ||
335 | |||
336 | #define prt_names(a,arr) (((a)>=0)&&((a)<ARRAY_SIZE(arr)))?arr[a]:"unknown" | ||
337 | |||
338 | static void dbgbuf(unsigned int cmd, struct video_device *vfd, | ||
339 | struct v4l2_buffer *p) | ||
340 | { | ||
341 | struct v4l2_timecode *tc=&p->timecode; | ||
342 | |||
343 | dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " | ||
344 | "bytesused=%d, flags=0x%08d, " | ||
345 | "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n", | ||
346 | (p->timestamp.tv_sec/3600), | ||
347 | (int)(p->timestamp.tv_sec/60)%60, | ||
348 | (int)(p->timestamp.tv_sec%60), | ||
349 | p->timestamp.tv_usec, | ||
350 | p->index, | ||
351 | prt_names(p->type,v4l2_type_names_FIXME), | ||
352 | p->bytesused,p->flags, | ||
353 | p->field,p->sequence, | ||
354 | prt_names(p->memory,v4l2_memory_names), | ||
355 | p->m.userptr); | ||
356 | dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " | ||
357 | "flags=0x%08d, frames=%d, userbits=0x%08x\n", | ||
358 | tc->hours,tc->minutes,tc->seconds, | ||
359 | tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits); | ||
360 | } | ||
361 | |||
362 | static inline void dbgrect(struct video_device *vfd, char *s, | ||
363 | struct v4l2_rect *r) | ||
364 | { | ||
365 | dbgarg2 ("%sRect start at %dx%d, size= %dx%d\n", s, r->left, r->top, | ||
366 | r->width, r->height); | ||
367 | }; | ||
368 | |||
369 | static inline void v4l_print_pix_fmt (struct video_device *vfd, | ||
370 | struct v4l2_pix_format *fmt) | ||
371 | { | ||
372 | dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, " | ||
373 | "bytesperline=%d sizeimage=%d, colorspace=%d\n", | ||
374 | fmt->width,fmt->height,fmt->pixelformat, | ||
375 | prt_names(fmt->field,v4l2_field_names_FIXME), | ||
376 | fmt->bytesperline,fmt->sizeimage,fmt->colorspace); | ||
377 | }; | ||
378 | |||
379 | |||
380 | static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type) | ||
381 | { | ||
382 | switch (type) { | ||
383 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
384 | if (vfd->vidioc_try_fmt_cap) | ||
385 | return (0); | ||
386 | break; | ||
387 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
388 | if (vfd->vidioc_try_fmt_overlay) | ||
389 | return (0); | ||
390 | break; | ||
391 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
392 | if (vfd->vidioc_try_fmt_vbi) | ||
393 | return (0); | ||
394 | break; | ||
395 | case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: | ||
396 | if (vfd->vidioc_try_fmt_vbi_output) | ||
397 | return (0); | ||
398 | break; | ||
399 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
400 | if (vfd->vidioc_try_fmt_vbi_capture) | ||
401 | return (0); | ||
402 | break; | ||
403 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
404 | if (vfd->vidioc_try_fmt_video_output) | ||
405 | return (0); | ||
406 | break; | ||
407 | case V4L2_BUF_TYPE_VBI_OUTPUT: | ||
408 | if (vfd->vidioc_try_fmt_vbi_output) | ||
409 | return (0); | ||
410 | break; | ||
411 | case V4L2_BUF_TYPE_PRIVATE: | ||
412 | if (vfd->vidioc_try_fmt_type_private) | ||
413 | return (0); | ||
414 | break; | ||
415 | } | ||
416 | return (-EINVAL); | ||
417 | } | ||
418 | |||
419 | static int __video_do_ioctl(struct inode *inode, struct file *file, | ||
420 | unsigned int cmd, void *arg) | ||
421 | { | ||
422 | struct video_device *vfd = video_devdata(file); | ||
423 | void *fh = file->private_data; | ||
424 | int ret = -EINVAL; | ||
425 | |||
426 | if ( (vfd->debug & V4L2_DEBUG_IOCTL) && | ||
427 | !(vfd->debug | V4L2_DEBUG_IOCTL_ARG)) { | ||
428 | v4l_print_ioctl(vfd->name, cmd); | ||
429 | } | ||
430 | |||
431 | switch(cmd) { | ||
432 | /* --- capabilities ------------------------------------------ */ | ||
433 | case VIDIOC_QUERYCAP: | ||
434 | { | ||
435 | struct v4l2_capability *cap = (struct v4l2_capability*)arg; | ||
436 | memset(cap, 0, sizeof(*cap)); | ||
437 | |||
438 | if (!vfd->vidioc_querycap) | ||
439 | break; | ||
440 | |||
441 | ret=vfd->vidioc_querycap(file, fh, cap); | ||
442 | if (!ret) | ||
443 | dbgarg (cmd, "driver=%s, card=%s, bus=%s, " | ||
444 | "version=0x%08x, " | ||
445 | "capabilities=0x%08x\n", | ||
446 | cap->driver,cap->card,cap->bus_info, | ||
447 | cap->version, | ||
448 | cap->capabilities); | ||
449 | break; | ||
450 | } | ||
451 | |||
452 | /* --- priority ------------------------------------------ */ | ||
453 | case VIDIOC_G_PRIORITY: | ||
454 | { | ||
455 | enum v4l2_priority *p=arg; | ||
456 | |||
457 | if (!vfd->vidioc_g_priority) | ||
458 | break; | ||
459 | ret=vfd->vidioc_g_priority(file, fh, p); | ||
460 | if (!ret) | ||
461 | dbgarg(cmd, "priority is %d\n", *p); | ||
462 | break; | ||
463 | } | ||
464 | case VIDIOC_S_PRIORITY: | ||
465 | { | ||
466 | enum v4l2_priority *p=arg; | ||
467 | |||
468 | if (!vfd->vidioc_s_priority) | ||
469 | break; | ||
470 | dbgarg(cmd, "setting priority to %d\n", *p); | ||
471 | ret=vfd->vidioc_s_priority(file, fh, *p); | ||
472 | break; | ||
473 | } | ||
474 | |||
475 | /* --- capture ioctls ---------------------------------------- */ | ||
476 | case VIDIOC_ENUM_FMT: | ||
477 | { | ||
478 | struct v4l2_fmtdesc *f = arg; | ||
479 | enum v4l2_buf_type type; | ||
480 | unsigned int index; | ||
481 | |||
482 | index = f->index; | ||
483 | type = f->type; | ||
484 | memset(f,0,sizeof(*f)); | ||
485 | f->index = index; | ||
486 | f->type = type; | ||
487 | |||
488 | switch (type) { | ||
489 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
490 | if (vfd->vidioc_enum_fmt_cap) | ||
491 | ret=vfd->vidioc_enum_fmt_cap(file, fh, f); | ||
492 | break; | ||
493 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
494 | if (vfd->vidioc_enum_fmt_overlay) | ||
495 | ret=vfd->vidioc_enum_fmt_overlay(file, fh, f); | ||
496 | break; | ||
497 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
498 | if (vfd->vidioc_enum_fmt_vbi) | ||
499 | ret=vfd->vidioc_enum_fmt_vbi(file, fh, f); | ||
500 | break; | ||
501 | case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: | ||
502 | if (vfd->vidioc_enum_fmt_vbi_output) | ||
503 | ret=vfd->vidioc_enum_fmt_vbi_output(file, | ||
504 | fh, f); | ||
505 | break; | ||
506 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
507 | if (vfd->vidioc_enum_fmt_vbi_capture) | ||
508 | ret=vfd->vidioc_enum_fmt_vbi_capture(file, | ||
509 | fh, f); | ||
510 | break; | ||
511 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
512 | if (vfd->vidioc_enum_fmt_video_output) | ||
513 | ret=vfd->vidioc_enum_fmt_video_output(file, | ||
514 | fh, f); | ||
515 | break; | ||
516 | case V4L2_BUF_TYPE_VBI_OUTPUT: | ||
517 | if (vfd->vidioc_enum_fmt_vbi_output) | ||
518 | ret=vfd->vidioc_enum_fmt_vbi_output(file, | ||
519 | fh, f); | ||
520 | break; | ||
521 | case V4L2_BUF_TYPE_PRIVATE: | ||
522 | if (vfd->vidioc_enum_fmt_type_private) | ||
523 | ret=vfd->vidioc_enum_fmt_type_private(file, | ||
524 | fh, f); | ||
525 | break; | ||
526 | } | ||
527 | if (!ret) | ||
528 | dbgarg (cmd, "index=%d, type=%d, flags=%d, " | ||
529 | "description=%s," | ||
530 | " pixelformat=0x%8x\n", | ||
531 | f->index, f->type, f->flags, | ||
532 | f->description, | ||
533 | f->pixelformat); | ||
534 | |||
535 | break; | ||
536 | } | ||
537 | case VIDIOC_G_FMT: | ||
538 | { | ||
539 | struct v4l2_format *f = (struct v4l2_format *)arg; | ||
540 | enum v4l2_buf_type type=f->type; | ||
541 | |||
542 | memset(&f->fmt.pix,0,sizeof(f->fmt.pix)); | ||
543 | f->type=type; | ||
544 | |||
545 | /* FIXME: Should be one dump per type */ | ||
546 | dbgarg (cmd, "type=%s\n", prt_names(type, | ||
547 | v4l2_type_names_FIXME)); | ||
548 | |||
549 | switch (type) { | ||
550 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
551 | if (vfd->vidioc_g_fmt_cap) | ||
552 | ret=vfd->vidioc_g_fmt_cap(file, fh, f); | ||
553 | if (!ret) | ||
554 | v4l_print_pix_fmt(vfd,&f->fmt.pix); | ||
555 | break; | ||
556 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
557 | if (vfd->vidioc_g_fmt_overlay) | ||
558 | ret=vfd->vidioc_g_fmt_overlay(file, fh, f); | ||
559 | break; | ||
560 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
561 | if (vfd->vidioc_g_fmt_vbi) | ||
562 | ret=vfd->vidioc_g_fmt_vbi(file, fh, f); | ||
563 | break; | ||
564 | case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: | ||
565 | if (vfd->vidioc_g_fmt_vbi_output) | ||
566 | ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f); | ||
567 | break; | ||
568 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
569 | if (vfd->vidioc_g_fmt_vbi_capture) | ||
570 | ret=vfd->vidioc_g_fmt_vbi_capture(file, fh, f); | ||
571 | break; | ||
572 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
573 | if (vfd->vidioc_g_fmt_video_output) | ||
574 | ret=vfd->vidioc_g_fmt_video_output(file, | ||
575 | fh, f); | ||
576 | break; | ||
577 | case V4L2_BUF_TYPE_VBI_OUTPUT: | ||
578 | if (vfd->vidioc_g_fmt_vbi_output) | ||
579 | ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f); | ||
580 | break; | ||
581 | case V4L2_BUF_TYPE_PRIVATE: | ||
582 | if (vfd->vidioc_g_fmt_type_private) | ||
583 | ret=vfd->vidioc_g_fmt_type_private(file, | ||
584 | fh, f); | ||
585 | break; | ||
586 | } | ||
587 | |||
588 | break; | ||
589 | } | ||
590 | case VIDIOC_S_FMT: | ||
591 | { | ||
592 | struct v4l2_format *f = (struct v4l2_format *)arg; | ||
593 | |||
594 | /* FIXME: Should be one dump per type */ | ||
595 | dbgarg (cmd, "type=%s\n", prt_names(f->type, | ||
596 | v4l2_type_names_FIXME)); | ||
597 | |||
598 | switch (f->type) { | ||
599 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
600 | v4l_print_pix_fmt(vfd,&f->fmt.pix); | ||
601 | if (vfd->vidioc_s_fmt_cap) | ||
602 | ret=vfd->vidioc_s_fmt_cap(file, fh, f); | ||
603 | break; | ||
604 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
605 | if (vfd->vidioc_s_fmt_overlay) | ||
606 | ret=vfd->vidioc_s_fmt_overlay(file, fh, f); | ||
607 | break; | ||
608 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
609 | if (vfd->vidioc_s_fmt_vbi) | ||
610 | ret=vfd->vidioc_s_fmt_vbi(file, fh, f); | ||
611 | break; | ||
612 | case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: | ||
613 | if (vfd->vidioc_s_fmt_vbi_output) | ||
614 | ret=vfd->vidioc_s_fmt_vbi_output(file, fh, f); | ||
615 | break; | ||
616 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
617 | if (vfd->vidioc_s_fmt_vbi_capture) | ||
618 | ret=vfd->vidioc_s_fmt_vbi_capture(file, fh, f); | ||
619 | break; | ||
620 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
621 | if (vfd->vidioc_s_fmt_video_output) | ||
622 | ret=vfd->vidioc_s_fmt_video_output(file, | ||
623 | fh, f); | ||
624 | break; | ||
625 | case V4L2_BUF_TYPE_VBI_OUTPUT: | ||
626 | if (vfd->vidioc_s_fmt_vbi_output) | ||
627 | ret=vfd->vidioc_s_fmt_vbi_output(file, | ||
628 | fh, f); | ||
629 | break; | ||
630 | case V4L2_BUF_TYPE_PRIVATE: | ||
631 | if (vfd->vidioc_s_fmt_type_private) | ||
632 | ret=vfd->vidioc_s_fmt_type_private(file, | ||
633 | fh, f); | ||
634 | break; | ||
635 | } | ||
636 | break; | ||
637 | } | ||
638 | case VIDIOC_TRY_FMT: | ||
639 | { | ||
640 | struct v4l2_format *f = (struct v4l2_format *)arg; | ||
641 | |||
642 | /* FIXME: Should be one dump per type */ | ||
643 | dbgarg (cmd, "type=%s\n", prt_names(f->type, | ||
644 | v4l2_type_names_FIXME)); | ||
645 | switch (f->type) { | ||
646 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
647 | if (vfd->vidioc_try_fmt_cap) | ||
648 | ret=vfd->vidioc_try_fmt_cap(file, fh, f); | ||
649 | if (!ret) | ||
650 | v4l_print_pix_fmt(vfd,&f->fmt.pix); | ||
651 | break; | ||
652 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
653 | if (vfd->vidioc_try_fmt_overlay) | ||
654 | ret=vfd->vidioc_try_fmt_overlay(file, fh, f); | ||
655 | break; | ||
656 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
657 | if (vfd->vidioc_try_fmt_vbi) | ||
658 | ret=vfd->vidioc_try_fmt_vbi(file, fh, f); | ||
659 | break; | ||
660 | case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: | ||
661 | if (vfd->vidioc_try_fmt_vbi_output) | ||
662 | ret=vfd->vidioc_try_fmt_vbi_output(file, | ||
663 | fh, f); | ||
664 | break; | ||
665 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
666 | if (vfd->vidioc_try_fmt_vbi_capture) | ||
667 | ret=vfd->vidioc_try_fmt_vbi_capture(file, | ||
668 | fh, f); | ||
669 | break; | ||
670 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
671 | if (vfd->vidioc_try_fmt_video_output) | ||
672 | ret=vfd->vidioc_try_fmt_video_output(file, | ||
673 | fh, f); | ||
674 | break; | ||
675 | case V4L2_BUF_TYPE_VBI_OUTPUT: | ||
676 | if (vfd->vidioc_try_fmt_vbi_output) | ||
677 | ret=vfd->vidioc_try_fmt_vbi_output(file, | ||
678 | fh, f); | ||
679 | break; | ||
680 | case V4L2_BUF_TYPE_PRIVATE: | ||
681 | if (vfd->vidioc_try_fmt_type_private) | ||
682 | ret=vfd->vidioc_try_fmt_type_private(file, | ||
683 | fh, f); | ||
684 | break; | ||
685 | } | ||
686 | |||
687 | break; | ||
688 | } | ||
689 | /* FIXME: Those buf reqs could be handled here, | ||
690 | with some changes on videobuf to allow its header to be included at | ||
691 | videodev2.h or being merged at videodev2. | ||
692 | */ | ||
693 | case VIDIOC_REQBUFS: | ||
694 | { | ||
695 | struct v4l2_requestbuffers *p=arg; | ||
696 | |||
697 | if (!vfd->vidioc_reqbufs) | ||
698 | break; | ||
699 | ret = check_fmt (vfd, p->type); | ||
700 | if (ret) | ||
701 | break; | ||
702 | |||
703 | ret=vfd->vidioc_reqbufs(file, fh, p); | ||
704 | dbgarg (cmd, "count=%d, type=%s, memory=%s\n", | ||
705 | p->count, | ||
706 | prt_names(p->type,v4l2_type_names_FIXME), | ||
707 | prt_names(p->memory,v4l2_memory_names)); | ||
708 | break; | ||
709 | } | ||
710 | case VIDIOC_QUERYBUF: | ||
711 | { | ||
712 | struct v4l2_buffer *p=arg; | ||
713 | |||
714 | if (!vfd->vidioc_querybuf) | ||
715 | break; | ||
716 | ret = check_fmt (vfd, p->type); | ||
717 | if (ret) | ||
718 | break; | ||
719 | |||
720 | ret=vfd->vidioc_querybuf(file, fh, p); | ||
721 | if (!ret) | ||
722 | dbgbuf(cmd,vfd,p); | ||
723 | break; | ||
724 | } | ||
725 | case VIDIOC_QBUF: | ||
726 | { | ||
727 | struct v4l2_buffer *p=arg; | ||
728 | |||
729 | if (!vfd->vidioc_qbuf) | ||
730 | break; | ||
731 | ret = check_fmt (vfd, p->type); | ||
732 | if (ret) | ||
733 | break; | ||
734 | |||
735 | ret=vfd->vidioc_qbuf(file, fh, p); | ||
736 | if (!ret) | ||
737 | dbgbuf(cmd,vfd,p); | ||
738 | break; | ||
739 | } | ||
740 | case VIDIOC_DQBUF: | ||
741 | { | ||
742 | struct v4l2_buffer *p=arg; | ||
743 | if (!vfd->vidioc_qbuf) | ||
744 | break; | ||
745 | ret = check_fmt (vfd, p->type); | ||
746 | if (ret) | ||
747 | break; | ||
748 | |||
749 | ret=vfd->vidioc_qbuf(file, fh, p); | ||
750 | if (!ret) | ||
751 | dbgbuf(cmd,vfd,p); | ||
752 | break; | ||
753 | } | ||
754 | case VIDIOC_OVERLAY: | ||
755 | { | ||
756 | int *i = arg; | ||
757 | |||
758 | if (!vfd->vidioc_overlay) | ||
759 | break; | ||
760 | dbgarg (cmd, "value=%d\n",*i); | ||
761 | ret=vfd->vidioc_overlay(file, fh, *i); | ||
762 | break; | ||
763 | } | ||
764 | #ifdef HAVE_V4L1 | ||
765 | /* --- streaming capture ------------------------------------- */ | ||
766 | case VIDIOCGMBUF: | ||
767 | { | ||
768 | struct video_mbuf *p=arg; | ||
769 | |||
770 | memset(p,0,sizeof(p)); | ||
771 | |||
772 | if (!vfd->vidiocgmbuf) | ||
773 | break; | ||
774 | ret=vfd->vidiocgmbuf(file, fh, p); | ||
775 | if (!ret) | ||
776 | dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n", | ||
777 | p->size, p->frames, | ||
778 | (unsigned long)p->offsets); | ||
779 | break; | ||
780 | } | ||
781 | #endif | ||
782 | case VIDIOC_G_FBUF: | ||
783 | { | ||
784 | struct v4l2_framebuffer *p=arg; | ||
785 | if (!vfd->vidioc_g_fbuf) | ||
786 | break; | ||
787 | ret=vfd->vidioc_g_fbuf(file, fh, arg); | ||
788 | if (!ret) { | ||
789 | dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n", | ||
790 | p->capability,p->flags, | ||
791 | (unsigned long)p->base); | ||
792 | v4l_print_pix_fmt (vfd, &p->fmt); | ||
793 | } | ||
794 | break; | ||
795 | } | ||
796 | case VIDIOC_S_FBUF: | ||
797 | { | ||
798 | struct v4l2_framebuffer *p=arg; | ||
799 | if (!vfd->vidioc_s_fbuf) | ||
800 | break; | ||
801 | |||
802 | dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n", | ||
803 | p->capability,p->flags,(unsigned long)p->base); | ||
804 | v4l_print_pix_fmt (vfd, &p->fmt); | ||
805 | ret=vfd->vidioc_s_fbuf(file, fh, arg); | ||
806 | |||
807 | break; | ||
808 | } | ||
809 | case VIDIOC_STREAMON: | ||
810 | { | ||
811 | enum v4l2_buf_type i = *(int *)arg; | ||
812 | if (!vfd->vidioc_streamon) | ||
813 | break; | ||
814 | dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME)); | ||
815 | ret=vfd->vidioc_streamon(file, fh,i); | ||
816 | break; | ||
817 | } | ||
818 | case VIDIOC_STREAMOFF: | ||
819 | { | ||
820 | enum v4l2_buf_type i = *(int *)arg; | ||
821 | |||
822 | if (!vfd->vidioc_streamoff) | ||
823 | break; | ||
824 | dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME)); | ||
825 | ret=vfd->vidioc_streamoff(file, fh, i); | ||
826 | break; | ||
827 | } | ||
828 | /* ---------- tv norms ---------- */ | ||
829 | case VIDIOC_ENUMSTD: | ||
830 | { | ||
831 | struct v4l2_standard *p = arg; | ||
832 | unsigned int index = p->index; | ||
833 | |||
834 | if (!vfd->tvnormsize) { | ||
835 | printk (KERN_WARNING "%s: no TV norms defined!\n", | ||
836 | vfd->name); | ||
837 | break; | ||
838 | } | ||
839 | |||
840 | if (index<=0 || index >= vfd->tvnormsize) { | ||
841 | ret=-EINVAL; | ||
842 | break; | ||
843 | } | ||
844 | v4l2_video_std_construct(p, vfd->tvnorms[p->index].id, | ||
845 | vfd->tvnorms[p->index].name); | ||
846 | p->index = index; | ||
847 | |||
848 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " | ||
849 | "framelines=%d\n", p->index, | ||
850 | (unsigned long long)p->id, p->name, | ||
851 | p->frameperiod.numerator, | ||
852 | p->frameperiod.denominator, | ||
853 | p->framelines); | ||
854 | |||
855 | ret=0; | ||
856 | break; | ||
857 | } | ||
858 | case VIDIOC_G_STD: | ||
859 | { | ||
860 | v4l2_std_id *id = arg; | ||
861 | |||
862 | *id = vfd->current_norm; | ||
863 | |||
864 | dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); | ||
865 | |||
866 | ret=0; | ||
867 | break; | ||
868 | } | ||
869 | case VIDIOC_S_STD: | ||
870 | { | ||
871 | v4l2_std_id *id = arg; | ||
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 | |||
880 | dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); | ||
881 | |||
882 | /* First search for exact match */ | ||
883 | for (i = 0; i < vfd->tvnormsize; i++) | ||
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; | ||
893 | } | ||
894 | |||
895 | /* Calls the specific handler */ | ||
896 | if (vfd->vidioc_s_std) | ||
897 | ret=vfd->vidioc_s_std(file, fh, i); | ||
898 | else | ||
899 | ret=-EINVAL; | ||
900 | |||
901 | /* Updates standard information */ | ||
902 | if (!ret) | ||
903 | vfd->current_norm=*id; | ||
904 | |||
905 | break; | ||
906 | } | ||
907 | case VIDIOC_QUERYSTD: | ||
908 | { | ||
909 | v4l2_std_id *p=arg; | ||
910 | |||
911 | if (!vfd->vidioc_querystd) | ||
912 | break; | ||
913 | ret=vfd->vidioc_querystd(file, fh, arg); | ||
914 | if (!ret) | ||
915 | dbgarg (cmd, "detected std=%Lu\n", | ||
916 | (unsigned long long)*p); | ||
917 | break; | ||
918 | } | ||
919 | /* ------ input switching ---------- */ | ||
920 | /* FIXME: Inputs can be handled inside videodev2 */ | ||
921 | case VIDIOC_ENUMINPUT: | ||
922 | { | ||
923 | struct v4l2_input *p=arg; | ||
924 | int i=p->index; | ||
925 | |||
926 | if (!vfd->vidioc_enum_input) | ||
927 | break; | ||
928 | memset(p, 0, sizeof(*p)); | ||
929 | p->index=i; | ||
930 | |||
931 | ret=vfd->vidioc_enum_input(file, fh, p); | ||
932 | if (!ret) | ||
933 | dbgarg (cmd, "index=%d, name=%s, type=%d, " | ||
934 | "audioset=%d, " | ||
935 | "tuner=%d, std=%Ld, status=%d\n", | ||
936 | p->index,p->name,p->type,p->audioset, | ||
937 | p->tuner, | ||
938 | (unsigned long long)p->std, | ||
939 | p->status); | ||
940 | break; | ||
941 | } | ||
942 | case VIDIOC_G_INPUT: | ||
943 | { | ||
944 | unsigned int *i = arg; | ||
945 | |||
946 | if (!vfd->vidioc_g_input) | ||
947 | break; | ||
948 | ret=vfd->vidioc_g_input(file, fh, i); | ||
949 | if (!ret) | ||
950 | dbgarg (cmd, "value=%d\n",*i); | ||
951 | break; | ||
952 | } | ||
953 | case VIDIOC_S_INPUT: | ||
954 | { | ||
955 | unsigned int *i = arg; | ||
956 | |||
957 | if (!vfd->vidioc_s_input) | ||
958 | break; | ||
959 | dbgarg (cmd, "value=%d\n",*i); | ||
960 | ret=vfd->vidioc_s_input(file, fh, *i); | ||
961 | break; | ||
962 | } | ||
963 | |||
964 | /* ------ output switching ---------- */ | ||
965 | case VIDIOC_G_OUTPUT: | ||
966 | { | ||
967 | unsigned int *i = arg; | ||
968 | |||
969 | if (!vfd->vidioc_g_output) | ||
970 | break; | ||
971 | ret=vfd->vidioc_g_output(file, fh, i); | ||
972 | if (!ret) | ||
973 | dbgarg (cmd, "value=%d\n",*i); | ||
974 | break; | ||
975 | } | ||
976 | case VIDIOC_S_OUTPUT: | ||
977 | { | ||
978 | unsigned int *i = arg; | ||
979 | |||
980 | if (!vfd->vidioc_s_output) | ||
981 | break; | ||
982 | dbgarg (cmd, "value=%d\n",*i); | ||
983 | ret=vfd->vidioc_s_output(file, fh, *i); | ||
984 | break; | ||
985 | } | ||
986 | |||
987 | /* --- controls ---------------------------------------------- */ | ||
988 | case VIDIOC_QUERYCTRL: | ||
989 | { | ||
990 | struct v4l2_queryctrl *p=arg; | ||
991 | |||
992 | if (!vfd->vidioc_queryctrl) | ||
993 | break; | ||
994 | ret=vfd->vidioc_queryctrl(file, fh, p); | ||
995 | |||
996 | if (!ret) | ||
997 | dbgarg (cmd, "id=%d, type=%d, name=%s, " | ||
998 | "min/max=%d/%d," | ||
999 | " step=%d, default=%d, flags=0x%08x\n", | ||
1000 | p->id,p->type,p->name,p->minimum, | ||
1001 | p->maximum,p->step,p->default_value, | ||
1002 | p->flags); | ||
1003 | break; | ||
1004 | } | ||
1005 | case VIDIOC_G_CTRL: | ||
1006 | { | ||
1007 | struct v4l2_control *p = arg; | ||
1008 | |||
1009 | if (!vfd->vidioc_g_ctrl) | ||
1010 | break; | ||
1011 | dbgarg(cmd, "Enum for index=%d\n", p->id); | ||
1012 | |||
1013 | ret=vfd->vidioc_g_ctrl(file, fh, p); | ||
1014 | if (!ret) | ||
1015 | dbgarg2 ( "id=%d, value=%d\n", p->id, p->value); | ||
1016 | break; | ||
1017 | } | ||
1018 | case VIDIOC_S_CTRL: | ||
1019 | { | ||
1020 | struct v4l2_control *p = arg; | ||
1021 | |||
1022 | if (!vfd->vidioc_s_ctrl) | ||
1023 | break; | ||
1024 | dbgarg (cmd, "id=%d, value=%d\n", p->id, p->value); | ||
1025 | |||
1026 | ret=vfd->vidioc_s_ctrl(file, fh, p); | ||
1027 | break; | ||
1028 | } | ||
1029 | case VIDIOC_G_EXT_CTRLS: | ||
1030 | { | ||
1031 | struct v4l2_ext_controls *p = arg; | ||
1032 | |||
1033 | if (vfd->vidioc_g_ext_ctrls) { | ||
1034 | dbgarg(cmd, "count=%d\n", p->count); | ||
1035 | |||
1036 | ret=vfd->vidioc_g_ext_ctrls(file, fh, p); | ||
1037 | } | ||
1038 | break; | ||
1039 | } | ||
1040 | case VIDIOC_S_EXT_CTRLS: | ||
1041 | { | ||
1042 | struct v4l2_ext_controls *p = arg; | ||
1043 | |||
1044 | if (vfd->vidioc_s_ext_ctrls) { | ||
1045 | dbgarg(cmd, "count=%d\n", p->count); | ||
1046 | |||
1047 | ret=vfd->vidioc_s_ext_ctrls(file, fh, p); | ||
1048 | } | ||
1049 | break; | ||
1050 | } | ||
1051 | case VIDIOC_TRY_EXT_CTRLS: | ||
1052 | { | ||
1053 | struct v4l2_ext_controls *p = arg; | ||
1054 | |||
1055 | if (vfd->vidioc_try_ext_ctrls) { | ||
1056 | dbgarg(cmd, "count=%d\n", p->count); | ||
1057 | |||
1058 | ret=vfd->vidioc_try_ext_ctrls(file, fh, p); | ||
1059 | } | ||
1060 | break; | ||
1061 | } | ||
1062 | case VIDIOC_QUERYMENU: | ||
1063 | { | ||
1064 | struct v4l2_querymenu *p=arg; | ||
1065 | if (!vfd->vidioc_querymenu) | ||
1066 | break; | ||
1067 | ret=vfd->vidioc_querymenu(file, fh, p); | ||
1068 | if (!ret) | ||
1069 | dbgarg (cmd, "id=%d, index=%d, name=%s\n", | ||
1070 | p->id,p->index,p->name); | ||
1071 | break; | ||
1072 | } | ||
1073 | /* --- audio ---------------------------------------------- */ | ||
1074 | case VIDIOC_ENUMAUDIO: | ||
1075 | { | ||
1076 | struct v4l2_audio *p=arg; | ||
1077 | |||
1078 | if (!vfd->vidioc_enumaudio) | ||
1079 | break; | ||
1080 | dbgarg(cmd, "Enum for index=%d\n", p->index); | ||
1081 | ret=vfd->vidioc_enumaudio(file, fh, p); | ||
1082 | if (!ret) | ||
1083 | dbgarg2("index=%d, name=%s, capability=%d, " | ||
1084 | "mode=%d\n",p->index,p->name, | ||
1085 | p->capability, p->mode); | ||
1086 | break; | ||
1087 | } | ||
1088 | case VIDIOC_G_AUDIO: | ||
1089 | { | ||
1090 | struct v4l2_audio *p=arg; | ||
1091 | |||
1092 | if (!vfd->vidioc_g_audio) | ||
1093 | break; | ||
1094 | dbgarg(cmd, "Get for index=%d\n", p->index); | ||
1095 | ret=vfd->vidioc_g_audio(file, fh, p); | ||
1096 | if (!ret) | ||
1097 | dbgarg2("index=%d, name=%s, capability=%d, " | ||
1098 | "mode=%d\n",p->index, | ||
1099 | p->name,p->capability, p->mode); | ||
1100 | break; | ||
1101 | } | ||
1102 | case VIDIOC_S_AUDIO: | ||
1103 | { | ||
1104 | struct v4l2_audio *p=arg; | ||
1105 | |||
1106 | if (!vfd->vidioc_s_audio) | ||
1107 | break; | ||
1108 | dbgarg(cmd, "index=%d, name=%s, capability=%d, " | ||
1109 | "mode=%d\n", p->index, p->name, | ||
1110 | p->capability, p->mode); | ||
1111 | ret=vfd->vidioc_s_audio(file, fh, p); | ||
1112 | break; | ||
1113 | } | ||
1114 | case VIDIOC_ENUMAUDOUT: | ||
1115 | { | ||
1116 | struct v4l2_audioout *p=arg; | ||
1117 | |||
1118 | if (!vfd->vidioc_enumaudout) | ||
1119 | break; | ||
1120 | dbgarg(cmd, "Enum for index=%d\n", p->index); | ||
1121 | ret=vfd->vidioc_enumaudout(file, fh, p); | ||
1122 | if (!ret) | ||
1123 | dbgarg2("index=%d, name=%s, capability=%d, " | ||
1124 | "mode=%d\n", p->index, p->name, | ||
1125 | p->capability,p->mode); | ||
1126 | break; | ||
1127 | } | ||
1128 | case VIDIOC_G_AUDOUT: | ||
1129 | { | ||
1130 | struct v4l2_audioout *p=arg; | ||
1131 | |||
1132 | if (!vfd->vidioc_g_audout) | ||
1133 | break; | ||
1134 | dbgarg(cmd, "Enum for index=%d\n", p->index); | ||
1135 | ret=vfd->vidioc_g_audout(file, fh, p); | ||
1136 | if (!ret) | ||
1137 | dbgarg2("index=%d, name=%s, capability=%d, " | ||
1138 | "mode=%d\n", p->index, p->name, | ||
1139 | p->capability,p->mode); | ||
1140 | break; | ||
1141 | } | ||
1142 | case VIDIOC_S_AUDOUT: | ||
1143 | { | ||
1144 | struct v4l2_audioout *p=arg; | ||
1145 | |||
1146 | if (!vfd->vidioc_s_audout) | ||
1147 | break; | ||
1148 | dbgarg(cmd, "index=%d, name=%s, capability=%d, " | ||
1149 | "mode=%d\n", p->index, p->name, | ||
1150 | p->capability,p->mode); | ||
1151 | |||
1152 | ret=vfd->vidioc_s_audout(file, fh, p); | ||
1153 | break; | ||
1154 | } | ||
1155 | case VIDIOC_G_MODULATOR: | ||
1156 | { | ||
1157 | struct v4l2_modulator *p=arg; | ||
1158 | if (!vfd->vidioc_g_modulator) | ||
1159 | break; | ||
1160 | ret=vfd->vidioc_g_modulator(file, fh, p); | ||
1161 | if (!ret) | ||
1162 | dbgarg(cmd, "index=%d, name=%s, " | ||
1163 | "capability=%d, rangelow=%d," | ||
1164 | " rangehigh=%d, txsubchans=%d\n", | ||
1165 | p->index, p->name,p->capability, | ||
1166 | p->rangelow, p->rangehigh, | ||
1167 | p->txsubchans); | ||
1168 | break; | ||
1169 | } | ||
1170 | case VIDIOC_S_MODULATOR: | ||
1171 | { | ||
1172 | struct v4l2_modulator *p=arg; | ||
1173 | if (!vfd->vidioc_s_modulator) | ||
1174 | break; | ||
1175 | dbgarg(cmd, "index=%d, name=%s, capability=%d, " | ||
1176 | "rangelow=%d, rangehigh=%d, txsubchans=%d\n", | ||
1177 | p->index, p->name,p->capability,p->rangelow, | ||
1178 | p->rangehigh,p->txsubchans); | ||
1179 | ret=vfd->vidioc_s_modulator(file, fh, p); | ||
1180 | break; | ||
1181 | } | ||
1182 | case VIDIOC_G_CROP: | ||
1183 | { | ||
1184 | struct v4l2_crop *p=arg; | ||
1185 | if (!vfd->vidioc_g_crop) | ||
1186 | break; | ||
1187 | ret=vfd->vidioc_g_crop(file, fh, p); | ||
1188 | if (!ret) { | ||
1189 | dbgarg(cmd, "type=%d\n", p->type); | ||
1190 | dbgrect(vfd, "", &p->c); | ||
1191 | } | ||
1192 | break; | ||
1193 | } | ||
1194 | case VIDIOC_S_CROP: | ||
1195 | { | ||
1196 | struct v4l2_crop *p=arg; | ||
1197 | if (!vfd->vidioc_s_crop) | ||
1198 | break; | ||
1199 | dbgarg(cmd, "type=%d\n", p->type); | ||
1200 | dbgrect(vfd, "", &p->c); | ||
1201 | ret=vfd->vidioc_s_crop(file, fh, p); | ||
1202 | break; | ||
1203 | } | ||
1204 | case VIDIOC_CROPCAP: | ||
1205 | { | ||
1206 | struct v4l2_cropcap *p=arg; | ||
1207 | /*FIXME: Should also show v4l2_fract pixelaspect */ | ||
1208 | if (!vfd->vidioc_cropcap) | ||
1209 | break; | ||
1210 | dbgarg(cmd, "type=%d\n", p->type); | ||
1211 | dbgrect(vfd, "bounds ", &p->bounds); | ||
1212 | dbgrect(vfd, "defrect ", &p->defrect); | ||
1213 | ret=vfd->vidioc_cropcap(file, fh, p); | ||
1214 | break; | ||
1215 | } | ||
1216 | case VIDIOC_G_MPEGCOMP: | ||
1217 | { | ||
1218 | struct v4l2_mpeg_compression *p=arg; | ||
1219 | |||
1220 | /*FIXME: Several fields not shown */ | ||
1221 | if (!vfd->vidioc_g_mpegcomp) | ||
1222 | break; | ||
1223 | ret=vfd->vidioc_g_mpegcomp(file, fh, p); | ||
1224 | if (!ret) | ||
1225 | dbgarg (cmd, "ts_pid_pmt=%d, ts_pid_audio=%d," | ||
1226 | " ts_pid_video=%d, ts_pid_pcr=%d, " | ||
1227 | "ps_size=%d, au_sample_rate=%d, " | ||
1228 | "au_pesid=%c, vi_frame_rate=%d, " | ||
1229 | "vi_frames_per_gop=%d, " | ||
1230 | "vi_bframes_count=%d, vi_pesid=%c\n", | ||
1231 | p->ts_pid_pmt,p->ts_pid_audio, | ||
1232 | p->ts_pid_video,p->ts_pid_pcr, | ||
1233 | p->ps_size, p->au_sample_rate, | ||
1234 | p->au_pesid, p->vi_frame_rate, | ||
1235 | p->vi_frames_per_gop, | ||
1236 | p->vi_bframes_count, p->vi_pesid); | ||
1237 | break; | ||
1238 | } | ||
1239 | case VIDIOC_S_MPEGCOMP: | ||
1240 | { | ||
1241 | struct v4l2_mpeg_compression *p=arg; | ||
1242 | /*FIXME: Several fields not shown */ | ||
1243 | if (!vfd->vidioc_s_mpegcomp) | ||
1244 | break; | ||
1245 | dbgarg (cmd, "ts_pid_pmt=%d, ts_pid_audio=%d, " | ||
1246 | "ts_pid_video=%d, ts_pid_pcr=%d, ps_size=%d, " | ||
1247 | "au_sample_rate=%d, au_pesid=%c, " | ||
1248 | "vi_frame_rate=%d, vi_frames_per_gop=%d, " | ||
1249 | "vi_bframes_count=%d, vi_pesid=%c\n", | ||
1250 | p->ts_pid_pmt,p->ts_pid_audio, p->ts_pid_video, | ||
1251 | p->ts_pid_pcr, p->ps_size, p->au_sample_rate, | ||
1252 | p->au_pesid, p->vi_frame_rate, | ||
1253 | p->vi_frames_per_gop, p->vi_bframes_count, | ||
1254 | p->vi_pesid); | ||
1255 | ret=vfd->vidioc_s_mpegcomp(file, fh, p); | ||
1256 | break; | ||
1257 | } | ||
1258 | case VIDIOC_G_JPEGCOMP: | ||
1259 | { | ||
1260 | struct v4l2_jpegcompression *p=arg; | ||
1261 | if (!vfd->vidioc_g_jpegcomp) | ||
1262 | break; | ||
1263 | ret=vfd->vidioc_g_jpegcomp(file, fh, p); | ||
1264 | if (!ret) | ||
1265 | dbgarg (cmd, "quality=%d, APPn=%d, " | ||
1266 | "APP_len=%d, COM_len=%d, " | ||
1267 | "jpeg_markers=%d\n", | ||
1268 | p->quality,p->APPn,p->APP_len, | ||
1269 | p->COM_len,p->jpeg_markers); | ||
1270 | break; | ||
1271 | } | ||
1272 | case VIDIOC_S_JPEGCOMP: | ||
1273 | { | ||
1274 | struct v4l2_jpegcompression *p=arg; | ||
1275 | if (!vfd->vidioc_g_jpegcomp) | ||
1276 | break; | ||
1277 | dbgarg (cmd, "quality=%d, APPn=%d, APP_len=%d, " | ||
1278 | "COM_len=%d, jpeg_markers=%d\n", | ||
1279 | p->quality,p->APPn,p->APP_len, | ||
1280 | p->COM_len,p->jpeg_markers); | ||
1281 | ret=vfd->vidioc_s_jpegcomp(file, fh, p); | ||
1282 | break; | ||
1283 | } | ||
1284 | case VIDIOC_G_PARM: | ||
1285 | { | ||
1286 | struct v4l2_streamparm *p=arg; | ||
1287 | if (!vfd->vidioc_g_parm) | ||
1288 | break; | ||
1289 | ret=vfd->vidioc_g_parm(file, fh, p); | ||
1290 | dbgarg (cmd, "type=%d\n", p->type); | ||
1291 | break; | ||
1292 | } | ||
1293 | case VIDIOC_S_PARM: | ||
1294 | { | ||
1295 | struct v4l2_streamparm *p=arg; | ||
1296 | if (!vfd->vidioc_s_parm) | ||
1297 | break; | ||
1298 | dbgarg (cmd, "type=%d\n", p->type); | ||
1299 | ret=vfd->vidioc_s_parm(file, fh, p); | ||
1300 | break; | ||
1301 | } | ||
1302 | case VIDIOC_G_TUNER: | ||
1303 | { | ||
1304 | struct v4l2_tuner *p=arg; | ||
1305 | if (!vfd->vidioc_g_tuner) | ||
1306 | break; | ||
1307 | ret=vfd->vidioc_g_tuner(file, fh, p); | ||
1308 | if (!ret) | ||
1309 | dbgarg (cmd, "index=%d, name=%s, type=%d, " | ||
1310 | "capability=%d, rangelow=%d, " | ||
1311 | "rangehigh=%d, signal=%d, afc=%d, " | ||
1312 | "rxsubchans=%d, audmode=%d\n", | ||
1313 | p->index, p->name, p->type, | ||
1314 | p->capability, p->rangelow, | ||
1315 | p->rangehigh, p->rxsubchans, | ||
1316 | p->audmode, p->signal, p->afc); | ||
1317 | break; | ||
1318 | } | ||
1319 | case VIDIOC_S_TUNER: | ||
1320 | { | ||
1321 | struct v4l2_tuner *p=arg; | ||
1322 | if (!vfd->vidioc_s_tuner) | ||
1323 | break; | ||
1324 | dbgarg (cmd, "index=%d, name=%s, type=%d, " | ||
1325 | "capability=%d, rangelow=%d, rangehigh=%d, " | ||
1326 | "signal=%d, afc=%d, rxsubchans=%d, " | ||
1327 | "audmode=%d\n",p->index, p->name, p->type, | ||
1328 | p->capability, p->rangelow,p->rangehigh, | ||
1329 | p->rxsubchans, p->audmode, p->signal, | ||
1330 | p->afc); | ||
1331 | ret=vfd->vidioc_s_tuner(file, fh, p); | ||
1332 | break; | ||
1333 | } | ||
1334 | case VIDIOC_G_FREQUENCY: | ||
1335 | { | ||
1336 | struct v4l2_frequency *p=arg; | ||
1337 | if (!vfd->vidioc_g_frequency) | ||
1338 | break; | ||
1339 | ret=vfd->vidioc_g_frequency(file, fh, p); | ||
1340 | if (!ret) | ||
1341 | dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", | ||
1342 | p->tuner,p->type,p->frequency); | ||
1343 | break; | ||
1344 | } | ||
1345 | case VIDIOC_S_FREQUENCY: | ||
1346 | { | ||
1347 | struct v4l2_frequency *p=arg; | ||
1348 | if (!vfd->vidioc_s_frequency) | ||
1349 | break; | ||
1350 | dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", | ||
1351 | p->tuner,p->type,p->frequency); | ||
1352 | ret=vfd->vidioc_s_frequency(file, fh, p); | ||
1353 | break; | ||
1354 | } | ||
1355 | case VIDIOC_G_SLICED_VBI_CAP: | ||
1356 | { | ||
1357 | struct v4l2_sliced_vbi_cap *p=arg; | ||
1358 | if (!vfd->vidioc_g_sliced_vbi_cap) | ||
1359 | break; | ||
1360 | ret=vfd->vidioc_g_sliced_vbi_cap(file, fh, p); | ||
1361 | if (!ret) | ||
1362 | dbgarg (cmd, "service_set=%d\n", p->service_set); | ||
1363 | break; | ||
1364 | } | ||
1365 | case VIDIOC_LOG_STATUS: | ||
1366 | { | ||
1367 | if (!vfd->vidioc_log_status) | ||
1368 | break; | ||
1369 | ret=vfd->vidioc_log_status(file, fh); | ||
1370 | break; | ||
1371 | } | ||
1372 | |||
1373 | /* --- Others --------------------------------------------- */ | ||
1374 | |||
1375 | default: | ||
1376 | ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl); | ||
1377 | } | ||
1378 | |||
1379 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { | ||
1380 | if (ret<0) { | ||
1381 | printk ("%s: err:\n", vfd->name); | ||
1382 | v4l_print_ioctl(vfd->name, cmd); | ||
1383 | } | ||
1384 | } | ||
1385 | |||
1386 | return ret; | ||
1387 | } | ||
1388 | |||
1389 | int video_ioctl2 (struct inode *inode, struct file *file, | ||
1390 | unsigned int cmd, unsigned long arg) | ||
1391 | { | ||
1392 | char sbuf[128]; | ||
1393 | void *mbuf = NULL; | ||
1394 | void *parg = NULL; | ||
1395 | int err = -EINVAL; | ||
1396 | int is_ext_ctrl; | ||
1397 | size_t ctrls_size = 0; | ||
1398 | void __user *user_ptr = NULL; | ||
1399 | |||
1400 | #ifdef __OLD_VIDIOC_ | ||
1401 | cmd = video_fix_command(cmd); | ||
1402 | #endif | ||
1403 | is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS || | ||
1404 | cmd == VIDIOC_TRY_EXT_CTRLS); | ||
1405 | |||
1406 | /* Copy arguments into temp kernel buffer */ | ||
1407 | switch (_IOC_DIR(cmd)) { | ||
1408 | case _IOC_NONE: | ||
1409 | parg = NULL; | ||
1410 | break; | ||
1411 | case _IOC_READ: | ||
1412 | case _IOC_WRITE: | ||
1413 | case (_IOC_WRITE | _IOC_READ): | ||
1414 | if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { | ||
1415 | parg = sbuf; | ||
1416 | } else { | ||
1417 | /* too big to allocate from stack */ | ||
1418 | mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); | ||
1419 | if (NULL == mbuf) | ||
1420 | return -ENOMEM; | ||
1421 | parg = mbuf; | ||
1422 | } | ||
1423 | |||
1424 | err = -EFAULT; | ||
1425 | if (_IOC_DIR(cmd) & _IOC_WRITE) | ||
1426 | if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) | ||
1427 | goto out; | ||
1428 | break; | ||
1429 | } | ||
1430 | |||
1431 | if (is_ext_ctrl) { | ||
1432 | struct v4l2_ext_controls *p = parg; | ||
1433 | |||
1434 | /* In case of an error, tell the caller that it wasn't | ||
1435 | a specific control that caused it. */ | ||
1436 | p->error_idx = p->count; | ||
1437 | user_ptr = (void __user *)p->controls; | ||
1438 | if (p->count) { | ||
1439 | ctrls_size = sizeof(struct v4l2_ext_control) * p->count; | ||
1440 | /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */ | ||
1441 | mbuf = kmalloc(ctrls_size, GFP_KERNEL); | ||
1442 | err = -ENOMEM; | ||
1443 | if (NULL == mbuf) | ||
1444 | goto out_ext_ctrl; | ||
1445 | err = -EFAULT; | ||
1446 | if (copy_from_user(mbuf, user_ptr, ctrls_size)) | ||
1447 | goto out_ext_ctrl; | ||
1448 | p->controls = mbuf; | ||
1449 | } | ||
1450 | } | ||
1451 | |||
1452 | /* Handles IOCTL */ | ||
1453 | err = __video_do_ioctl(inode, file, cmd, parg); | ||
1454 | if (err == -ENOIOCTLCMD) | ||
1455 | err = -EINVAL; | ||
1456 | if (is_ext_ctrl) { | ||
1457 | struct v4l2_ext_controls *p = parg; | ||
1458 | |||
1459 | p->controls = (void *)user_ptr; | ||
1460 | if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size)) | ||
1461 | err = -EFAULT; | ||
1462 | goto out_ext_ctrl; | ||
1463 | } | ||
1464 | if (err < 0) | ||
1465 | goto out; | ||
1466 | |||
1467 | out_ext_ctrl: | ||
1468 | /* Copy results into user buffer */ | ||
1469 | switch (_IOC_DIR(cmd)) | ||
1470 | { | ||
1471 | case _IOC_READ: | ||
1472 | case (_IOC_WRITE | _IOC_READ): | ||
1473 | if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) | ||
1474 | err = -EFAULT; | ||
1475 | break; | ||
1476 | } | ||
1477 | |||
1478 | out: | ||
1479 | kfree(mbuf); | ||
1480 | return err; | ||
1481 | } | ||
1482 | |||
1483 | |||
245 | static struct file_operations video_fops; | 1484 | static struct file_operations video_fops; |
246 | 1485 | ||
247 | /** | 1486 | /** |
@@ -371,7 +1610,9 @@ void video_unregister_device(struct video_device *vfd) | |||
371 | mutex_unlock(&videodev_lock); | 1610 | mutex_unlock(&videodev_lock); |
372 | } | 1611 | } |
373 | 1612 | ||
374 | 1613 | /* | |
1614 | * Video fs operations | ||
1615 | */ | ||
375 | static struct file_operations video_fops= | 1616 | static struct file_operations video_fops= |
376 | { | 1617 | { |
377 | .owner = THIS_MODULE, | 1618 | .owner = THIS_MODULE, |
@@ -387,7 +1628,7 @@ static int __init videodev_init(void) | |||
387 | { | 1628 | { |
388 | int ret; | 1629 | int ret; |
389 | 1630 | ||
390 | printk(KERN_INFO "Linux video capture interface: v1.00\n"); | 1631 | printk(KERN_INFO "Linux video capture interface: v2.00\n"); |
391 | if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) { | 1632 | if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) { |
392 | printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR); | 1633 | printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR); |
393 | return -EIO; | 1634 | return -EIO; |
@@ -418,11 +1659,12 @@ EXPORT_SYMBOL(video_devdata); | |||
418 | EXPORT_SYMBOL(video_usercopy); | 1659 | EXPORT_SYMBOL(video_usercopy); |
419 | EXPORT_SYMBOL(video_exclusive_open); | 1660 | EXPORT_SYMBOL(video_exclusive_open); |
420 | EXPORT_SYMBOL(video_exclusive_release); | 1661 | EXPORT_SYMBOL(video_exclusive_release); |
1662 | EXPORT_SYMBOL(video_ioctl2); | ||
421 | EXPORT_SYMBOL(video_device_alloc); | 1663 | EXPORT_SYMBOL(video_device_alloc); |
422 | EXPORT_SYMBOL(video_device_release); | 1664 | EXPORT_SYMBOL(video_device_release); |
423 | 1665 | ||
424 | MODULE_AUTHOR("Alan Cox"); | 1666 | MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>"); |
425 | MODULE_DESCRIPTION("Device registrar for Video4Linux drivers"); | 1667 | MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2"); |
426 | MODULE_LICENSE("GPL"); | 1668 | MODULE_LICENSE("GPL"); |
427 | 1669 | ||
428 | 1670 | ||
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index a8c101494cf5..268e69fdefc6 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <linux/i2c-algo-sgi.h> | 40 | #include <linux/i2c-algo-sgi.h> |
41 | 41 | ||
42 | #include <linux/videodev.h> | 42 | #include <linux/videodev.h> |
43 | #include <linux/videodev2.h> | 43 | #include <media/v4l2-common.h> |
44 | #include <linux/video_decoder.h> | 44 | #include <linux/video_decoder.h> |
45 | #include <linux/mutex.h> | 45 | #include <linux/mutex.h> |
46 | 46 | ||
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 779db26771c0..41d23c8acbd8 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -48,34 +48,15 @@ | |||
48 | 48 | ||
49 | #include "font.h" | 49 | #include "font.h" |
50 | 50 | ||
51 | #ifndef kzalloc | ||
52 | #define kzalloc(size, flags) \ | ||
53 | ({ \ | ||
54 | void *__ret = kmalloc(size, flags); \ | ||
55 | if (__ret) \ | ||
56 | memset(__ret, 0, size); \ | ||
57 | __ret; \ | ||
58 | }) | ||
59 | #endif | ||
60 | |||
61 | MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); | ||
62 | MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); | ||
63 | MODULE_LICENSE("Dual BSD/GPL"); | ||
64 | |||
65 | #define VIVI_MAJOR_VERSION 0 | 51 | #define VIVI_MAJOR_VERSION 0 |
66 | #define VIVI_MINOR_VERSION 4 | 52 | #define VIVI_MINOR_VERSION 4 |
67 | #define VIVI_RELEASE 0 | 53 | #define VIVI_RELEASE 0 |
68 | #define VIVI_VERSION KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) | 54 | #define VIVI_VERSION KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) |
69 | 55 | ||
70 | static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ | 56 | /* Declare static vars that will be used as parameters */ |
71 | module_param(video_nr, int, 0); | 57 | static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ |
72 | 58 | static struct video_device vivi; /* Video device */ | |
73 | static int debug = 0; | 59 | static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ |
74 | module_param(debug, int, 0); | ||
75 | |||
76 | static unsigned int vid_limit = 16; | ||
77 | module_param(vid_limit,int,0644); | ||
78 | MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); | ||
79 | 60 | ||
80 | /* supported controls */ | 61 | /* supported controls */ |
81 | static struct v4l2_queryctrl vivi_qctrl[] = { | 62 | static struct v4l2_queryctrl vivi_qctrl[] = { |
@@ -129,10 +110,10 @@ static struct v4l2_queryctrl vivi_qctrl[] = { | |||
129 | 110 | ||
130 | static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; | 111 | static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; |
131 | 112 | ||
132 | #define dprintk(level,fmt, arg...) \ | 113 | #define dprintk(level,fmt, arg...) \ |
133 | do { \ | 114 | do { \ |
134 | if (debug >= (level)) \ | 115 | if (vivi.debug >= (level)) \ |
135 | printk(KERN_DEBUG "vivi: " fmt , ## arg); \ | 116 | printk(KERN_DEBUG "vivi: " fmt , ## arg); \ |
136 | } while (0) | 117 | } while (0) |
137 | 118 | ||
138 | /* ------------------------------------------------------------------ | 119 | /* ------------------------------------------------------------------ |
@@ -190,7 +171,7 @@ struct vivi_dev { | |||
190 | 171 | ||
191 | /* various device info */ | 172 | /* various device info */ |
192 | unsigned int resources; | 173 | unsigned int resources; |
193 | struct video_device video_dev; | 174 | struct video_device vfd; |
194 | 175 | ||
195 | struct vivi_dmaqueue vidq; | 176 | struct vivi_dmaqueue vidq; |
196 | 177 | ||
@@ -248,7 +229,8 @@ static u8 bars[8][3] = { | |||
248 | #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 | 229 | #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 |
249 | #define TSTAMP_MIN_X 64 | 230 | #define TSTAMP_MIN_X 64 |
250 | 231 | ||
251 | void prep_to_addr(struct sg_to_addr to_addr[],struct videobuf_buffer *vb) | 232 | static void prep_to_addr(struct sg_to_addr to_addr[], |
233 | struct videobuf_buffer *vb) | ||
252 | { | 234 | { |
253 | int i, pos=0; | 235 | int i, pos=0; |
254 | 236 | ||
@@ -259,7 +241,7 @@ void prep_to_addr(struct sg_to_addr to_addr[],struct videobuf_buffer *vb) | |||
259 | } | 241 | } |
260 | } | 242 | } |
261 | 243 | ||
262 | inline int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) | 244 | static int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) |
263 | { | 245 | { |
264 | int p1=0,p2=pages-1,p3=pages/2; | 246 | int p1=0,p2=pages-1,p3=pages/2; |
265 | 247 | ||
@@ -280,8 +262,8 @@ inline int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) | |||
280 | return (p1); | 262 | return (p1); |
281 | } | 263 | } |
282 | 264 | ||
283 | void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, | 265 | static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, |
284 | int hmax, int line, char *timestr) | 266 | int hmax, int line, char *timestr) |
285 | { | 267 | { |
286 | int w,i,j,pos=inipos,pgpos,oldpg,y; | 268 | int w,i,j,pos=inipos,pgpos,oldpg,y; |
287 | char *p,*s,*basep; | 269 | char *p,*s,*basep; |
@@ -491,7 +473,7 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) | |||
491 | dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc); | 473 | dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc); |
492 | } | 474 | } |
493 | 475 | ||
494 | void vivi_sleep(struct vivi_dmaqueue *dma_q) | 476 | static void vivi_sleep(struct vivi_dmaqueue *dma_q) |
495 | { | 477 | { |
496 | int timeout; | 478 | int timeout; |
497 | DECLARE_WAITQUEUE(wait, current); | 479 | DECLARE_WAITQUEUE(wait, current); |
@@ -526,7 +508,7 @@ void vivi_sleep(struct vivi_dmaqueue *dma_q) | |||
526 | try_to_freeze(); | 508 | try_to_freeze(); |
527 | } | 509 | } |
528 | 510 | ||
529 | int vivi_thread(void *data) | 511 | static int vivi_thread(void *data) |
530 | { | 512 | { |
531 | struct vivi_dmaqueue *dma_q=data; | 513 | struct vivi_dmaqueue *dma_q=data; |
532 | 514 | ||
@@ -542,7 +524,7 @@ int vivi_thread(void *data) | |||
542 | return 0; | 524 | return 0; |
543 | } | 525 | } |
544 | 526 | ||
545 | int vivi_start_thread(struct vivi_dmaqueue *dma_q) | 527 | static int vivi_start_thread(struct vivi_dmaqueue *dma_q) |
546 | { | 528 | { |
547 | dma_q->frame=0; | 529 | dma_q->frame=0; |
548 | dma_q->ini_jiffies=jiffies; | 530 | dma_q->ini_jiffies=jiffies; |
@@ -560,7 +542,7 @@ int vivi_start_thread(struct vivi_dmaqueue *dma_q) | |||
560 | return 0; | 542 | return 0; |
561 | } | 543 | } |
562 | 544 | ||
563 | void vivi_stop_thread(struct vivi_dmaqueue *dma_q) | 545 | static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) |
564 | { | 546 | { |
565 | dprintk(1,"%s\n",__FUNCTION__); | 547 | dprintk(1,"%s\n",__FUNCTION__); |
566 | /* shutdown control thread */ | 548 | /* shutdown control thread */ |
@@ -666,8 +648,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) | |||
666 | return 0; | 648 | return 0; |
667 | } | 649 | } |
668 | 650 | ||
669 | void | 651 | static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) |
670 | free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) | ||
671 | { | 652 | { |
672 | dprintk(1,"%s\n",__FUNCTION__); | 653 | dprintk(1,"%s\n",__FUNCTION__); |
673 | 654 | ||
@@ -791,8 +772,8 @@ static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb | |||
791 | free_buffer(vq,buf); | 772 | free_buffer(vq,buf); |
792 | } | 773 | } |
793 | 774 | ||
794 | int vivi_map_sg (void *dev, struct scatterlist *sg, int nents, | 775 | static int vivi_map_sg(void *dev, struct scatterlist *sg, int nents, |
795 | int direction) | 776 | int direction) |
796 | { | 777 | { |
797 | int i; | 778 | int i; |
798 | 779 | ||
@@ -808,15 +789,15 @@ int vivi_map_sg (void *dev, struct scatterlist *sg, int nents, | |||
808 | return nents; | 789 | return nents; |
809 | } | 790 | } |
810 | 791 | ||
811 | int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages, | 792 | static int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages, |
812 | int direction) | 793 | int direction) |
813 | { | 794 | { |
814 | dprintk(1,"%s\n",__FUNCTION__); | 795 | dprintk(1,"%s\n",__FUNCTION__); |
815 | return 0; | 796 | return 0; |
816 | } | 797 | } |
817 | 798 | ||
818 | int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist,int nr_pages, | 799 | static int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist, int nr_pages, |
819 | int direction) | 800 | int direction) |
820 | { | 801 | { |
821 | // dprintk(1,"%s\n",__FUNCTION__); | 802 | // dprintk(1,"%s\n",__FUNCTION__); |
822 | 803 | ||
@@ -840,7 +821,80 @@ static struct videobuf_queue_ops vivi_video_qops = { | |||
840 | IOCTL handling | 821 | IOCTL handling |
841 | ------------------------------------------------------------------*/ | 822 | ------------------------------------------------------------------*/ |
842 | 823 | ||
843 | static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh, | 824 | |
825 | static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) | ||
826 | { | ||
827 | /* is it free? */ | ||
828 | down(&dev->lock); | ||
829 | if (dev->resources) { | ||
830 | /* no, someone else uses it */ | ||
831 | up(&dev->lock); | ||
832 | return 0; | ||
833 | } | ||
834 | /* it's free, grab it */ | ||
835 | dev->resources =1; | ||
836 | dprintk(1,"res: get\n"); | ||
837 | up(&dev->lock); | ||
838 | return 1; | ||
839 | } | ||
840 | |||
841 | static int res_locked(struct vivi_dev *dev) | ||
842 | { | ||
843 | return (dev->resources); | ||
844 | } | ||
845 | |||
846 | static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) | ||
847 | { | ||
848 | down(&dev->lock); | ||
849 | dev->resources = 0; | ||
850 | dprintk(1,"res: put\n"); | ||
851 | up(&dev->lock); | ||
852 | } | ||
853 | |||
854 | /* ------------------------------------------------------------------ | ||
855 | IOCTL vidioc handling | ||
856 | ------------------------------------------------------------------*/ | ||
857 | static int vidioc_querycap (struct file *file, void *priv, | ||
858 | struct v4l2_capability *cap) | ||
859 | { | ||
860 | strcpy(cap->driver, "vivi"); | ||
861 | strcpy(cap->card, "vivi"); | ||
862 | cap->version = VIVI_VERSION; | ||
863 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
864 | V4L2_CAP_STREAMING | | ||
865 | V4L2_CAP_READWRITE; | ||
866 | return 0; | ||
867 | } | ||
868 | |||
869 | static int vidioc_enum_fmt_cap (struct file *file, void *priv, | ||
870 | struct v4l2_fmtdesc *f) | ||
871 | { | ||
872 | if (f->index > 0) | ||
873 | return -EINVAL; | ||
874 | |||
875 | strlcpy(f->description,format.name,sizeof(f->description)); | ||
876 | f->pixelformat = format.fourcc; | ||
877 | return 0; | ||
878 | } | ||
879 | |||
880 | static int vidioc_g_fmt_cap (struct file *file, void *priv, | ||
881 | struct v4l2_format *f) | ||
882 | { | ||
883 | struct vivi_fh *fh=priv; | ||
884 | |||
885 | f->fmt.pix.width = fh->width; | ||
886 | f->fmt.pix.height = fh->height; | ||
887 | f->fmt.pix.field = fh->vb_vidq.field; | ||
888 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | ||
889 | f->fmt.pix.bytesperline = | ||
890 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | ||
891 | f->fmt.pix.sizeimage = | ||
892 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
893 | |||
894 | return (0); | ||
895 | } | ||
896 | |||
897 | static int vidioc_try_fmt_cap (struct file *file, void *priv, | ||
844 | struct v4l2_format *f) | 898 | struct v4l2_format *f) |
845 | { | 899 | { |
846 | struct vivi_fmt *fmt; | 900 | struct vivi_fmt *fmt; |
@@ -848,7 +902,8 @@ static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh, | |||
848 | unsigned int maxw, maxh; | 902 | unsigned int maxw, maxh; |
849 | 903 | ||
850 | if (format.fourcc != f->fmt.pix.pixelformat) { | 904 | if (format.fourcc != f->fmt.pix.pixelformat) { |
851 | dprintk(1,"Fourcc format invalid.\n"); | 905 | dprintk(1,"Fourcc format (0x%08x) invalid. Driver accepts " |
906 | "only 0x%08x\n",f->fmt.pix.pixelformat,format.fourcc); | ||
852 | return -EINVAL; | 907 | return -EINVAL; |
853 | } | 908 | } |
854 | fmt=&format; | 909 | fmt=&format; |
@@ -884,356 +939,196 @@ static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh, | |||
884 | return 0; | 939 | return 0; |
885 | } | 940 | } |
886 | 941 | ||
887 | static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) | 942 | /*FIXME: This seems to be generic enough to be at videodev2 */ |
943 | static int vidioc_s_fmt_cap (struct file *file, void *priv, | ||
944 | struct v4l2_format *f) | ||
888 | { | 945 | { |
889 | /* is it free? */ | 946 | struct vivi_fh *fh=priv; |
890 | down(&dev->lock); | 947 | int ret = vidioc_try_fmt_cap(file,fh,f); |
891 | if (dev->resources) { | 948 | if (ret < 0) |
892 | /* no, someone else uses it */ | 949 | return (ret); |
893 | up(&dev->lock); | 950 | |
894 | return 0; | 951 | fh->fmt = &format; |
895 | } | 952 | fh->width = f->fmt.pix.width; |
896 | /* it's free, grab it */ | 953 | fh->height = f->fmt.pix.height; |
897 | dev->resources =1; | 954 | fh->vb_vidq.field = f->fmt.pix.field; |
898 | dprintk(1,"res: get\n"); | 955 | fh->type = f->type; |
899 | up(&dev->lock); | 956 | |
900 | return 1; | 957 | return (0); |
901 | } | 958 | } |
902 | 959 | ||
903 | static inline int res_locked(struct vivi_dev *dev) | 960 | static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) |
904 | { | 961 | { |
905 | return (dev->resources); | 962 | struct vivi_fh *fh=priv; |
906 | } | ||
907 | 963 | ||
908 | static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) | 964 | return (videobuf_reqbufs(&fh->vb_vidq, p)); |
909 | { | ||
910 | down(&dev->lock); | ||
911 | dev->resources = 0; | ||
912 | dprintk(1,"res: put\n"); | ||
913 | up(&dev->lock); | ||
914 | } | 965 | } |
915 | 966 | ||
916 | static int vivi_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) | 967 | static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) |
917 | { | 968 | { |
918 | struct vivi_fh *fh = file->private_data; | 969 | struct vivi_fh *fh=priv; |
919 | struct vivi_dev *dev = fh->dev; | ||
920 | int ret=0; | ||
921 | 970 | ||
922 | if (debug) { | 971 | return (videobuf_querybuf(&fh->vb_vidq, p)); |
923 | if (_IOC_DIR(cmd) & _IOC_WRITE) | 972 | } |
924 | v4l_printk_ioctl_arg("vivi(w)",cmd, arg); | ||
925 | else if (!_IOC_DIR(cmd) & _IOC_READ) { | ||
926 | v4l_print_ioctl("vivi", cmd); | ||
927 | } | ||
928 | } | ||
929 | 973 | ||
930 | switch(cmd) { | 974 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) |
931 | /* --- capabilities ------------------------------------------ */ | 975 | { |
932 | case VIDIOC_QUERYCAP: | 976 | struct vivi_fh *fh=priv; |
933 | { | ||
934 | struct v4l2_capability *cap = (struct v4l2_capability*)arg; | ||
935 | |||
936 | memset(cap, 0, sizeof(*cap)); | ||
937 | |||
938 | strcpy(cap->driver, "vivi"); | ||
939 | strcpy(cap->card, "vivi"); | ||
940 | cap->version = VIVI_VERSION; | ||
941 | cap->capabilities = | ||
942 | V4L2_CAP_VIDEO_CAPTURE | | ||
943 | V4L2_CAP_STREAMING | | ||
944 | V4L2_CAP_READWRITE; | ||
945 | break; | ||
946 | } | ||
947 | /* --- capture ioctls ---------------------------------------- */ | ||
948 | case VIDIOC_ENUM_FMT: | ||
949 | { | ||
950 | struct v4l2_fmtdesc *f = arg; | ||
951 | enum v4l2_buf_type type; | ||
952 | unsigned int index; | ||
953 | 977 | ||
954 | index = f->index; | 978 | return (videobuf_qbuf(&fh->vb_vidq, p)); |
955 | type = f->type; | 979 | } |
956 | 980 | ||
957 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 981 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) |
958 | ret=-EINVAL; | 982 | { |
959 | break; | 983 | struct vivi_fh *fh=priv; |
960 | } | ||
961 | 984 | ||
962 | switch (type) { | 985 | return (videobuf_dqbuf(&fh->vb_vidq, p, |
963 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 986 | file->f_flags & O_NONBLOCK)); |
964 | if (index > 0){ | 987 | } |
965 | ret=-EINVAL; | ||
966 | break; | ||
967 | } | ||
968 | memset(f,0,sizeof(*f)); | ||
969 | 988 | ||
970 | f->index = index; | 989 | #ifdef HAVE_V4L1 |
971 | f->type = type; | 990 | static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) |
972 | strlcpy(f->description,format.name,sizeof(f->description)); | 991 | { |
973 | f->pixelformat = format.fourcc; | 992 | struct vivi_fh *fh=priv; |
974 | break; | 993 | struct videobuf_queue *q=&fh->vb_vidq; |
975 | default: | 994 | struct v4l2_requestbuffers req; |
976 | ret=-EINVAL; | 995 | unsigned int i, ret; |
977 | } | 996 | |
978 | break; | 997 | req.type = q->type; |
998 | req.count = 8; | ||
999 | req.memory = V4L2_MEMORY_MMAP; | ||
1000 | ret = videobuf_reqbufs(q,&req); | ||
1001 | if (ret < 0) | ||
1002 | return (ret); | ||
1003 | |||
1004 | mbuf->frames = req.count; | ||
1005 | mbuf->size = 0; | ||
1006 | for (i = 0; i < mbuf->frames; i++) { | ||
1007 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
1008 | mbuf->size += q->bufs[i]->bsize; | ||
979 | } | 1009 | } |
980 | case VIDIOC_G_FMT: | 1010 | return (0); |
981 | { | 1011 | } |
982 | struct v4l2_format *f = (struct v4l2_format *)arg; | 1012 | #endif |
983 | 1013 | ||
984 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1014 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
985 | ret=-EINVAL; | 1015 | { |
986 | break; | 1016 | struct vivi_fh *fh=priv; |
987 | } | 1017 | struct vivi_dev *dev = fh->dev; |
988 | 1018 | ||
989 | memset(&f->fmt.pix,0,sizeof(f->fmt.pix)); | 1019 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
990 | f->fmt.pix.width = fh->width; | 1020 | return -EINVAL; |
991 | f->fmt.pix.height = fh->height; | 1021 | if (i != fh->type) |
992 | f->fmt.pix.field = fh->vb_vidq.field; | 1022 | return -EINVAL; |
993 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | ||
994 | f->fmt.pix.bytesperline = | ||
995 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | ||
996 | f->fmt.pix.sizeimage = | ||
997 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
998 | break; | ||
999 | } | ||
1000 | case VIDIOC_S_FMT: | ||
1001 | { | ||
1002 | struct v4l2_format *f = arg; | ||
1003 | 1023 | ||
1004 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1024 | if (!res_get(dev,fh)) |
1005 | dprintk(1,"Only capture supported.\n"); | 1025 | return -EBUSY; |
1006 | ret=-EINVAL; | 1026 | return (videobuf_streamon(&fh->vb_vidq)); |
1007 | break; | 1027 | } |
1008 | } | ||
1009 | 1028 | ||
1010 | ret = vivi_try_fmt(dev,fh,f); | 1029 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) |
1011 | if (ret < 0) | 1030 | { |
1012 | break; | 1031 | struct vivi_fh *fh=priv; |
1032 | struct vivi_dev *dev = fh->dev; | ||
1013 | 1033 | ||
1014 | fh->fmt = &format; | 1034 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1015 | fh->width = f->fmt.pix.width; | 1035 | return -EINVAL; |
1016 | fh->height = f->fmt.pix.height; | 1036 | if (i != fh->type) |
1017 | fh->vb_vidq.field = f->fmt.pix.field; | 1037 | return -EINVAL; |
1018 | fh->type = f->type; | ||
1019 | 1038 | ||
1020 | break; | 1039 | videobuf_streamoff(&fh->vb_vidq); |
1021 | } | 1040 | res_free(dev,fh); |
1022 | case VIDIOC_TRY_FMT: | ||
1023 | { | ||
1024 | struct v4l2_format *f = arg; | ||
1025 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1026 | ret=-EINVAL; | ||
1027 | break; | ||
1028 | } | ||
1029 | 1041 | ||
1030 | ret=vivi_try_fmt(dev,fh,f); | 1042 | return (0); |
1031 | break; | 1043 | } |
1032 | } | 1044 | |
1033 | case VIDIOC_REQBUFS: | 1045 | static struct v4l2_tvnorm tvnorms[] = { |
1034 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1035 | ret=-EINVAL; | ||
1036 | break; | ||
1037 | } | ||
1038 | ret=videobuf_reqbufs(&fh->vb_vidq, arg); | ||
1039 | break; | ||
1040 | case VIDIOC_QUERYBUF: | ||
1041 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1042 | ret=-EINVAL; | ||
1043 | break; | ||
1044 | } | ||
1045 | ret=videobuf_querybuf(&fh->vb_vidq, arg); | ||
1046 | break; | ||
1047 | case VIDIOC_QBUF: | ||
1048 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1049 | ret=-EINVAL; | ||
1050 | break; | ||
1051 | } | ||
1052 | ret=videobuf_qbuf(&fh->vb_vidq, arg); | ||
1053 | break; | ||
1054 | case VIDIOC_DQBUF: | ||
1055 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1056 | ret=-EINVAL; | ||
1057 | break; | ||
1058 | } | ||
1059 | ret=videobuf_dqbuf(&fh->vb_vidq, arg, | ||
1060 | file->f_flags & O_NONBLOCK); | ||
1061 | break; | ||
1062 | #ifdef HAVE_V4L1 | ||
1063 | /* --- streaming capture ------------------------------------- */ | ||
1064 | case VIDIOCGMBUF: | ||
1065 | { | ||
1066 | struct video_mbuf *mbuf = arg; | ||
1067 | struct videobuf_queue *q=&fh->vb_vidq; | ||
1068 | struct v4l2_requestbuffers req; | ||
1069 | unsigned int i; | ||
1070 | |||
1071 | memset(&req,0,sizeof(req)); | ||
1072 | req.type = q->type; | ||
1073 | req.count = 8; | ||
1074 | req.memory = V4L2_MEMORY_MMAP; | ||
1075 | ret = videobuf_reqbufs(q,&req); | ||
1076 | if (ret < 0) | ||
1077 | break; | ||
1078 | memset(mbuf,0,sizeof(*mbuf)); | ||
1079 | mbuf->frames = req.count; | ||
1080 | mbuf->size = 0; | ||
1081 | for (i = 0; i < mbuf->frames; i++) { | ||
1082 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
1083 | mbuf->size += q->bufs[i]->bsize; | ||
1084 | } | ||
1085 | break; | ||
1086 | } | ||
1087 | #endif | ||
1088 | case VIDIOC_STREAMON: | ||
1089 | { | ||
1090 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1091 | return -EINVAL; | ||
1092 | if (!res_get(dev,fh)) | ||
1093 | return -EBUSY; | ||
1094 | ret=videobuf_streamon(&fh->vb_vidq); | ||
1095 | break; | ||
1096 | } | ||
1097 | case VIDIOC_STREAMOFF: | ||
1098 | { | 1046 | { |
1099 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1047 | .name = "NTSC-M", |
1100 | ret=-EINVAL; | 1048 | .id = V4L2_STD_NTSC_M, |
1101 | break; | ||
1102 | } | ||
1103 | ret = videobuf_streamoff(&fh->vb_vidq); | ||
1104 | if (ret < 0) | ||
1105 | break; | ||
1106 | res_free(dev,fh); | ||
1107 | break; | ||
1108 | } | 1049 | } |
1109 | /* ---------- tv norms ---------- */ | 1050 | }; |
1110 | case VIDIOC_ENUMSTD: | ||
1111 | { | ||
1112 | struct v4l2_standard *e = arg; | ||
1113 | 1051 | ||
1114 | if (e->index>0) { | 1052 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a) |
1115 | ret=-EINVAL; | 1053 | { |
1116 | break; | ||
1117 | } | ||
1118 | ret = v4l2_video_std_construct(e, V4L2_STD_NTSC_M, "NTSC-M"); | ||
1119 | 1054 | ||
1120 | /* Allows vivi to use different fps from video std */ | 1055 | return 0; |
1121 | e->frameperiod.numerator = WAKE_NUMERATOR; | 1056 | } |
1122 | e->frameperiod.denominator = WAKE_DENOMINATOR; | ||
1123 | 1057 | ||
1124 | break; | 1058 | /* only one input in this sample driver */ |
1125 | } | 1059 | static int vidioc_enum_input (struct file *file, void *priv, |
1126 | case VIDIOC_G_STD: | 1060 | struct v4l2_input *inp) |
1127 | { | 1061 | { |
1128 | v4l2_std_id *id = arg; | 1062 | if (inp->index != 0) |
1063 | return -EINVAL; | ||
1129 | 1064 | ||
1130 | *id = V4L2_STD_NTSC_M; | 1065 | inp->type = V4L2_INPUT_TYPE_CAMERA; |
1131 | break; | 1066 | inp->std = V4L2_STD_NTSC_M; |
1132 | } | 1067 | strcpy(inp->name,"Camera"); |
1133 | case VIDIOC_S_STD: | ||
1134 | { | ||
1135 | break; | ||
1136 | } | ||
1137 | /* ------ input switching ---------- */ | ||
1138 | case VIDIOC_ENUMINPUT: | ||
1139 | { /* only one input in this sample driver */ | ||
1140 | struct v4l2_input *inp = arg; | ||
1141 | 1068 | ||
1142 | if (inp->index != 0) { | 1069 | return (0); |
1143 | ret=-EINVAL; | 1070 | } |
1144 | break; | ||
1145 | } | ||
1146 | memset(inp, 0, sizeof(*inp)); | ||
1147 | 1071 | ||
1148 | inp->index = 0; | 1072 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) |
1149 | inp->type = V4L2_INPUT_TYPE_CAMERA; | 1073 | { |
1150 | inp->std = V4L2_STD_NTSC_M; | 1074 | *i = 0; |
1151 | strcpy(inp->name,"Camera"); | ||
1152 | break; | ||
1153 | } | ||
1154 | case VIDIOC_G_INPUT: | ||
1155 | { | ||
1156 | unsigned int *i = arg; | ||
1157 | 1075 | ||
1158 | *i = 0; | 1076 | return (0); |
1159 | break; | 1077 | } |
1160 | } | 1078 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) |
1161 | case VIDIOC_S_INPUT: | 1079 | { |
1162 | { | 1080 | if (i > 0) |
1163 | unsigned int *i = arg; | 1081 | return -EINVAL; |
1164 | 1082 | ||
1165 | if (*i > 0) | 1083 | return (0); |
1166 | ret=-EINVAL; | 1084 | } |
1167 | break; | ||
1168 | } | ||
1169 | 1085 | ||
1170 | /* --- controls ---------------------------------------------- */ | 1086 | /* --- controls ---------------------------------------------- */ |
1171 | case VIDIOC_QUERYCTRL: | 1087 | static int vidioc_queryctrl (struct file *file, void *priv, |
1172 | { | 1088 | struct v4l2_queryctrl *qc) |
1173 | struct v4l2_queryctrl *qc = arg; | 1089 | { |
1174 | int i; | 1090 | int i; |
1175 | |||
1176 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1177 | if (qc->id && qc->id == vivi_qctrl[i].id) { | ||
1178 | memcpy(qc, &(vivi_qctrl[i]), | ||
1179 | sizeof(*qc)); | ||
1180 | break; | ||
1181 | } | ||
1182 | 1091 | ||
1183 | ret=-EINVAL; | 1092 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) |
1184 | break; | 1093 | if (qc->id && qc->id == vivi_qctrl[i].id) { |
1185 | } | 1094 | memcpy(qc, &(vivi_qctrl[i]), |
1186 | case VIDIOC_G_CTRL: | 1095 | sizeof(*qc)); |
1187 | { | 1096 | return (0); |
1188 | struct v4l2_control *ctrl = arg; | 1097 | } |
1189 | int i; | ||
1190 | 1098 | ||
1191 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | 1099 | return -EINVAL; |
1192 | if (ctrl->id == vivi_qctrl[i].id) { | 1100 | } |
1193 | ctrl->value=qctl_regs[i]; | ||
1194 | break; | ||
1195 | } | ||
1196 | 1101 | ||
1197 | ret=-EINVAL; | 1102 | static int vidioc_g_ctrl (struct file *file, void *priv, |
1198 | break; | 1103 | struct v4l2_control *ctrl) |
1199 | } | 1104 | { |
1200 | case VIDIOC_S_CTRL: | 1105 | int i; |
1201 | { | ||
1202 | struct v4l2_control *ctrl = arg; | ||
1203 | int i; | ||
1204 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1205 | if (ctrl->id == vivi_qctrl[i].id) { | ||
1206 | if (ctrl->value < | ||
1207 | vivi_qctrl[i].minimum | ||
1208 | || ctrl->value > | ||
1209 | vivi_qctrl[i].maximum) { | ||
1210 | ret=-ERANGE; | ||
1211 | break; | ||
1212 | } | ||
1213 | qctl_regs[i]=ctrl->value; | ||
1214 | break; | ||
1215 | } | ||
1216 | ret=-EINVAL; | ||
1217 | break; | ||
1218 | } | ||
1219 | default: | ||
1220 | ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,vivi_do_ioctl); | ||
1221 | } | ||
1222 | 1106 | ||
1223 | if (debug) { | 1107 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) |
1224 | if (ret<0) { | 1108 | if (ctrl->id == vivi_qctrl[i].id) { |
1225 | v4l_print_ioctl("vivi(err)", cmd); | 1109 | ctrl->value=qctl_regs[i]; |
1226 | dprintk(1,"errcode=%d\n",ret); | 1110 | return (0); |
1227 | } else if (_IOC_DIR(cmd) & _IOC_READ) | 1111 | } |
1228 | v4l_printk_ioctl_arg("vivi(r)",cmd, arg); | ||
1229 | } | ||
1230 | 1112 | ||
1231 | return ret; | 1113 | return -EINVAL; |
1232 | } | 1114 | } |
1233 | 1115 | static int vidioc_s_ctrl (struct file *file, void *priv, | |
1234 | static int vivi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 1116 | struct v4l2_control *ctrl) |
1235 | { | 1117 | { |
1236 | return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl); | 1118 | int i; |
1119 | |||
1120 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1121 | if (ctrl->id == vivi_qctrl[i].id) { | ||
1122 | if (ctrl->value < | ||
1123 | vivi_qctrl[i].minimum | ||
1124 | || ctrl->value > | ||
1125 | vivi_qctrl[i].maximum) { | ||
1126 | return (-ERANGE); | ||
1127 | } | ||
1128 | qctl_regs[i]=ctrl->value; | ||
1129 | return (0); | ||
1130 | } | ||
1131 | return -EINVAL; | ||
1237 | } | 1132 | } |
1238 | 1133 | ||
1239 | /* ------------------------------------------------------------------ | 1134 | /* ------------------------------------------------------------------ |
@@ -1255,7 +1150,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1255 | 1150 | ||
1256 | list_for_each(list,&vivi_devlist) { | 1151 | list_for_each(list,&vivi_devlist) { |
1257 | h = list_entry(list, struct vivi_dev, vivi_devlist); | 1152 | h = list_entry(list, struct vivi_dev, vivi_devlist); |
1258 | if (h->video_dev.minor == minor) { | 1153 | if (h->vfd.minor == minor) { |
1259 | dev = h; | 1154 | dev = h; |
1260 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1155 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1261 | } | 1156 | } |
@@ -1264,6 +1159,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1264 | return -ENODEV; | 1159 | return -ENODEV; |
1265 | 1160 | ||
1266 | 1161 | ||
1162 | |||
1267 | /* If more than one user, mutex should be added */ | 1163 | /* If more than one user, mutex should be added */ |
1268 | dev->users++; | 1164 | dev->users++; |
1269 | 1165 | ||
@@ -1279,6 +1175,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1279 | 1175 | ||
1280 | file->private_data = fh; | 1176 | file->private_data = fh; |
1281 | fh->dev = dev; | 1177 | fh->dev = dev; |
1178 | |||
1282 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1179 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1283 | fh->fmt = &format; | 1180 | fh->fmt = &format; |
1284 | fh->width = 640; | 1181 | fh->width = 640; |
@@ -1314,7 +1211,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1314 | static ssize_t | 1211 | static ssize_t |
1315 | vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | 1212 | vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) |
1316 | { | 1213 | { |
1317 | struct vivi_fh *fh = file->private_data; | 1214 | struct vivi_fh *fh = file->private_data; |
1318 | 1215 | ||
1319 | if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1216 | if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1320 | if (res_locked(fh->dev)) | 1217 | if (res_locked(fh->dev)) |
@@ -1328,8 +1225,8 @@ vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | |||
1328 | static unsigned int | 1225 | static unsigned int |
1329 | vivi_poll(struct file *file, struct poll_table_struct *wait) | 1226 | vivi_poll(struct file *file, struct poll_table_struct *wait) |
1330 | { | 1227 | { |
1331 | struct vivi_fh *fh = file->private_data; | 1228 | struct vivi_fh *fh = file->private_data; |
1332 | struct vivi_buffer *buf; | 1229 | struct vivi_buffer *buf; |
1333 | 1230 | ||
1334 | dprintk(1,"%s\n",__FUNCTION__); | 1231 | dprintk(1,"%s\n",__FUNCTION__); |
1335 | 1232 | ||
@@ -1358,8 +1255,8 @@ vivi_poll(struct file *file, struct poll_table_struct *wait) | |||
1358 | 1255 | ||
1359 | static int vivi_release(struct inode *inode, struct file *file) | 1256 | static int vivi_release(struct inode *inode, struct file *file) |
1360 | { | 1257 | { |
1361 | struct vivi_fh *fh = file->private_data; | 1258 | struct vivi_fh *fh = file->private_data; |
1362 | struct vivi_dev *dev = fh->dev; | 1259 | struct vivi_dev *dev = fh->dev; |
1363 | struct vivi_dmaqueue *vidq = &dev->vidq; | 1260 | struct vivi_dmaqueue *vidq = &dev->vidq; |
1364 | 1261 | ||
1365 | int minor = iminor(inode); | 1262 | int minor = iminor(inode); |
@@ -1379,7 +1276,7 @@ static int vivi_release(struct inode *inode, struct file *file) | |||
1379 | static int | 1276 | static int |
1380 | vivi_mmap(struct file *file, struct vm_area_struct * vma) | 1277 | vivi_mmap(struct file *file, struct vm_area_struct * vma) |
1381 | { | 1278 | { |
1382 | struct vivi_fh *fh = file->private_data; | 1279 | struct vivi_fh *fh = file->private_data; |
1383 | int ret; | 1280 | int ret; |
1384 | 1281 | ||
1385 | dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma); | 1282 | dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma); |
@@ -1400,20 +1297,44 @@ static struct file_operations vivi_fops = { | |||
1400 | .release = vivi_release, | 1297 | .release = vivi_release, |
1401 | .read = vivi_read, | 1298 | .read = vivi_read, |
1402 | .poll = vivi_poll, | 1299 | .poll = vivi_poll, |
1403 | .ioctl = vivi_ioctl, | 1300 | .ioctl = video_ioctl2, /* V4L2 ioctl handler */ |
1404 | .mmap = vivi_mmap, | 1301 | .mmap = vivi_mmap, |
1405 | .llseek = no_llseek, | 1302 | .llseek = no_llseek, |
1406 | }; | 1303 | }; |
1407 | 1304 | ||
1408 | static struct video_device vivi = { | 1305 | static struct video_device vivi = { |
1409 | .name = "VTM Virtual Video Capture Board", | 1306 | .name = "vivi", |
1410 | .type = VID_TYPE_CAPTURE, | 1307 | .type = VID_TYPE_CAPTURE, |
1411 | .hardware = 0, | 1308 | .hardware = 0, |
1412 | .fops = &vivi_fops, | 1309 | .fops = &vivi_fops, |
1413 | .minor = -1, | 1310 | .minor = -1, |
1414 | // .release = video_device_release, | 1311 | // .release = video_device_release, |
1312 | |||
1313 | .vidioc_querycap = vidioc_querycap, | ||
1314 | .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, | ||
1315 | .vidioc_g_fmt_cap = vidioc_g_fmt_cap, | ||
1316 | .vidioc_try_fmt_cap = vidioc_try_fmt_cap, | ||
1317 | .vidioc_s_fmt_cap = vidioc_s_fmt_cap, | ||
1318 | .vidioc_reqbufs = vidioc_reqbufs, | ||
1319 | .vidioc_querybuf = vidioc_querybuf, | ||
1320 | .vidioc_qbuf = vidioc_qbuf, | ||
1321 | .vidioc_dqbuf = vidioc_dqbuf, | ||
1322 | .vidioc_s_std = vidioc_s_std, | ||
1323 | .vidioc_enum_input = vidioc_enum_input, | ||
1324 | .vidioc_g_input = vidioc_g_input, | ||
1325 | .vidioc_s_input = vidioc_s_input, | ||
1326 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1327 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1328 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1329 | .vidioc_streamon = vidioc_streamon, | ||
1330 | .vidioc_streamoff = vidioc_streamoff, | ||
1331 | #ifdef HAVE_V4L1 | ||
1332 | .vidiocgmbuf = vidiocgmbuf, | ||
1333 | #endif | ||
1334 | .tvnorms = tvnorms, | ||
1335 | .tvnormsize = ARRAY_SIZE(tvnorms), | ||
1415 | }; | 1336 | }; |
1416 | /* ------------------------------------------------------------------ | 1337 | /* ----------------------------------------------------------------- |
1417 | Initialization and module stuff | 1338 | Initialization and module stuff |
1418 | ------------------------------------------------------------------*/ | 1339 | ------------------------------------------------------------------*/ |
1419 | 1340 | ||
@@ -1457,3 +1378,16 @@ static void __exit vivi_exit(void) | |||
1457 | 1378 | ||
1458 | module_init(vivi_init); | 1379 | module_init(vivi_init); |
1459 | module_exit(vivi_exit); | 1380 | module_exit(vivi_exit); |
1381 | |||
1382 | MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); | ||
1383 | MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); | ||
1384 | MODULE_LICENSE("Dual BSD/GPL"); | ||
1385 | |||
1386 | module_param(video_nr, int, 0); | ||
1387 | |||
1388 | module_param_named(debug,vivi.debug, int, 0644); | ||
1389 | MODULE_PARM_DESC(debug,"activates debug info"); | ||
1390 | |||
1391 | module_param(vid_limit,int,0644); | ||
1392 | MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); | ||
1393 | |||
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 40b205b91481..1eca7e65d235 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #define I2C_NAME(x) (x)->name | 34 | #define I2C_NAME(x) (x)->name |
35 | 35 | ||
36 | #include <linux/videodev.h> | 36 | #include <linux/videodev.h> |
37 | #include <media/v4l2-common.h> | ||
37 | #include <linux/video_decoder.h> | 38 | #include <linux/video_decoder.h> |
38 | 39 | ||
39 | #define I2C_VPX3220 0x86 | 40 | #define I2C_VPX3220 0x86 |
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 80ef8a1b8f63..4bdc886abc4c 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/init.h> | 58 | #include <linux/init.h> |
59 | #include <linux/delay.h> | 59 | #include <linux/delay.h> |
60 | #include <linux/videodev.h> | 60 | #include <linux/videodev.h> |
61 | #include <media/v4l2-common.h> | ||
61 | #include <linux/parport.h> | 62 | #include <linux/parport.h> |
62 | 63 | ||
63 | //#define DEBUG // Undef me for production | 64 | //#define DEBUG // Undef me for production |
diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig index 115833e4f4dd..a859a6920189 100644 --- a/drivers/media/video/zc0301/Kconfig +++ b/drivers/media/video/zc0301/Kconfig | |||
@@ -1,9 +1,9 @@ | |||
1 | config USB_ZC0301 | 1 | config USB_ZC0301 |
2 | tristate "USB ZC0301 Image Processor and Control Chip support" | 2 | tristate "USB ZC0301[P] Image Processor and Control Chip support" |
3 | depends on USB && VIDEO_V4L1 | 3 | depends on USB && VIDEO_V4L1 |
4 | ---help--- | 4 | ---help--- |
5 | Say Y here if you want support for cameras based on the ZC0301 | 5 | Say Y here if you want support for cameras based on the ZC0301 or |
6 | Image Processor and Control Chip. | 6 | ZC0301P Image Processors and Control Chips. |
7 | 7 | ||
8 | See <file:Documentation/video4linux/zc0301.txt> for more info. | 8 | See <file:Documentation/video4linux/zc0301.txt> for more info. |
9 | 9 | ||
diff --git a/drivers/media/video/zc0301/Makefile b/drivers/media/video/zc0301/Makefile index d749199d8f06..d9e6d97fade6 100644 --- a/drivers/media/video/zc0301/Makefile +++ b/drivers/media/video/zc0301/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | zc0301-objs := zc0301_core.o zc0301_pas202bcb.o | 1 | zc0301-objs := zc0301_core.o zc0301_pb0330.o zc0301_pas202bcb.o |
2 | 2 | ||
3 | obj-$(CONFIG_USB_ZC0301) += zc0301.o | 3 | obj-$(CONFIG_USB_ZC0301) += zc0301.o |
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 0fad39754f7a..1b2be2d2a3ec 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Video4Linux2 driver for ZC0301 Image Processor and Control Chip * | 2 | * Video4Linux2 driver for ZC0301[P] Image Processor and Control Chip * |
3 | * * | 3 | * * |
4 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 4 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * |
5 | * * | 5 | * * |
@@ -47,13 +47,13 @@ | |||
47 | 47 | ||
48 | /*****************************************************************************/ | 48 | /*****************************************************************************/ |
49 | 49 | ||
50 | #define ZC0301_MODULE_NAME "V4L2 driver for ZC0301 " \ | 50 | #define ZC0301_MODULE_NAME "V4L2 driver for ZC0301[P] " \ |
51 | "Image Processor and Control Chip" | 51 | "Image Processor and Control Chip" |
52 | #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" | 52 | #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" |
53 | #define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" | 53 | #define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" |
54 | #define ZC0301_MODULE_LICENSE "GPL" | 54 | #define ZC0301_MODULE_LICENSE "GPL" |
55 | #define ZC0301_MODULE_VERSION "1:1.03" | 55 | #define ZC0301_MODULE_VERSION "1:1.05" |
56 | #define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 3) | 56 | #define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 5) |
57 | 57 | ||
58 | /*****************************************************************************/ | 58 | /*****************************************************************************/ |
59 | 59 | ||
@@ -427,10 +427,11 @@ resubmit_urb: | |||
427 | static int zc0301_start_transfer(struct zc0301_device* cam) | 427 | static int zc0301_start_transfer(struct zc0301_device* cam) |
428 | { | 428 | { |
429 | struct usb_device *udev = cam->usbdev; | 429 | struct usb_device *udev = cam->usbdev; |
430 | struct usb_host_interface* altsetting = usb_altnum_to_altsetting( | ||
431 | usb_ifnum_to_if(udev, 0), | ||
432 | ZC0301_ALTERNATE_SETTING); | ||
433 | const unsigned int psz = altsetting->endpoint[0].desc.wMaxPacketSize; | ||
430 | struct urb* urb; | 434 | struct urb* urb; |
431 | const unsigned int wMaxPacketSize[] = {0, 128, 192, 256, 384, | ||
432 | 512, 768, 1023}; | ||
433 | const unsigned int psz = wMaxPacketSize[ZC0301_ALTERNATE_SETTING]; | ||
434 | s8 i, j; | 435 | s8 i, j; |
435 | int err = 0; | 436 | int err = 0; |
436 | 437 | ||
@@ -1772,11 +1773,9 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
1772 | case VIDIOC_G_CTRL: | 1773 | case VIDIOC_G_CTRL: |
1773 | return zc0301_vidioc_g_ctrl(cam, arg); | 1774 | return zc0301_vidioc_g_ctrl(cam, arg); |
1774 | 1775 | ||
1775 | case VIDIOC_S_CTRL_OLD: | ||
1776 | case VIDIOC_S_CTRL: | 1776 | case VIDIOC_S_CTRL: |
1777 | return zc0301_vidioc_s_ctrl(cam, arg); | 1777 | return zc0301_vidioc_s_ctrl(cam, arg); |
1778 | 1778 | ||
1779 | case VIDIOC_CROPCAP_OLD: | ||
1780 | case VIDIOC_CROPCAP: | 1779 | case VIDIOC_CROPCAP: |
1781 | return zc0301_vidioc_cropcap(cam, arg); | 1780 | return zc0301_vidioc_cropcap(cam, arg); |
1782 | 1781 | ||
@@ -1823,7 +1822,6 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
1823 | case VIDIOC_G_PARM: | 1822 | case VIDIOC_G_PARM: |
1824 | return zc0301_vidioc_g_parm(cam, arg); | 1823 | return zc0301_vidioc_g_parm(cam, arg); |
1825 | 1824 | ||
1826 | case VIDIOC_S_PARM_OLD: | ||
1827 | case VIDIOC_S_PARM: | 1825 | case VIDIOC_S_PARM: |
1828 | return zc0301_vidioc_s_parm(cam, arg); | 1826 | return zc0301_vidioc_s_parm(cam, arg); |
1829 | 1827 | ||
@@ -1914,7 +1912,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
1914 | 1912 | ||
1915 | mutex_init(&cam->dev_mutex); | 1913 | mutex_init(&cam->dev_mutex); |
1916 | 1914 | ||
1917 | DBG(2, "ZC0301 Image Processor and Control Chip detected " | 1915 | DBG(2, "ZC0301[P] Image Processor and Control Chip detected " |
1918 | "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); | 1916 | "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); |
1919 | 1917 | ||
1920 | for (i = 0; zc0301_sensor_table[i]; i++) { | 1918 | for (i = 0; zc0301_sensor_table[i]; i++) { |
@@ -1936,7 +1934,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
1936 | cam->state |= DEV_MISCONFIGURED; | 1934 | cam->state |= DEV_MISCONFIGURED; |
1937 | } | 1935 | } |
1938 | 1936 | ||
1939 | strcpy(cam->v4ldev->name, "ZC0301 PC Camera"); | 1937 | strcpy(cam->v4ldev->name, "ZC0301[P] PC Camera"); |
1940 | cam->v4ldev->owner = THIS_MODULE; | 1938 | cam->v4ldev->owner = THIS_MODULE; |
1941 | cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; | 1939 | cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; |
1942 | cam->v4ldev->hardware = 0; | 1940 | cam->v4ldev->hardware = 0; |
diff --git a/drivers/media/video/zc0301/zc0301_pas202bcb.c b/drivers/media/video/zc0301/zc0301_pas202bcb.c index eaadf0252049..ecfd39a56df1 100644 --- a/drivers/media/video/zc0301/zc0301_pas202bcb.c +++ b/drivers/media/video/zc0301/zc0301_pas202bcb.c | |||
@@ -1,10 +1,10 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Plug-in for PAS202BCB image sensor connected to the ZC030! Image * | 2 | * Plug-in for PAS202BCB image sensor connected to the ZC0301[P] Image * |
3 | * Processor and Control Chip * | 3 | * Processor and Control Chip * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * |
6 | * * | 6 | * * |
7 | * Initialization values of the ZC0301 have been taken from the SPCA5XX * | 7 | * Initialization values of the ZC0301[P] have been taken from the SPCA5XX * |
8 | * driver maintained by Michel Xhaard <mxhaard@magic.fr> * | 8 | * driver maintained by Michel Xhaard <mxhaard@magic.fr> * |
9 | * * | 9 | * * |
10 | * This program is free software; you can redistribute it and/or modify * | 10 | * This program is free software; you can redistribute it and/or modify * |
diff --git a/drivers/media/video/zc0301/zc0301_pb0330.c b/drivers/media/video/zc0301/zc0301_pb0330.c new file mode 100644 index 000000000000..ed8542e6c50f --- /dev/null +++ b/drivers/media/video/zc0301/zc0301_pb0330.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /*************************************************************************** | ||
2 | * Plug-in for PB-0330 image sensor connected to the ZC0301[P] Image * | ||
3 | * Processor and Control Chip * | ||
4 | * * | ||
5 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
6 | * * | ||
7 | * Initialization values of the ZC0301[P] have been taken from the SPCA5XX * | ||
8 | * driver maintained by Michel Xhaard <mxhaard@magic.fr> * | ||
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 | #include <linux/delay.h> | ||
26 | #include "zc0301_sensor.h" | ||
27 | |||
28 | |||
29 | static struct zc0301_sensor pb0330; | ||
30 | |||
31 | |||
32 | static int pb0330_init(struct zc0301_device* cam) | ||
33 | { | ||
34 | int err = 0; | ||
35 | |||
36 | err += zc0301_write_reg(cam, 0x0000, 0x01); | ||
37 | err += zc0301_write_reg(cam, 0x0008, 0x03); | ||
38 | err += zc0301_write_reg(cam, 0x0010, 0x0A); | ||
39 | err += zc0301_write_reg(cam, 0x0002, 0x00); | ||
40 | err += zc0301_write_reg(cam, 0x0003, 0x02); | ||
41 | err += zc0301_write_reg(cam, 0x0004, 0x80); | ||
42 | err += zc0301_write_reg(cam, 0x0005, 0x01); | ||
43 | err += zc0301_write_reg(cam, 0x0006, 0xE0); | ||
44 | err += zc0301_write_reg(cam, 0x0001, 0x01); | ||
45 | err += zc0301_write_reg(cam, 0x0012, 0x05); | ||
46 | err += zc0301_write_reg(cam, 0x0012, 0x07); | ||
47 | err += zc0301_write_reg(cam, 0x0098, 0x00); | ||
48 | err += zc0301_write_reg(cam, 0x009A, 0x00); | ||
49 | err += zc0301_write_reg(cam, 0x011A, 0x00); | ||
50 | err += zc0301_write_reg(cam, 0x011C, 0x00); | ||
51 | err += zc0301_write_reg(cam, 0x0012, 0x05); | ||
52 | |||
53 | err += zc0301_i2c_write(cam, 0x01, 0x0006); | ||
54 | err += zc0301_i2c_write(cam, 0x02, 0x0011); | ||
55 | err += zc0301_i2c_write(cam, 0x03, 0x01E7); | ||
56 | err += zc0301_i2c_write(cam, 0x04, 0x0287); | ||
57 | err += zc0301_i2c_write(cam, 0x06, 0x0003); | ||
58 | err += zc0301_i2c_write(cam, 0x07, 0x3002); | ||
59 | err += zc0301_i2c_write(cam, 0x20, 0x1100); | ||
60 | err += zc0301_i2c_write(cam, 0x2F, 0xF7B0); | ||
61 | err += zc0301_i2c_write(cam, 0x30, 0x0005); | ||
62 | err += zc0301_i2c_write(cam, 0x31, 0x0000); | ||
63 | err += zc0301_i2c_write(cam, 0x34, 0x0100); | ||
64 | err += zc0301_i2c_write(cam, 0x35, 0x0060); | ||
65 | err += zc0301_i2c_write(cam, 0x3D, 0x068F); | ||
66 | err += zc0301_i2c_write(cam, 0x40, 0x01E0); | ||
67 | err += zc0301_i2c_write(cam, 0x58, 0x0078); | ||
68 | err += zc0301_i2c_write(cam, 0x62, 0x0411); | ||
69 | |||
70 | err += zc0301_write_reg(cam, 0x0087, 0x10); | ||
71 | err += zc0301_write_reg(cam, 0x0101, 0x37); | ||
72 | err += zc0301_write_reg(cam, 0x0012, 0x05); | ||
73 | err += zc0301_write_reg(cam, 0x0100, 0x0D); | ||
74 | err += zc0301_write_reg(cam, 0x0189, 0x06); | ||
75 | err += zc0301_write_reg(cam, 0x01AD, 0x00); | ||
76 | err += zc0301_write_reg(cam, 0x01C5, 0x03); | ||
77 | err += zc0301_write_reg(cam, 0x01CB, 0x13); | ||
78 | err += zc0301_write_reg(cam, 0x0250, 0x08); | ||
79 | err += zc0301_write_reg(cam, 0x0301, 0x08); | ||
80 | err += zc0301_write_reg(cam, 0x01A8, 0x60); | ||
81 | err += zc0301_write_reg(cam, 0x018D, 0x6C); | ||
82 | err += zc0301_write_reg(cam, 0x01AD, 0x09); | ||
83 | err += zc0301_write_reg(cam, 0x01AE, 0x15); | ||
84 | err += zc0301_write_reg(cam, 0x010A, 0x50); | ||
85 | err += zc0301_write_reg(cam, 0x010B, 0xF8); | ||
86 | err += zc0301_write_reg(cam, 0x010C, 0xF8); | ||
87 | err += zc0301_write_reg(cam, 0x010D, 0xF8); | ||
88 | err += zc0301_write_reg(cam, 0x010E, 0x50); | ||
89 | err += zc0301_write_reg(cam, 0x010F, 0xF8); | ||
90 | err += zc0301_write_reg(cam, 0x0110, 0xF8); | ||
91 | err += zc0301_write_reg(cam, 0x0111, 0xF8); | ||
92 | err += zc0301_write_reg(cam, 0x0112, 0x50); | ||
93 | err += zc0301_write_reg(cam, 0x0008, 0x03); | ||
94 | err += zc0301_write_reg(cam, 0x01C6, 0x08); | ||
95 | err += zc0301_write_reg(cam, 0x01CB, 0x0F); | ||
96 | err += zc0301_write_reg(cam, 0x010A, 0x50); | ||
97 | err += zc0301_write_reg(cam, 0x010B, 0xF8); | ||
98 | err += zc0301_write_reg(cam, 0x010C, 0xF8); | ||
99 | err += zc0301_write_reg(cam, 0x010D, 0xF8); | ||
100 | err += zc0301_write_reg(cam, 0x010E, 0x50); | ||
101 | err += zc0301_write_reg(cam, 0x010F, 0xF8); | ||
102 | err += zc0301_write_reg(cam, 0x0110, 0xF8); | ||
103 | err += zc0301_write_reg(cam, 0x0111, 0xF8); | ||
104 | err += zc0301_write_reg(cam, 0x0112, 0x50); | ||
105 | err += zc0301_write_reg(cam, 0x0180, 0x00); | ||
106 | err += zc0301_write_reg(cam, 0x0019, 0x00); | ||
107 | |||
108 | err += zc0301_i2c_write(cam, 0x05, 0x0066); | ||
109 | err += zc0301_i2c_write(cam, 0x09, 0x02B2); | ||
110 | err += zc0301_i2c_write(cam, 0x10, 0x0002); | ||
111 | |||
112 | err += zc0301_write_reg(cam, 0x011D, 0x60); | ||
113 | err += zc0301_write_reg(cam, 0x0190, 0x00); | ||
114 | err += zc0301_write_reg(cam, 0x0191, 0x07); | ||
115 | err += zc0301_write_reg(cam, 0x0192, 0x8C); | ||
116 | err += zc0301_write_reg(cam, 0x0195, 0x00); | ||
117 | err += zc0301_write_reg(cam, 0x0196, 0x00); | ||
118 | err += zc0301_write_reg(cam, 0x0197, 0x8A); | ||
119 | err += zc0301_write_reg(cam, 0x018C, 0x10); | ||
120 | err += zc0301_write_reg(cam, 0x018F, 0x20); | ||
121 | err += zc0301_write_reg(cam, 0x01A9, 0x14); | ||
122 | err += zc0301_write_reg(cam, 0x01AA, 0x24); | ||
123 | err += zc0301_write_reg(cam, 0x001D, 0xD7); | ||
124 | err += zc0301_write_reg(cam, 0x001E, 0xF0); | ||
125 | err += zc0301_write_reg(cam, 0x001F, 0xF8); | ||
126 | err += zc0301_write_reg(cam, 0x0020, 0xFF); | ||
127 | err += zc0301_write_reg(cam, 0x01AD, 0x09); | ||
128 | err += zc0301_write_reg(cam, 0x01AE, 0x15); | ||
129 | err += zc0301_write_reg(cam, 0x0180, 0x40); | ||
130 | err += zc0301_write_reg(cam, 0x0180, 0x42); | ||
131 | |||
132 | msleep(100); | ||
133 | |||
134 | return err; | ||
135 | } | ||
136 | |||
137 | |||
138 | static struct zc0301_sensor pb0330 = { | ||
139 | .name = "PB-0330", | ||
140 | .init = &pb0330_init, | ||
141 | .cropcap = { | ||
142 | .bounds = { | ||
143 | .left = 0, | ||
144 | .top = 0, | ||
145 | .width = 640, | ||
146 | .height = 480, | ||
147 | }, | ||
148 | .defrect = { | ||
149 | .left = 0, | ||
150 | .top = 0, | ||
151 | .width = 640, | ||
152 | .height = 480, | ||
153 | }, | ||
154 | }, | ||
155 | .pix_format = { | ||
156 | .width = 640, | ||
157 | .height = 480, | ||
158 | .pixelformat = V4L2_PIX_FMT_JPEG, | ||
159 | .priv = 8, | ||
160 | }, | ||
161 | }; | ||
162 | |||
163 | |||
164 | int zc0301_probe_pb0330(struct zc0301_device* cam) | ||
165 | { | ||
166 | int r0, err = 0; | ||
167 | |||
168 | err += zc0301_write_reg(cam, 0x0000, 0x01); | ||
169 | err += zc0301_write_reg(cam, 0x0010, 0x0a); | ||
170 | err += zc0301_write_reg(cam, 0x0001, 0x01); | ||
171 | err += zc0301_write_reg(cam, 0x0012, 0x03); | ||
172 | err += zc0301_write_reg(cam, 0x0012, 0x01); | ||
173 | |||
174 | msleep(10); | ||
175 | |||
176 | r0 = zc0301_i2c_read(cam, 0x00, 2); | ||
177 | |||
178 | if (r0 < 0 || err) | ||
179 | return -EIO; | ||
180 | |||
181 | if (r0 != 0x8243) | ||
182 | return -ENODEV; | ||
183 | |||
184 | zc0301_attach_sensor(cam, &pb0330); | ||
185 | |||
186 | return 0; | ||
187 | } | ||
diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h index 1f95c28b1015..4363a915b1f4 100644 --- a/drivers/media/video/zc0301/zc0301_sensor.h +++ b/drivers/media/video/zc0301/zc0301_sensor.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * API for image sensors connected to the ZC030! Image Processor and * | 2 | * API for image sensors connected to the ZC0301 Image Processor and * |
3 | * Control Chip * | 3 | * Control Chip * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * |
@@ -35,11 +35,13 @@ struct zc0301_sensor; | |||
35 | /*****************************************************************************/ | 35 | /*****************************************************************************/ |
36 | 36 | ||
37 | extern int zc0301_probe_pas202bcb(struct zc0301_device* cam); | 37 | extern int zc0301_probe_pas202bcb(struct zc0301_device* cam); |
38 | extern int zc0301_probe_pb0330(struct zc0301_device* cam); | ||
38 | 39 | ||
39 | #define ZC0301_SENSOR_TABLE \ | 40 | #define ZC0301_SENSOR_TABLE \ |
40 | /* Weak detections must go at the end of the list */ \ | 41 | /* Weak detections must go at the end of the list */ \ |
41 | static int (*zc0301_sensor_table[])(struct zc0301_device*) = { \ | 42 | static int (*zc0301_sensor_table[])(struct zc0301_device*) = { \ |
42 | &zc0301_probe_pas202bcb, \ | 43 | &zc0301_probe_pas202bcb, \ |
44 | &zc0301_probe_pb0330, \ | ||
43 | NULL, \ | 45 | NULL, \ |
44 | }; | 46 | }; |
45 | 47 | ||
@@ -58,14 +60,28 @@ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor); | |||
58 | 60 | ||
59 | #define ZC0301_ID_TABLE \ | 61 | #define ZC0301_ID_TABLE \ |
60 | static const struct usb_device_id zc0301_id_table[] = { \ | 62 | static const struct usb_device_id zc0301_id_table[] = { \ |
61 | { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, \ | 63 | { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, /* ICM105 */ \ |
62 | { ZC0301_USB_DEVICE(0x041e, 0x401c, 0xff), }, /* PAS106 */ \ | 64 | { ZC0301_USB_DEVICE(0x041e, 0x401c, 0xff), }, /* PAS106 */ \ |
63 | { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131B */ \ | 65 | { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131 */ \ |
66 | { ZC0301_USB_DEVICE(0x041e, 0x401f, 0xff), }, /* TAS5130 */ \ | ||
67 | { ZC0301_USB_DEVICE(0x041e, 0x4022, 0xff), }, \ | ||
64 | { ZC0301_USB_DEVICE(0x041e, 0x4034, 0xff), }, /* PAS106 */ \ | 68 | { ZC0301_USB_DEVICE(0x041e, 0x4034, 0xff), }, /* PAS106 */ \ |
65 | { ZC0301_USB_DEVICE(0x041e, 0x4035, 0xff), }, /* PAS106 */ \ | 69 | { ZC0301_USB_DEVICE(0x041e, 0x4035, 0xff), }, /* PAS106 */ \ |
66 | { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */ \ | 70 | { ZC0301_USB_DEVICE(0x041e, 0x4036, 0xff), }, /* HV7131 */ \ |
71 | { ZC0301_USB_DEVICE(0x041e, 0x403a, 0xff), }, /* HV7131 */ \ | ||
72 | { ZC0301_USB_DEVICE(0x0458, 0x7007, 0xff), }, /* TAS5130 */ \ | ||
73 | { ZC0301_USB_DEVICE(0x0458, 0x700C, 0xff), }, /* TAS5130 */ \ | ||
74 | { ZC0301_USB_DEVICE(0x0458, 0x700f, 0xff), }, /* TAS5130 */ \ | ||
75 | { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ | ||
76 | { ZC0301_USB_DEVICE(0x055f, 0xd003, 0xff), }, /* TAS5130 */ \ | ||
77 | { ZC0301_USB_DEVICE(0x055f, 0xd004, 0xff), }, /* TAS5130 */ \ | ||
78 | { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ | ||
67 | { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \ | 79 | { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \ |
68 | { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */ \ | 80 | { ZC0301_USB_DEVICE(0x0ac8, 0x301b, 0xff), }, /* PB-0330/HV7131 */ \ |
81 | { ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */ \ | ||
82 | { ZC0301_USB_DEVICE(0x10fd, 0x0128, 0xff), }, /* TAS5130 */ \ | ||
83 | { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130 */ \ | ||
84 | { ZC0301_USB_DEVICE(0x10fd, 0x804e, 0xff), }, /* TAS5130 */ \ | ||
69 | { } \ | 85 | { } \ |
70 | }; | 86 | }; |
71 | 87 | ||
diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h index 0166f555a5ca..ffcda95ed9d4 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran.h | |||
@@ -159,7 +159,7 @@ Private IOCTL to set up for displaying MJPEG | |||
159 | #define BUZ_MAX_FRAME 256 /* Must be a power of 2 */ | 159 | #define BUZ_MAX_FRAME 256 /* Must be a power of 2 */ |
160 | #define BUZ_MASK_FRAME 255 /* Must be BUZ_MAX_FRAME-1 */ | 160 | #define BUZ_MASK_FRAME 255 /* Must be BUZ_MAX_FRAME-1 */ |
161 | 161 | ||
162 | #define BUZ_MAX_INPUT 8 | 162 | #define BUZ_MAX_INPUT 16 |
163 | 163 | ||
164 | #if VIDEO_MAX_FRAME <= 32 | 164 | #if VIDEO_MAX_FRAME <= 32 |
165 | # define V4L_MAX_FRAME 32 | 165 | # define V4L_MAX_FRAME 32 |
@@ -191,6 +191,9 @@ enum card_type { | |||
191 | /* Iomega */ | 191 | /* Iomega */ |
192 | BUZ, | 192 | BUZ, |
193 | 193 | ||
194 | /* AverMedia */ | ||
195 | AVS6EYES, | ||
196 | |||
194 | /* total number of cards */ | 197 | /* total number of cards */ |
195 | NUM_CARDS | 198 | NUM_CARDS |
196 | }; | 199 | }; |
@@ -379,6 +382,9 @@ struct card_info { | |||
379 | /* is the /GWS line conected? */ | 382 | /* is the /GWS line conected? */ |
380 | u8 gws_not_connected; | 383 | u8 gws_not_connected; |
381 | 384 | ||
385 | /* avs6eyes mux setting */ | ||
386 | u8 input_mux; | ||
387 | |||
382 | void (*init) (struct zoran * zr); | 388 | void (*init) (struct zoran * zr); |
383 | }; | 389 | }; |
384 | 390 | ||
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index 0a85c9e7fb48..958c1e6fc852 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c | |||
@@ -27,6 +27,8 @@ | |||
27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/delay.h> | ||
31 | |||
30 | #include <linux/config.h> | 32 | #include <linux/config.h> |
31 | #include <linux/types.h> | 33 | #include <linux/types.h> |
32 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
@@ -38,6 +40,7 @@ | |||
38 | #include <linux/i2c.h> | 40 | #include <linux/i2c.h> |
39 | #include <linux/i2c-algo-bit.h> | 41 | #include <linux/i2c-algo-bit.h> |
40 | #include <linux/videodev.h> | 42 | #include <linux/videodev.h> |
43 | #include <media/v4l2-common.h> | ||
41 | #include <linux/spinlock.h> | 44 | #include <linux/spinlock.h> |
42 | #include <linux/sem.h> | 45 | #include <linux/sem.h> |
43 | #include <linux/kmod.h> | 46 | #include <linux/kmod.h> |
@@ -93,6 +96,11 @@ module_param(default_input, int, 0); | |||
93 | MODULE_PARM_DESC(default_input, | 96 | MODULE_PARM_DESC(default_input, |
94 | "Default input (0=Composite, 1=S-Video, 2=Internal)"); | 97 | "Default input (0=Composite, 1=S-Video, 2=Internal)"); |
95 | 98 | ||
99 | static int default_mux = 1; /* 6 Eyes input selection */ | ||
100 | module_param(default_mux, int, 0); | ||
101 | MODULE_PARM_DESC(default_mux, | ||
102 | "Default 6 Eyes mux setting (Input selection)"); | ||
103 | |||
96 | static int default_norm = 0; /* 0=PAL, 1=NTSC 2=SECAM */ | 104 | static int default_norm = 0; /* 0=PAL, 1=NTSC 2=SECAM */ |
97 | module_param(default_norm, int, 0); | 105 | module_param(default_norm, int, 0); |
98 | MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); | 106 | MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); |
@@ -301,6 +309,30 @@ lml33_init (struct zoran *zr) | |||
301 | GPIO(zr, 2, 1); // Set Composite input/output | 309 | GPIO(zr, 2, 1); // Set Composite input/output |
302 | } | 310 | } |
303 | 311 | ||
312 | static void | ||
313 | avs6eyes_init (struct zoran *zr) | ||
314 | { | ||
315 | // AverMedia 6-Eyes original driver by Christer Weinigel | ||
316 | |||
317 | // Lifted straight from Christer's old driver and | ||
318 | // modified slightly by Martin Samuelsson. | ||
319 | |||
320 | int mux = default_mux; /* 1 = BT866, 7 = VID1 */ | ||
321 | |||
322 | GPIO(zr, 4, 1); /* Bt866 SLEEP on */ | ||
323 | udelay(2); | ||
324 | |||
325 | GPIO(zr, 0, 1); /* ZR36060 /RESET on */ | ||
326 | GPIO(zr, 1, 0); /* ZR36060 /SLEEP on */ | ||
327 | GPIO(zr, 2, mux & 1); /* MUX S0 */ | ||
328 | GPIO(zr, 3, 0); /* /FRAME on */ | ||
329 | GPIO(zr, 4, 0); /* Bt866 SLEEP off */ | ||
330 | GPIO(zr, 5, mux & 2); /* MUX S1 */ | ||
331 | GPIO(zr, 6, 0); /* ? */ | ||
332 | GPIO(zr, 7, mux & 4); /* MUX S2 */ | ||
333 | |||
334 | } | ||
335 | |||
304 | static char * | 336 | static char * |
305 | i2cid_to_modulename (u16 i2c_id) | 337 | i2cid_to_modulename (u16 i2c_id) |
306 | { | 338 | { |
@@ -391,6 +423,14 @@ static struct tvnorm f60sqpixel_dc10 = { 780, 640, 0, 716, 525, 480, 12 }; | |||
391 | static struct tvnorm f50ccir601_lm33r10 = { 864, 720, 74+54, 804, 625, 576, 18 }; | 423 | static struct tvnorm f50ccir601_lm33r10 = { 864, 720, 74+54, 804, 625, 576, 18 }; |
392 | static struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56+54, 788, 525, 480, 16 }; | 424 | static struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56+54, 788, 525, 480, 16 }; |
393 | 425 | ||
426 | /* FIXME: The ks0127 seem incapable of swapping U and V, too, which is why I | ||
427 | * copy Maxim's left shift hack for the 6 Eyes. | ||
428 | * | ||
429 | * Christer's driver used the unshifted norms, though... | ||
430 | * /Sam */ | ||
431 | static struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 }; | ||
432 | static struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 }; | ||
433 | |||
394 | static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | 434 | static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { |
395 | { | 435 | { |
396 | .type = DC10_old, | 436 | .type = DC10_old, |
@@ -419,6 +459,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
419 | .gpcs = { -1, 0 }, | 459 | .gpcs = { -1, 0 }, |
420 | .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, | 460 | .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, |
421 | .gws_not_connected = 0, | 461 | .gws_not_connected = 0, |
462 | .input_mux = 0, | ||
422 | .init = &dc10_init, | 463 | .init = &dc10_init, |
423 | }, { | 464 | }, { |
424 | .type = DC10_new, | 465 | .type = DC10_new, |
@@ -445,6 +486,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
445 | .gpcs = { -1, 1}, | 486 | .gpcs = { -1, 1}, |
446 | .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 }, | 487 | .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 }, |
447 | .gws_not_connected = 0, | 488 | .gws_not_connected = 0, |
489 | .input_mux = 0, | ||
448 | .init = &dc10plus_init, | 490 | .init = &dc10plus_init, |
449 | }, { | 491 | }, { |
450 | .type = DC10plus, | 492 | .type = DC10plus, |
@@ -474,6 +516,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
474 | .gpcs = { -1, 1 }, | 516 | .gpcs = { -1, 1 }, |
475 | .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 }, | 517 | .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 }, |
476 | .gws_not_connected = 0, | 518 | .gws_not_connected = 0, |
519 | .input_mux = 0, | ||
477 | .init = &dc10plus_init, | 520 | .init = &dc10plus_init, |
478 | }, { | 521 | }, { |
479 | .type = DC30, | 522 | .type = DC30, |
@@ -502,6 +545,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
502 | .gpcs = { -1, 0 }, | 545 | .gpcs = { -1, 0 }, |
503 | .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, | 546 | .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, |
504 | .gws_not_connected = 0, | 547 | .gws_not_connected = 0, |
548 | .input_mux = 0, | ||
505 | .init = &dc10_init, | 549 | .init = &dc10_init, |
506 | }, { | 550 | }, { |
507 | .type = DC30plus, | 551 | .type = DC30plus, |
@@ -532,6 +576,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
532 | .gpcs = { -1, 0 }, | 576 | .gpcs = { -1, 0 }, |
533 | .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, | 577 | .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, |
534 | .gws_not_connected = 0, | 578 | .gws_not_connected = 0, |
579 | .input_mux = 0, | ||
535 | .init = &dc10_init, | 580 | .init = &dc10_init, |
536 | }, { | 581 | }, { |
537 | .type = LML33, | 582 | .type = LML33, |
@@ -558,6 +603,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
558 | .gpcs = { 3, 1 }, | 603 | .gpcs = { 3, 1 }, |
559 | .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 }, | 604 | .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 }, |
560 | .gws_not_connected = 1, | 605 | .gws_not_connected = 1, |
606 | .input_mux = 0, | ||
561 | .init = &lml33_init, | 607 | .init = &lml33_init, |
562 | }, { | 608 | }, { |
563 | .type = LML33R10, | 609 | .type = LML33R10, |
@@ -586,6 +632,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
586 | .gpcs = { 3, 1 }, | 632 | .gpcs = { 3, 1 }, |
587 | .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 }, | 633 | .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 }, |
588 | .gws_not_connected = 1, | 634 | .gws_not_connected = 1, |
635 | .input_mux = 0, | ||
589 | .init = &lml33_init, | 636 | .init = &lml33_init, |
590 | }, { | 637 | }, { |
591 | .type = BUZ, | 638 | .type = BUZ, |
@@ -614,8 +661,49 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
614 | .gpcs = { 3, 1 }, | 661 | .gpcs = { 3, 1 }, |
615 | .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 }, | 662 | .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 }, |
616 | .gws_not_connected = 1, | 663 | .gws_not_connected = 1, |
664 | .input_mux = 0, | ||
617 | .init = &buz_init, | 665 | .init = &buz_init, |
666 | }, { | ||
667 | .type = AVS6EYES, | ||
668 | .name = "6-Eyes", | ||
669 | /* AverMedia chose not to brand the 6-Eyes. Thus it | ||
670 | can't be autodetected, and requires card=x. */ | ||
671 | .vendor_id = -1, | ||
672 | .device_id = -1, | ||
673 | .i2c_decoder = I2C_DRIVERID_KS0127, | ||
674 | .i2c_encoder = I2C_DRIVERID_BT866, | ||
675 | .video_codec = CODEC_TYPE_ZR36060, | ||
676 | |||
677 | .inputs = 10, | ||
678 | .input = { | ||
679 | { 0, "Composite 1" }, | ||
680 | { 1, "Composite 2" }, | ||
681 | { 2, "Composite 3" }, | ||
682 | { 4, "Composite 4" }, | ||
683 | { 5, "Composite 5" }, | ||
684 | { 6, "Composite 6" }, | ||
685 | { 8, "S-Video 1" }, | ||
686 | { 9, "S-Video 2" }, | ||
687 | {10, "S-Video 3" }, | ||
688 | {15, "YCbCr" } | ||
689 | }, | ||
690 | .norms = 2, | ||
691 | .tvn = { | ||
692 | &f50ccir601_avs6eyes, | ||
693 | &f60ccir601_avs6eyes, | ||
694 | NULL | ||
695 | }, | ||
696 | .jpeg_int = ZR36057_ISR_GIRQ1, | ||
697 | .vsync_int = ZR36057_ISR_GIRQ0, | ||
698 | .gpio = { 1, 0, 3, -1, -1, -1, -1, -1 },// Validity unknown /Sam | ||
699 | .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, // Validity unknown /Sam | ||
700 | .gpcs = { 3, 1 }, // Validity unknown /Sam | ||
701 | .vfe_pol = { 1, 0, 0, 0, 0, 1, 0, 0 }, // Validity unknown /Sam | ||
702 | .gws_not_connected = 1, | ||
703 | .input_mux = 1, | ||
704 | .init = &avs6eyes_init, | ||
618 | } | 705 | } |
706 | |||
619 | }; | 707 | }; |
620 | 708 | ||
621 | /* | 709 | /* |
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index c690b2ee880a..02168d9c2187 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c | |||
@@ -536,7 +536,7 @@ zr36057_overlay (struct zoran *zr, | |||
536 | * All error messages are internal driver checking only! */ | 536 | * All error messages are internal driver checking only! */ |
537 | 537 | ||
538 | /* video display top and bottom registers */ | 538 | /* video display top and bottom registers */ |
539 | reg = (u32) zr->buffer.base + | 539 | reg = (long) zr->buffer.base + |
540 | zr->overlay_settings.x * | 540 | zr->overlay_settings.x * |
541 | ((zr->overlay_settings.format->depth + 7) / 8) + | 541 | ((zr->overlay_settings.format->depth + 7) / 8) + |
542 | zr->overlay_settings.y * | 542 | zr->overlay_settings.y * |
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index b5a576a37fd2..9711f6248ef7 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c | |||
@@ -73,6 +73,7 @@ | |||
73 | ) | 73 | ) |
74 | 74 | ||
75 | #include <linux/videodev.h> | 75 | #include <linux/videodev.h> |
76 | #include <media/v4l2-common.h> | ||
76 | #include "videocodec.h" | 77 | #include "videocodec.h" |
77 | 78 | ||
78 | #include <asm/io.h> | 79 | #include <asm/io.h> |
@@ -2047,7 +2048,7 @@ zoran_do_ioctl (struct inode *inode, | |||
2047 | dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr)); | 2048 | dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr)); |
2048 | 2049 | ||
2049 | memset(vcap, 0, sizeof(struct video_capability)); | 2050 | memset(vcap, 0, sizeof(struct video_capability)); |
2050 | strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)); | 2051 | strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)-1); |
2051 | vcap->type = ZORAN_VID_TYPE; | 2052 | vcap->type = ZORAN_VID_TYPE; |
2052 | 2053 | ||
2053 | vcap->channels = zr->card.inputs; | 2054 | vcap->channels = zr->card.inputs; |
@@ -2689,8 +2690,8 @@ zoran_do_ioctl (struct inode *inode, | |||
2689 | dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCAP\n", ZR_DEVNAME(zr)); | 2690 | dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCAP\n", ZR_DEVNAME(zr)); |
2690 | 2691 | ||
2691 | memset(cap, 0, sizeof(*cap)); | 2692 | memset(cap, 0, sizeof(*cap)); |
2692 | strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)); | 2693 | strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1); |
2693 | strncpy(cap->driver, "zoran", sizeof(cap->driver)); | 2694 | strncpy(cap->driver, "zoran", sizeof(cap->driver)-1); |
2694 | snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", | 2695 | snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", |
2695 | pci_name(zr->pci_dev)); | 2696 | pci_name(zr->pci_dev)); |
2696 | cap->version = | 2697 | cap->version = |
@@ -2742,7 +2743,7 @@ zoran_do_ioctl (struct inode *inode, | |||
2742 | memset(fmt, 0, sizeof(*fmt)); | 2743 | memset(fmt, 0, sizeof(*fmt)); |
2743 | fmt->index = index; | 2744 | fmt->index = index; |
2744 | fmt->type = type; | 2745 | fmt->type = type; |
2745 | strncpy(fmt->description, zoran_formats[i].name, 31); | 2746 | strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1); |
2746 | fmt->pixelformat = zoran_formats[i].fourcc; | 2747 | fmt->pixelformat = zoran_formats[i].fourcc; |
2747 | if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) | 2748 | if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) |
2748 | fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; | 2749 | fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; |
@@ -3566,16 +3567,16 @@ zoran_do_ioctl (struct inode *inode, | |||
3566 | 3567 | ||
3567 | switch (ctrl->id) { | 3568 | switch (ctrl->id) { |
3568 | case V4L2_CID_BRIGHTNESS: | 3569 | case V4L2_CID_BRIGHTNESS: |
3569 | strncpy(ctrl->name, "Brightness", 31); | 3570 | strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1); |
3570 | break; | 3571 | break; |
3571 | case V4L2_CID_CONTRAST: | 3572 | case V4L2_CID_CONTRAST: |
3572 | strncpy(ctrl->name, "Contrast", 31); | 3573 | strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1); |
3573 | break; | 3574 | break; |
3574 | case V4L2_CID_SATURATION: | 3575 | case V4L2_CID_SATURATION: |
3575 | strncpy(ctrl->name, "Saturation", 31); | 3576 | strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1); |
3576 | break; | 3577 | break; |
3577 | case V4L2_CID_HUE: | 3578 | case V4L2_CID_HUE: |
3578 | strncpy(ctrl->name, "Hue", 31); | 3579 | strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1); |
3579 | break; | 3580 | break; |
3580 | } | 3581 | } |
3581 | 3582 | ||
@@ -3693,7 +3694,7 @@ zoran_do_ioctl (struct inode *inode, | |||
3693 | &caps); | 3694 | &caps); |
3694 | if (caps.flags & VIDEO_DECODER_AUTO) { | 3695 | if (caps.flags & VIDEO_DECODER_AUTO) { |
3695 | std->id = V4L2_STD_ALL; | 3696 | std->id = V4L2_STD_ALL; |
3696 | strncpy(std->name, "Autodetect", 31); | 3697 | strncpy(std->name, "Autodetect", sizeof(std->name)-1); |
3697 | return 0; | 3698 | return 0; |
3698 | } else | 3699 | } else |
3699 | return -EINVAL; | 3700 | return -EINVAL; |
@@ -3701,21 +3702,21 @@ zoran_do_ioctl (struct inode *inode, | |||
3701 | switch (std->index) { | 3702 | switch (std->index) { |
3702 | case 0: | 3703 | case 0: |
3703 | std->id = V4L2_STD_PAL; | 3704 | std->id = V4L2_STD_PAL; |
3704 | strncpy(std->name, "PAL", 31); | 3705 | strncpy(std->name, "PAL", sizeof(std->name)-1); |
3705 | std->frameperiod.numerator = 1; | 3706 | std->frameperiod.numerator = 1; |
3706 | std->frameperiod.denominator = 25; | 3707 | std->frameperiod.denominator = 25; |
3707 | std->framelines = zr->card.tvn[0]->Ht; | 3708 | std->framelines = zr->card.tvn[0]->Ht; |
3708 | break; | 3709 | break; |
3709 | case 1: | 3710 | case 1: |
3710 | std->id = V4L2_STD_NTSC; | 3711 | std->id = V4L2_STD_NTSC; |
3711 | strncpy(std->name, "NTSC", 31); | 3712 | strncpy(std->name, "NTSC", sizeof(std->name)-1); |
3712 | std->frameperiod.numerator = 1001; | 3713 | std->frameperiod.numerator = 1001; |
3713 | std->frameperiod.denominator = 30000; | 3714 | std->frameperiod.denominator = 30000; |
3714 | std->framelines = zr->card.tvn[1]->Ht; | 3715 | std->framelines = zr->card.tvn[1]->Ht; |
3715 | break; | 3716 | break; |
3716 | case 2: | 3717 | case 2: |
3717 | std->id = V4L2_STD_SECAM; | 3718 | std->id = V4L2_STD_SECAM; |
3718 | strncpy(std->name, "SECAM", 31); | 3719 | strncpy(std->name, "SECAM", sizeof(std->name)-1); |
3719 | std->frameperiod.numerator = 1; | 3720 | std->frameperiod.numerator = 1; |
3720 | std->frameperiod.denominator = 25; | 3721 | std->frameperiod.denominator = 25; |
3721 | std->framelines = zr->card.tvn[2]->Ht; | 3722 | std->framelines = zr->card.tvn[2]->Ht; |
@@ -3871,7 +3872,7 @@ zoran_do_ioctl (struct inode *inode, | |||
3871 | memset(outp, 0, sizeof(*outp)); | 3872 | memset(outp, 0, sizeof(*outp)); |
3872 | outp->index = 0; | 3873 | outp->index = 0; |
3873 | outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; | 3874 | outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; |
3874 | strncpy(outp->name, "Autodetect", 31); | 3875 | strncpy(outp->name, "Autodetect", sizeof(outp->name)-1); |
3875 | 3876 | ||
3876 | return 0; | 3877 | return 0; |
3877 | } | 3878 | } |
diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c index a00fae90229a..f4ffe79bdc5b 100644 --- a/drivers/media/video/zoran_procfs.c +++ b/drivers/media/video/zoran_procfs.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/seq_file.h> | 43 | #include <linux/seq_file.h> |
44 | 44 | ||
45 | #include <linux/ctype.h> | 45 | #include <linux/ctype.h> |
46 | #include <linux/poll.h> | ||
46 | #include <asm/io.h> | 47 | #include <asm/io.h> |
47 | 48 | ||
48 | #include "videocodec.h" | 49 | #include "videocodec.h" |