aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx88
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/media/video/cx88
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r--drivers/media/video/cx88/Makefile11
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c911
-rw-r--r--drivers/media/video/cx88/cx88-cards.c938
-rw-r--r--drivers/media/video/cx88/cx88-core.c1239
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c381
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c213
-rw-r--r--drivers/media/video/cx88/cx88-input.c396
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c466
-rw-r--r--drivers/media/video/cx88/cx88-reg.h787
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c1032
-rw-r--r--drivers/media/video/cx88/cx88-vbi.c248
-rw-r--r--drivers/media/video/cx88/cx88-video.c2277
-rw-r--r--drivers/media/video/cx88/cx88.h551
13 files changed, 9450 insertions, 0 deletions
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
new file mode 100644
index 000000000000..606d0348da2c
--- /dev/null
+++ b/drivers/media/video/cx88/Makefile
@@ -0,0 +1,11 @@
1cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \
2 cx88-input.o
3cx8800-objs := cx88-video.o cx88-vbi.o
4cx8802-objs := cx88-mpeg.o
5
6obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o
7obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
8
9EXTRA_CFLAGS += -I$(src)/..
10EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
11EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
new file mode 100644
index 000000000000..46d6778b863b
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -0,0 +1,911 @@
1/*
2 * $Id: cx88-blackbird.c,v 1.26 2005/03/07 15:58:05 kraxel Exp $
3 *
4 * Support for a cx23416 mpeg encoder via cx2388x host port.
5 * "blackbird" reference design.
6 *
7 * (c) 2004 Jelle Foks <jelle@foks.8m.com>
8 * (c) 2004 Gerd Knorr <kraxel@bytesex.org>
9 *
10 * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
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., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#include <linux/module.h>
28#include <linux/moduleparam.h>
29#include <linux/init.h>
30#include <linux/fs.h>
31#include <linux/delay.h>
32#include <linux/device.h>
33#include <linux/firmware.h>
34
35#include "cx88.h"
36
37MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
38MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>");
39MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
40MODULE_LICENSE("GPL");
41
42static unsigned int mpegbufs = 8;
43module_param(mpegbufs,int,0644);
44MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
45
46static unsigned int debug = 0;
47module_param(debug,int,0644);
48MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
49
50#define dprintk(level,fmt, arg...) if (debug >= level) \
51 printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
52
53static LIST_HEAD(cx8802_devlist);
54
55/* ------------------------------------------------------------------ */
56
57#define BLACKBIRD_FIRM_ENC_FILENAME "blackbird-fw-enc.bin"
58#define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024
59
60/* defines below are from ivtv-driver.h */
61
62#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
63
64/*Firmware API commands*/
65#define IVTV_API_ENC_PING_FW 0x00000080
66#define IVTV_API_ENC_GETVER 0x000000C4
67#define IVTV_API_ENC_HALT_FW 0x000000C3
68#define IVTV_API_STD_TIMEOUT 0x00010000 /*units??*/
69//#define IVTV_API_ASSIGN_PGM_INDEX_INFO 0x000000c7
70#define IVTV_API_ASSIGN_STREAM_TYPE 0x000000b9
71#define IVTV_API_ASSIGN_OUTPUT_PORT 0x000000bb
72#define IVTV_API_ASSIGN_FRAMERATE 0x0000008f
73#define IVTV_API_ASSIGN_FRAME_SIZE 0x00000091
74#define IVTV_API_ASSIGN_ASPECT_RATIO 0x00000099
75#define IVTV_API_ASSIGN_BITRATES 0x00000095
76#define IVTV_API_ASSIGN_GOP_PROPERTIES 0x00000097
77#define IVTV_API_ASSIGN_3_2_PULLDOWN 0x000000b1
78#define IVTV_API_ASSIGN_GOP_CLOSURE 0x000000c5
79#define IVTV_API_ASSIGN_AUDIO_PROPERTIES 0x000000bd
80#define IVTV_API_ASSIGN_DNR_FILTER_MODE 0x0000009b
81#define IVTV_API_ASSIGN_DNR_FILTER_PROPS 0x0000009d
82#define IVTV_API_ASSIGN_CORING_LEVELS 0x0000009f
83#define IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE 0x000000a1
84#define IVTV_API_ASSIGN_FRAME_DROP_RATE 0x000000d0
85#define IVTV_API_ASSIGN_PLACEHOLDER 0x000000d8
86#define IVTV_API_MUTE_VIDEO 0x000000d9
87#define IVTV_API_MUTE_AUDIO 0x000000da
88#define IVTV_API_INITIALIZE_INPUT 0x000000cd
89#define IVTV_API_REFRESH_INPUT 0x000000d3
90#define IVTV_API_ASSIGN_NUM_VSYNC_LINES 0x000000d6
91#define IVTV_API_BEGIN_CAPTURE 0x00000081
92//#define IVTV_API_PAUSE_ENCODER 0x000000d2
93//#define IVTV_API_EVENT_NOTIFICATION 0x000000d5
94#define IVTV_API_END_CAPTURE 0x00000082
95
96/* Registers */
97#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/)
98#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC /*| IVTV_REG_OFFSET*/)
99#define IVTV_REG_SPU (0x9050 /*| IVTV_REG_OFFSET*/)
100#define IVTV_REG_HW_BLOCKS (0x9054 /*| IVTV_REG_OFFSET*/)
101#define IVTV_REG_VPU (0x9058 /*| IVTV_REG_OFFSET*/)
102#define IVTV_REG_APU (0xA064 /*| IVTV_REG_OFFSET*/)
103
104/* ------------------------------------------------------------------ */
105
106static void host_setup(struct cx88_core *core)
107{
108 /* toggle reset of the host */
109 cx_write(MO_GPHST_SOFT_RST, 1);
110 udelay(100);
111 cx_write(MO_GPHST_SOFT_RST, 0);
112 udelay(100);
113
114 /* host port setup */
115 cx_write(MO_GPHST_WSC, 0x44444444U);
116 cx_write(MO_GPHST_XFR, 0);
117 cx_write(MO_GPHST_WDTH, 15);
118 cx_write(MO_GPHST_HDSHK, 0);
119 cx_write(MO_GPHST_MUX16, 0x44448888U);
120 cx_write(MO_GPHST_MODE, 0);
121}
122
123/* ------------------------------------------------------------------ */
124
125#define P1_MDATA0 0x390000
126#define P1_MDATA1 0x390001
127#define P1_MDATA2 0x390002
128#define P1_MDATA3 0x390003
129#define P1_MADDR2 0x390004
130#define P1_MADDR1 0x390005
131#define P1_MADDR0 0x390006
132#define P1_RDATA0 0x390008
133#define P1_RDATA1 0x390009
134#define P1_RDATA2 0x39000A
135#define P1_RDATA3 0x39000B
136#define P1_RADDR0 0x39000C
137#define P1_RADDR1 0x39000D
138#define P1_RRDWR 0x39000E
139
140static int wait_ready_gpio0_bit1(struct cx88_core *core, u32 state)
141{
142 unsigned long timeout = jiffies + msecs_to_jiffies(1);
143 u32 gpio0,need;
144
145 need = state ? 2 : 0;
146 for (;;) {
147 gpio0 = cx_read(MO_GP0_IO) & 2;
148 if (need == gpio0)
149 return 0;
150 if (time_after(jiffies,timeout))
151 return -1;
152 udelay(1);
153 }
154}
155
156static int memory_write(struct cx88_core *core, u32 address, u32 value)
157{
158 /* Warning: address is dword address (4 bytes) */
159 cx_writeb(P1_MDATA0, (unsigned int)value);
160 cx_writeb(P1_MDATA1, (unsigned int)(value >> 8));
161 cx_writeb(P1_MDATA2, (unsigned int)(value >> 16));
162 cx_writeb(P1_MDATA3, (unsigned int)(value >> 24));
163 cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) | 0x40);
164 cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
165 cx_writeb(P1_MADDR0, (unsigned int)address);
166 cx_read(P1_MDATA0);
167 cx_read(P1_MADDR0);
168
169 return wait_ready_gpio0_bit1(core,1);
170}
171
172static int memory_read(struct cx88_core *core, u32 address, u32 *value)
173{
174 int retval;
175 u32 val;
176
177 /* Warning: address is dword address (4 bytes) */
178 cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) & ~0xC0);
179 cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
180 cx_writeb(P1_MADDR0, (unsigned int)address);
181 cx_read(P1_MADDR0);
182
183 retval = wait_ready_gpio0_bit1(core,1);
184
185 cx_writeb(P1_MDATA3, 0);
186 val = (unsigned char)cx_read(P1_MDATA3) << 24;
187 cx_writeb(P1_MDATA2, 0);
188 val |= (unsigned char)cx_read(P1_MDATA2) << 16;
189 cx_writeb(P1_MDATA1, 0);
190 val |= (unsigned char)cx_read(P1_MDATA1) << 8;
191 cx_writeb(P1_MDATA0, 0);
192 val |= (unsigned char)cx_read(P1_MDATA0);
193
194 *value = val;
195 return retval;
196}
197
198static int register_write(struct cx88_core *core, u32 address, u32 value)
199{
200 cx_writeb(P1_RDATA0, (unsigned int)value);
201 cx_writeb(P1_RDATA1, (unsigned int)(value >> 8));
202 cx_writeb(P1_RDATA2, (unsigned int)(value >> 16));
203 cx_writeb(P1_RDATA3, (unsigned int)(value >> 24));
204 cx_writeb(P1_RADDR0, (unsigned int)address);
205 cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
206 cx_writeb(P1_RRDWR, 1);
207 cx_read(P1_RDATA0);
208 cx_read(P1_RADDR0);
209
210 return wait_ready_gpio0_bit1(core,1);
211}
212
213
214static int register_read(struct cx88_core *core, u32 address, u32 *value)
215{
216 int retval;
217 u32 val;
218
219 cx_writeb(P1_RADDR0, (unsigned int)address);
220 cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
221 cx_writeb(P1_RRDWR, 0);
222 cx_read(P1_RADDR0);
223
224 retval = wait_ready_gpio0_bit1(core,1);
225 val = (unsigned char)cx_read(P1_RDATA0);
226 val |= (unsigned char)cx_read(P1_RDATA1) << 8;
227 val |= (unsigned char)cx_read(P1_RDATA2) << 16;
228 val |= (unsigned char)cx_read(P1_RDATA3) << 24;
229
230 *value = val;
231 return retval;
232}
233
234/* ------------------------------------------------------------------ */
235
236/* We don't need to call the API often, so using just one mailbox will probably suffice */
237static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
238 u32 inputcnt, u32 outputcnt, ...)
239{
240 unsigned long timeout;
241 u32 value, flag, retval;
242 int i;
243 va_list args;
244 va_start(args, outputcnt);
245
246 dprintk(1,"%s: 0x%X\n", __FUNCTION__, command);
247
248 /* this may not be 100% safe if we can't read any memory location
249 without side effects */
250 memory_read(dev->core, dev->mailbox - 4, &value);
251 if (value != 0x12345678) {
252 dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n");
253 return -1;
254 }
255
256 memory_read(dev->core, dev->mailbox, &flag);
257 if (flag) {
258 dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag);
259 return -1;
260 }
261
262 flag |= 1; /* tell 'em we're working on it */
263 memory_write(dev->core, dev->mailbox, flag);
264
265 /* write command + args + fill remaining with zeros */
266 memory_write(dev->core, dev->mailbox + 1, command); /* command code */
267 memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */
268 for (i = 0; i < inputcnt ; i++) {
269 value = va_arg(args, int);
270 memory_write(dev->core, dev->mailbox + 4 + i, value);
271 dprintk(1, "API Input %d = %d\n", i, value);
272 }
273 for (; i < 16 ; i++)
274 memory_write(dev->core, dev->mailbox + 4 + i, 0);
275
276 flag |= 3; /* tell 'em we're done writing */
277 memory_write(dev->core, dev->mailbox, flag);
278
279 /* wait for firmware to handle the API command */
280 timeout = jiffies + msecs_to_jiffies(10);
281 for (;;) {
282 memory_read(dev->core, dev->mailbox, &flag);
283 if (0 != (flag & 4))
284 break;
285 if (time_after(jiffies,timeout)) {
286 dprintk(0, "ERROR: API Mailbox timeout\n");
287 return -1;
288 }
289 udelay(10);
290 }
291
292 /* read output values */
293 for (i = 0; i < outputcnt ; i++) {
294 int *vptr = va_arg(args, int *);
295 memory_read(dev->core, dev->mailbox + 4 + i, vptr);
296 dprintk(1, "API Output %d = %d\n", i, *vptr);
297 }
298 va_end(args);
299
300 memory_read(dev->core, dev->mailbox + 2, &retval);
301 dprintk(1, "API result = %d\n",retval);
302
303 flag = 0;
304 memory_write(dev->core, dev->mailbox, flag);
305 return retval;
306}
307
308
309static int blackbird_find_mailbox(struct cx8802_dev *dev)
310{
311 u32 signature[4]={0x12345678, 0x34567812, 0x56781234, 0x78123456};
312 int signaturecnt=0;
313 u32 value;
314 int i;
315
316 for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) {
317 memory_read(dev->core, i, &value);
318 if (value == signature[signaturecnt])
319 signaturecnt++;
320 else
321 signaturecnt = 0;
322 if (4 == signaturecnt) {
323 dprintk(1, "Mailbox signature found\n");
324 return i+1;
325 }
326 }
327 dprintk(0, "Mailbox signature values not found!\n");
328 return -1;
329}
330
331static int blackbird_load_firmware(struct cx8802_dev *dev)
332{
333 static const unsigned char magic[8] = {
334 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
335 };
336 const struct firmware *firmware;
337 int i, retval = 0;
338 u32 value = 0;
339 u32 checksum = 0;
340 u32 *dataptr;
341
342 retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED);
343 retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
344 retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640);
345 retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
346 msleep(1);
347 retval |= register_write(dev->core, IVTV_REG_APU, 0);
348
349 if (retval < 0)
350 dprintk(0, "Error with register_write\n");
351
352 retval = request_firmware(&firmware, BLACKBIRD_FIRM_ENC_FILENAME,
353 &dev->pci->dev);
354 if (retval != 0) {
355 dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
356 BLACKBIRD_FIRM_ENC_FILENAME);
357 dprintk(0, "Please fix your hotplug setup, the board will "
358 "not work without firmware loaded!\n");
359 return -1;
360 }
361
362 if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
363 dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
364 firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
365 return -1;
366 }
367
368 if (0 != memcmp(firmware->data, magic, 8)) {
369 dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
370 return -1;
371 }
372
373 /* transfer to the chip */
374 dprintk(1,"Loading firmware ...\n");
375 dataptr = (u32*)firmware->data;
376 for (i = 0; i < (firmware->size >> 2); i++) {
377 value = *dataptr;
378 checksum += ~value;
379 memory_write(dev->core, i, value);
380 dataptr++;
381 }
382
383 /* read back to verify with the checksum */
384 for (i--; i >= 0; i--) {
385 memory_read(dev->core, i, &value);
386 checksum -= ~value;
387 }
388 if (checksum) {
389 dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n");
390 return -1;
391 }
392 release_firmware(firmware);
393 dprintk(0, "Firmware upload successful.\n");
394
395 retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
396 retval |= register_read(dev->core, IVTV_REG_SPU, &value);
397 retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE);
398 msleep(1);
399
400 retval |= register_read(dev->core, IVTV_REG_VPU, &value);
401 retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8);
402
403 if (retval < 0)
404 dprintk(0, "Error with register_write\n");
405 return 0;
406}
407
408static void blackbird_codec_settings(struct cx8802_dev *dev)
409{
410 int bitrate_mode = 1;
411 int bitrate = 7500000;
412 int bitrate_peak = 7500000;
413
414 /* assign stream type */
415 blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 0); /* program stream */
416 //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 2); /* MPEG1 stream */
417 //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 3); /* PES A/V */
418 //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 10); /* DVD stream */
419
420 /* assign output port */
421 blackbird_api_cmd(dev, IVTV_API_ASSIGN_OUTPUT_PORT, 1, 0, 1); /* 1 = Host */
422
423 /* assign framerate */
424 blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAMERATE, 1, 0, 0);
425
426 /* assign frame size */
427 blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0,
428 dev->height, dev->width);
429
430 /* assign aspect ratio */
431 blackbird_api_cmd(dev, IVTV_API_ASSIGN_ASPECT_RATIO, 1, 0, 2);
432
433 /* assign bitrates */
434 blackbird_api_cmd(dev, IVTV_API_ASSIGN_BITRATES, 5, 0,
435 bitrate_mode, /* mode */
436 bitrate, /* bps */
437 bitrate_peak / 400, /* peak/400 */
438 0, 0x70); /* encoding buffer, ckennedy */
439
440 /* assign gop properties */
441 blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 15, 3);
442 //blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 2, 1);
443
444 /* assign 3 2 pulldown */
445 blackbird_api_cmd(dev, IVTV_API_ASSIGN_3_2_PULLDOWN, 1, 0, 0);
446
447 /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */
448 blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, (2<<2) | (8<<4));
449
450 /* assign gop closure */
451 blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_CLOSURE, 1, 0, 0);
452
453 /* assign audio properties */
454 blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, 0 | (2 << 2) | (14 << 4));
455
456 /* assign dnr filter mode */
457 blackbird_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_MODE, 2, 0, 0, 0);
458
459 /* assign dnr filter props*/
460 blackbird_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_PROPS, 2, 0, 0, 0);
461
462 /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */
463 blackbird_api_cmd(dev, IVTV_API_ASSIGN_CORING_LEVELS, 4, 0, 0, 255, 0, 255);
464
465 /* assign spatial filter type: luma_t: 1 = horiz_only, chroma_t: 1 = horiz_only */
466 blackbird_api_cmd(dev, IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE, 2, 0, 1, 1);
467
468 /* assign frame drop rate */
469 blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0);
470}
471
472static int blackbird_initialize_codec(struct cx8802_dev *dev)
473{
474 struct cx88_core *core = dev->core;
475 int version;
476 int retval;
477
478 dprintk(1,"Initialize codec\n");
479 retval = blackbird_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */
480 if (retval < 0) {
481 /* ping was not successful, reset and upload firmware */
482 cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
483 msleep(1);
484 cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */
485 msleep(1);
486 retval = blackbird_load_firmware(dev);
487 if (retval < 0)
488 return retval;
489
490 dev->mailbox = blackbird_find_mailbox(dev);
491 if (dev->mailbox < 0)
492 return -1;
493
494 retval = blackbird_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */
495 if (retval < 0) {
496 dprintk(0, "ERROR: Firmware ping failed!\n");
497 return -1;
498 }
499
500 retval = blackbird_api_cmd(dev, IVTV_API_ENC_GETVER, 0, 1, &version);
501 if (retval < 0) {
502 dprintk(0, "ERROR: Firmware get encoder version failed!\n");
503 return -1;
504 }
505 dprintk(0, "Firmware version is 0x%08x\n", version);
506 }
507 msleep(1);
508
509 cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */
510 cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */
511 cx_write(MO_VBOS_CONTROL, 0x84A00); /* no 656 mode, 8-bit pixels, disable VBI */
512 cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */
513
514#if 0 /* FIXME */
515 set_scale(dev, 720, 480, V4L2_FIELD_INTERLACED);
516#endif
517 blackbird_codec_settings(dev);
518 msleep(1);
519
520 //blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef);
521 blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0);
522 //blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180);
523 blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
524
525 blackbird_api_cmd(dev, IVTV_API_INITIALIZE_INPUT, 0, 0); /* initialize the video input */
526
527 msleep(1);
528
529 blackbird_api_cmd(dev, IVTV_API_MUTE_VIDEO, 1, 0, 0);
530 msleep(1);
531 blackbird_api_cmd(dev, IVTV_API_MUTE_AUDIO, 1, 0, 0);
532 msleep(1);
533
534 blackbird_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); /* start capturing to the host interface */
535 //blackbird_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0); /* start capturing to the host interface */
536 msleep(1);
537
538 blackbird_api_cmd(dev, IVTV_API_REFRESH_INPUT, 0,0);
539 return 0;
540}
541
542/* ------------------------------------------------------------------ */
543
544static int bb_buf_setup(struct videobuf_queue *q,
545 unsigned int *count, unsigned int *size)
546{
547 struct cx8802_fh *fh = q->priv_data;
548
549 fh->dev->ts_packet_size = 512;
550 fh->dev->ts_packet_count = 100;
551
552 *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
553 if (0 == *count)
554 *count = mpegbufs;
555 if (*count < 2)
556 *count = 2;
557 if (*count > 32)
558 *count = 32;
559 return 0;
560}
561
562static int
563bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
564 enum v4l2_field field)
565{
566 struct cx8802_fh *fh = q->priv_data;
567 return cx8802_buf_prepare(fh->dev, (struct cx88_buffer*)vb);
568}
569
570static void
571bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
572{
573 struct cx8802_fh *fh = q->priv_data;
574 cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);
575}
576
577static void
578bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
579{
580 struct cx8802_fh *fh = q->priv_data;
581 cx88_free_buffer(fh->dev->pci, (struct cx88_buffer*)vb);
582}
583
584static struct videobuf_queue_ops blackbird_qops = {
585 .buf_setup = bb_buf_setup,
586 .buf_prepare = bb_buf_prepare,
587 .buf_queue = bb_buf_queue,
588 .buf_release = bb_buf_release,
589};
590
591/* ------------------------------------------------------------------ */
592
593static int mpeg_do_ioctl(struct inode *inode, struct file *file,
594 unsigned int cmd, void *arg)
595{
596 struct cx8802_fh *fh = file->private_data;
597 struct cx8802_dev *dev = fh->dev;
598
599 if (debug > 1)
600 cx88_print_ioctl(dev->core->name,cmd);
601
602 switch (cmd) {
603
604 /* --- capture ioctls ---------------------------------------- */
605 case VIDIOC_ENUM_FMT:
606 {
607 struct v4l2_fmtdesc *f = arg;
608 int index;
609
610 index = f->index;
611 if (index != 0)
612 return -EINVAL;
613
614 memset(f,0,sizeof(*f));
615 f->index = index;
616 strlcpy(f->description, "MPEG TS", sizeof(f->description));
617 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
618 f->pixelformat = V4L2_PIX_FMT_MPEG;
619 return 0;
620 }
621 case VIDIOC_G_FMT:
622 case VIDIOC_S_FMT:
623 case VIDIOC_TRY_FMT:
624 {
625 /* FIXME -- quick'n'dirty for exactly one size ... */
626 struct v4l2_format *f = arg;
627
628 memset(f,0,sizeof(*f));
629 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
630 f->fmt.pix.width = dev->width;
631 f->fmt.pix.height = dev->height;
632 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
633 f->fmt.pix.sizeimage = 1024 * 512 /* FIXME: BUFFER_SIZE */;
634 }
635
636 /* --- streaming capture ------------------------------------- */
637 case VIDIOC_REQBUFS:
638 return videobuf_reqbufs(&fh->mpegq, arg);
639
640 case VIDIOC_QUERYBUF:
641 return videobuf_querybuf(&fh->mpegq, arg);
642
643 case VIDIOC_QBUF:
644 return videobuf_qbuf(&fh->mpegq, arg);
645
646 case VIDIOC_DQBUF:
647 return videobuf_dqbuf(&fh->mpegq, arg,
648 file->f_flags & O_NONBLOCK);
649
650 case VIDIOC_STREAMON:
651 return videobuf_streamon(&fh->mpegq);
652
653 case VIDIOC_STREAMOFF:
654 return videobuf_streamoff(&fh->mpegq);
655
656 default:
657 return -EINVAL;
658 }
659 return 0;
660}
661
662static int mpeg_ioctl(struct inode *inode, struct file *file,
663 unsigned int cmd, unsigned long arg)
664{
665 return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
666}
667
668static int mpeg_open(struct inode *inode, struct file *file)
669{
670 int minor = iminor(inode);
671 struct cx8802_dev *h,*dev = NULL;
672 struct cx8802_fh *fh;
673 struct list_head *list;
674
675 list_for_each(list,&cx8802_devlist) {
676 h = list_entry(list, struct cx8802_dev, devlist);
677 if (h->mpeg_dev->minor == minor)
678 dev = h;
679 }
680 if (NULL == dev)
681 return -ENODEV;
682
683 if (blackbird_initialize_codec(dev) < 0)
684 return -EINVAL;
685 dprintk(1,"open minor=%d\n",minor);
686
687 /* allocate + initialize per filehandle data */
688 fh = kmalloc(sizeof(*fh),GFP_KERNEL);
689 if (NULL == fh)
690 return -ENOMEM;
691 memset(fh,0,sizeof(*fh));
692 file->private_data = fh;
693 fh->dev = dev;
694
695 /* FIXME: locking against other video device */
696 cx88_set_scale(dev->core, dev->width, dev->height,
697 V4L2_FIELD_INTERLACED);
698
699 videobuf_queue_init(&fh->mpegq, &blackbird_qops,
700 dev->pci, &dev->slock,
701 V4L2_BUF_TYPE_VIDEO_CAPTURE,
702 V4L2_FIELD_TOP,
703 sizeof(struct cx88_buffer),
704 fh);
705 return 0;
706}
707
708static int mpeg_release(struct inode *inode, struct file *file)
709{
710 struct cx8802_fh *fh = file->private_data;
711
712 blackbird_api_cmd(fh->dev, IVTV_API_END_CAPTURE, 3, 0, 1, 0, 0x13);
713
714 /* stop mpeg capture */
715 if (fh->mpegq.streaming)
716 videobuf_streamoff(&fh->mpegq);
717 if (fh->mpegq.reading)
718 videobuf_read_stop(&fh->mpegq);
719
720 videobuf_mmap_free(&fh->mpegq);
721 file->private_data = NULL;
722 kfree(fh);
723 return 0;
724}
725
726static ssize_t
727mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
728{
729 struct cx8802_fh *fh = file->private_data;
730
731 return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
732 file->f_flags & O_NONBLOCK);
733}
734
735static unsigned int
736mpeg_poll(struct file *file, struct poll_table_struct *wait)
737{
738 struct cx8802_fh *fh = file->private_data;
739
740 return videobuf_poll_stream(file, &fh->mpegq, wait);
741}
742
743static int
744mpeg_mmap(struct file *file, struct vm_area_struct * vma)
745{
746 struct cx8802_fh *fh = file->private_data;
747
748 return videobuf_mmap_mapper(&fh->mpegq, vma);
749}
750
751static struct file_operations mpeg_fops =
752{
753 .owner = THIS_MODULE,
754 .open = mpeg_open,
755 .release = mpeg_release,
756 .read = mpeg_read,
757 .poll = mpeg_poll,
758 .mmap = mpeg_mmap,
759 .ioctl = mpeg_ioctl,
760 .llseek = no_llseek,
761};
762
763static struct video_device cx8802_mpeg_template =
764{
765 .name = "cx8802",
766 .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER,
767 .hardware = 0,
768 .fops = &mpeg_fops,
769 .minor = -1,
770};
771
772/* ------------------------------------------------------------------ */
773
774static void blackbird_unregister_video(struct cx8802_dev *dev)
775{
776 if (dev->mpeg_dev) {
777 if (-1 != dev->mpeg_dev->minor)
778 video_unregister_device(dev->mpeg_dev);
779 else
780 video_device_release(dev->mpeg_dev);
781 dev->mpeg_dev = NULL;
782 }
783}
784
785static int blackbird_register_video(struct cx8802_dev *dev)
786{
787 int err;
788
789 dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
790 &cx8802_mpeg_template,"mpeg");
791 err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
792 if (err < 0) {
793 printk(KERN_INFO "%s/2: can't register mpeg device\n",
794 dev->core->name);
795 return err;
796 }
797 printk(KERN_INFO "%s/2: registered device video%d [mpeg]\n",
798 dev->core->name,dev->mpeg_dev->minor & 0x1f);
799 return 0;
800}
801
802/* ----------------------------------------------------------- */
803
804static int __devinit blackbird_probe(struct pci_dev *pci_dev,
805 const struct pci_device_id *pci_id)
806{
807 struct cx8802_dev *dev;
808 struct cx88_core *core;
809 int err;
810
811 /* general setup */
812 core = cx88_core_get(pci_dev);
813 if (NULL == core)
814 return -EINVAL;
815
816 err = -ENODEV;
817 if (!cx88_boards[core->board].blackbird)
818 goto fail_core;
819
820 err = -ENOMEM;
821 dev = kmalloc(sizeof(*dev),GFP_KERNEL);
822 if (NULL == dev)
823 goto fail_core;
824 memset(dev,0,sizeof(*dev));
825 dev->pci = pci_dev;
826 dev->core = core;
827 dev->width = 720;
828 dev->height = 480;
829
830 err = cx8802_init_common(dev);
831 if (0 != err)
832 goto fail_free;
833
834 /* blackbird stuff */
835 printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
836 core->name);
837 host_setup(dev->core);
838
839 list_add_tail(&dev->devlist,&cx8802_devlist);
840 blackbird_register_video(dev);
841 return 0;
842
843 fail_free:
844 kfree(dev);
845 fail_core:
846 cx88_core_put(core,pci_dev);
847 return err;
848}
849
850static void __devexit blackbird_remove(struct pci_dev *pci_dev)
851{
852 struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
853
854 /* blackbird */
855 blackbird_unregister_video(dev);
856 list_del(&dev->devlist);
857
858 /* common */
859 cx8802_fini_common(dev);
860 cx88_core_put(dev->core,dev->pci);
861 kfree(dev);
862}
863
864static struct pci_device_id cx8802_pci_tbl[] = {
865 {
866 .vendor = 0x14f1,
867 .device = 0x8802,
868 .subvendor = PCI_ANY_ID,
869 .subdevice = PCI_ANY_ID,
870 },{
871 /* --- end of list --- */
872 }
873};
874MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
875
876static struct pci_driver blackbird_pci_driver = {
877 .name = "cx88-blackbird",
878 .id_table = cx8802_pci_tbl,
879 .probe = blackbird_probe,
880 .remove = __devexit_p(blackbird_remove),
881 .suspend = cx8802_suspend_common,
882 .resume = cx8802_resume_common,
883};
884
885static int blackbird_init(void)
886{
887 printk(KERN_INFO "cx2388x blackbird driver version %d.%d.%d loaded\n",
888 (CX88_VERSION_CODE >> 16) & 0xff,
889 (CX88_VERSION_CODE >> 8) & 0xff,
890 CX88_VERSION_CODE & 0xff);
891#ifdef SNAPSHOT
892 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
893 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
894#endif
895 return pci_register_driver(&blackbird_pci_driver);
896}
897
898static void blackbird_fini(void)
899{
900 pci_unregister_driver(&blackbird_pci_driver);
901}
902
903module_init(blackbird_init);
904module_exit(blackbird_fini);
905
906/* ----------------------------------------------------------- */
907/*
908 * Local variables:
909 * c-basic-offset: 8
910 * End:
911 */
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
new file mode 100644
index 000000000000..367624822d77
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -0,0 +1,938 @@
1/*
2 * $Id: cx88-cards.c,v 1.66 2005/03/04 09:12:23 kraxel Exp $
3 *
4 * device driver for Conexant 2388x based TV cards
5 * card-specific stuff.
6 *
7 * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/init.h>
25#include <linux/module.h>
26#include <linux/pci.h>
27#include <linux/delay.h>
28
29#include "cx88.h"
30
31/* ------------------------------------------------------------------ */
32/* board config info */
33
34struct cx88_board cx88_boards[] = {
35 [CX88_BOARD_UNKNOWN] = {
36 .name = "UNKNOWN/GENERIC",
37 .tuner_type = UNSET,
38 .input = {{
39 .type = CX88_VMUX_COMPOSITE1,
40 .vmux = 0,
41 },{
42 .type = CX88_VMUX_COMPOSITE2,
43 .vmux = 1,
44 },{
45 .type = CX88_VMUX_COMPOSITE3,
46 .vmux = 2,
47 },{
48 .type = CX88_VMUX_COMPOSITE4,
49 .vmux = 3,
50 }},
51 },
52 [CX88_BOARD_HAUPPAUGE] = {
53 .name = "Hauppauge WinTV 34xxx models",
54 .tuner_type = UNSET,
55 .tda9887_conf = TDA9887_PRESENT,
56 .input = {{
57 .type = CX88_VMUX_TELEVISION,
58 .vmux = 0,
59 .gpio0 = 0xff00, // internal decoder
60 },{
61 .type = CX88_VMUX_DEBUG,
62 .vmux = 0,
63 .gpio0 = 0xff01, // mono from tuner chip
64 },{
65 .type = CX88_VMUX_COMPOSITE1,
66 .vmux = 1,
67 .gpio0 = 0xff02,
68 },{
69 .type = CX88_VMUX_SVIDEO,
70 .vmux = 2,
71 .gpio0 = 0xff02,
72 }},
73 .radio = {
74 .type = CX88_RADIO,
75 .gpio0 = 0xff01,
76 },
77 },
78 [CX88_BOARD_GDI] = {
79 .name = "GDI Black Gold",
80 .tuner_type = UNSET,
81 .input = {{
82 .type = CX88_VMUX_TELEVISION,
83 .vmux = 0,
84 }},
85 },
86 [CX88_BOARD_PIXELVIEW] = {
87 .name = "PixelView",
88 .tuner_type = 5,
89 .input = {{
90 .type = CX88_VMUX_TELEVISION,
91 .vmux = 0,
92 .gpio0 = 0xff00, // internal decoder
93 },{
94 .type = CX88_VMUX_COMPOSITE1,
95 .vmux = 1,
96 },{
97 .type = CX88_VMUX_SVIDEO,
98 .vmux = 2,
99 }},
100 .radio = {
101 .type = CX88_RADIO,
102 .gpio0 = 0xff10,
103 },
104 },
105 [CX88_BOARD_ATI_WONDER_PRO] = {
106 .name = "ATI TV Wonder Pro",
107 .tuner_type = 44,
108 .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER,
109 .input = {{
110 .type = CX88_VMUX_TELEVISION,
111 .vmux = 0,
112 .gpio0 = 0x03ff,
113 },{
114 .type = CX88_VMUX_COMPOSITE1,
115 .vmux = 1,
116 .gpio0 = 0x03fe,
117 },{
118 .type = CX88_VMUX_SVIDEO,
119 .vmux = 2,
120 .gpio0 = 0x03fe,
121 }},
122 },
123 [CX88_BOARD_WINFAST2000XP_EXPERT] = {
124 .name = "Leadtek Winfast 2000XP Expert",
125 .tuner_type = 44,
126 .tda9887_conf = TDA9887_PRESENT,
127 .input = {{
128 .type = CX88_VMUX_TELEVISION,
129 .vmux = 0,
130 .gpio0 = 0x00F5e700,
131 .gpio1 = 0x00003004,
132 .gpio2 = 0x00F5e700,
133 .gpio3 = 0x02000000,
134 },{
135 .type = CX88_VMUX_COMPOSITE1,
136 .vmux = 1,
137 .gpio0 = 0x00F5c700,
138 .gpio1 = 0x00003004,
139 .gpio2 = 0x00F5c700,
140 .gpio3 = 0x02000000,
141 },{
142 .type = CX88_VMUX_SVIDEO,
143 .vmux = 2,
144 .gpio0 = 0x00F5c700,
145 .gpio1 = 0x00003004,
146 .gpio2 = 0x00F5c700,
147 .gpio3 = 0x02000000,
148 }},
149 .radio = {
150 .type = CX88_RADIO,
151 .gpio0 = 0x00F5d700,
152 .gpio1 = 0x00003004,
153 .gpio2 = 0x00F5d700,
154 .gpio3 = 0x02000000,
155 },
156 },
157 [CX88_BOARD_AVERTV_303] = {
158 .name = "AverTV Studio 303 (M126)",
159 .tuner_type = 38,
160 .tda9887_conf = TDA9887_PRESENT,
161 .input = {{
162 .type = CX88_VMUX_TELEVISION,
163 .vmux = 0,
164 .gpio1 = 0x309f,
165 },{
166 .type = CX88_VMUX_COMPOSITE1,
167 .vmux = 1,
168 .gpio1 = 0x305f,
169 },{
170 .type = CX88_VMUX_SVIDEO,
171 .vmux = 2,
172 .gpio1 = 0x305f,
173 }},
174 .radio = {
175 .type = CX88_RADIO,
176 },
177 },
178 [CX88_BOARD_MSI_TVANYWHERE_MASTER] = {
179 // added gpio values thanks to Michal
180 // values for PAL from DScaler
181 .name = "MSI TV-@nywhere Master",
182 .tuner_type = 33,
183 .tda9887_conf = TDA9887_PRESENT,
184 .input = {{
185 .type = CX88_VMUX_TELEVISION,
186 .vmux = 0,
187 .gpio0 = 0x000040bf,
188 .gpio1 = 0x000080c0,
189 .gpio2 = 0x0000ff40,
190 },{
191 .type = CX88_VMUX_COMPOSITE1,
192 .vmux = 1,
193 .gpio0 = 0x000040bf,
194 .gpio1 = 0x000080c0,
195 .gpio2 = 0x0000ff40,
196 },{
197 .type = CX88_VMUX_SVIDEO,
198 .vmux = 2,
199 .gpio0 = 0x000040bf,
200 .gpio1 = 0x000080c0,
201 .gpio2 = 0x0000ff40,
202 }},
203 .radio = {
204 .type = CX88_RADIO,
205 },
206 },
207 [CX88_BOARD_WINFAST_DV2000] = {
208 .name = "Leadtek Winfast DV2000",
209 .tuner_type = 38,
210 .tda9887_conf = TDA9887_PRESENT,
211 .input = {{
212 .type = CX88_VMUX_TELEVISION,
213 .vmux = 0,
214 .gpio0 = 0x0035e700,
215 .gpio1 = 0x00003004,
216 .gpio2 = 0x0035e700,
217 .gpio3 = 0x02000000,
218 },{
219
220 .type = CX88_VMUX_COMPOSITE1,
221 .vmux = 1,
222 .gpio0 = 0x0035c700,
223 .gpio1 = 0x00003004,
224 .gpio2 = 0x0035c700,
225 .gpio3 = 0x02000000,
226 },{
227 .type = CX88_VMUX_SVIDEO,
228 .vmux = 2,
229 .gpio0 = 0x0035c700,
230 .gpio1 = 0x0035c700,
231 .gpio2 = 0x02000000,
232 .gpio3 = 0x02000000,
233 }},
234 .radio = {
235 .type = CX88_RADIO,
236 .gpio0 = 0x0035d700,
237 .gpio1 = 0x00007004,
238 .gpio2 = 0x0035d700,
239 .gpio3 = 0x02000000,
240 },
241 },
242 [CX88_BOARD_LEADTEK_PVR2000] = {
243 // gpio values for PAL version from regspy by DScaler
244 .name = "Leadtek PVR 2000",
245 .tuner_type = 38,
246 .tda9887_conf = TDA9887_PRESENT,
247 .input = {{
248 .type = CX88_VMUX_TELEVISION,
249 .vmux = 0,
250 .gpio0 = 0x0000bde6,
251 },{
252 .type = CX88_VMUX_COMPOSITE1,
253 .vmux = 1,
254 .gpio0 = 0x0000bde6,
255 },{
256 .type = CX88_VMUX_SVIDEO,
257 .vmux = 2,
258 .gpio0 = 0x0000bde6,
259 }},
260 .radio = {
261 .type = CX88_RADIO,
262 .gpio0 = 0x0000bd62,
263 },
264 .blackbird = 1,
265 },
266 [CX88_BOARD_IODATA_GVVCP3PCI] = {
267 .name = "IODATA GV-VCP3/PCI",
268 .tuner_type = TUNER_ABSENT,
269 .input = {{
270 .type = CX88_VMUX_COMPOSITE1,
271 .vmux = 0,
272 },{
273 .type = CX88_VMUX_COMPOSITE2,
274 .vmux = 1,
275 },{
276 .type = CX88_VMUX_SVIDEO,
277 .vmux = 2,
278 }},
279 },
280 [CX88_BOARD_PROLINK_PLAYTVPVR] = {
281 .name = "Prolink PlayTV PVR",
282 .tuner_type = 43,
283 .tda9887_conf = TDA9887_PRESENT,
284 .input = {{
285 .type = CX88_VMUX_TELEVISION,
286 .vmux = 0,
287 .gpio0 = 0xff00,
288 },{
289 .type = CX88_VMUX_COMPOSITE1,
290 .vmux = 1,
291 .gpio0 = 0xff03,
292 },{
293 .type = CX88_VMUX_SVIDEO,
294 .vmux = 2,
295 .gpio0 = 0xff03,
296 }},
297 .radio = {
298 .type = CX88_RADIO,
299 .gpio0 = 0xff00,
300 },
301 },
302 [CX88_BOARD_ASUS_PVR_416] = {
303 .name = "ASUS PVR-416",
304 .tuner_type = 43,
305 .tda9887_conf = TDA9887_PRESENT,
306 .input = {{
307 .type = CX88_VMUX_TELEVISION,
308 .vmux = 0,
309 .gpio0 = 0x0000fde6,
310 },{
311 .type = CX88_VMUX_SVIDEO,
312 .vmux = 2,
313 .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in?
314 }},
315 .radio = {
316 .type = CX88_RADIO,
317 .gpio0 = 0x0000fde2,
318 },
319 .blackbird = 1,
320 },
321 [CX88_BOARD_MSI_TVANYWHERE] = {
322 .name = "MSI TV-@nywhere",
323 .tuner_type = 33,
324 .tda9887_conf = TDA9887_PRESENT,
325 .input = {{
326 .type = CX88_VMUX_TELEVISION,
327 .vmux = 0,
328 .gpio0 = 0x00000fbf,
329 .gpio2 = 0x0000fc08,
330 },{
331 .type = CX88_VMUX_COMPOSITE1,
332 .vmux = 1,
333 .gpio0 = 0x00000fbf,
334 .gpio2 = 0x0000fc68,
335 },{
336 .type = CX88_VMUX_SVIDEO,
337 .vmux = 2,
338 .gpio0 = 0x00000fbf,
339 .gpio2 = 0x0000fc68,
340 }},
341 },
342 [CX88_BOARD_KWORLD_DVB_T] = {
343 .name = "KWorld/VStream XPert DVB-T",
344 .tuner_type = TUNER_ABSENT,
345 .input = {{
346 .type = CX88_VMUX_COMPOSITE1,
347 .vmux = 1,
348 .gpio0 = 0x0700,
349 .gpio2 = 0x0101,
350 },{
351 .type = CX88_VMUX_SVIDEO,
352 .vmux = 2,
353 .gpio0 = 0x0700,
354 .gpio2 = 0x0101,
355 }},
356 .dvb = 1,
357 },
358 [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
359 .name = "DVICO FusionHDTV DVB-T1",
360 .tuner_type = TUNER_ABSENT, /* No analog tuner */
361 .input = {{
362 .type = CX88_VMUX_COMPOSITE1,
363 .vmux = 1,
364 .gpio0 = 0x000027df,
365 },{
366 .type = CX88_VMUX_SVIDEO,
367 .vmux = 2,
368 .gpio0 = 0x000027df,
369 }},
370 .dvb = 1,
371 },
372 [CX88_BOARD_KWORLD_LTV883] = {
373 .name = "KWorld LTV883RF",
374 .tuner_type = 48,
375 .input = {{
376 .type = CX88_VMUX_TELEVISION,
377 .vmux = 0,
378 .gpio0 = 0x07f8,
379 },{
380 .type = CX88_VMUX_DEBUG,
381 .vmux = 0,
382 .gpio0 = 0x07f9, // mono from tuner chip
383 },{
384 .type = CX88_VMUX_COMPOSITE1,
385 .vmux = 1,
386 .gpio0 = 0x000007fa,
387 },{
388 .type = CX88_VMUX_SVIDEO,
389 .vmux = 2,
390 .gpio0 = 0x000007fa,
391 }},
392 .radio = {
393 .type = CX88_RADIO,
394 .gpio0 = 0x000007f8,
395 },
396 },
397 [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD] = {
398 .name = "DViCO - FusionHDTV 3 Gold",
399 .tuner_type = TUNER_MICROTUNE_4042FI5,
400 /*
401 GPIO[0] resets DT3302 DTV receiver
402 0 - reset asserted
403 1 - normal operation
404 GPIO[1] mutes analog audio output connector
405 0 - enable selected source
406 1 - mute
407 GPIO[2] selects source for analog audio output connector
408 0 - analog audio input connector on tab
409 1 - analog DAC output from CX23881 chip
410 GPIO[3] selects RF input connector on tuner module
411 0 - RF connector labeled CABLE
412 1 - RF connector labeled ANT
413 */
414 .input = {{
415 .type = CX88_VMUX_TELEVISION,
416 .vmux = 0,
417 .gpio0 = 0x0f0d,
418 },{
419 .type = CX88_VMUX_CABLE,
420 .vmux = 0,
421 .gpio0 = 0x0f05,
422 },{
423 .type = CX88_VMUX_COMPOSITE1,
424 .vmux = 1,
425 .gpio0 = 0x0f00,
426 },{
427 .type = CX88_VMUX_SVIDEO,
428 .vmux = 2,
429 .gpio0 = 0x0f00,
430 }},
431#if 0
432 .ts = {
433 .type = CX88_TS,
434 .gpio0 = 0x00000f01, /* Hooked to tuner reset bit */
435 }
436#endif
437 },
438 [CX88_BOARD_HAUPPAUGE_DVB_T1] = {
439 .name = "Hauppauge Nova-T DVB-T",
440 .tuner_type = TUNER_ABSENT,
441 .input = {{
442 .type = CX88_VMUX_DVB,
443 .vmux = 0,
444 }},
445 .dvb = 1,
446 },
447 [CX88_BOARD_CONEXANT_DVB_T1] = {
448 .name = "Conexant DVB-T reference design",
449 .tuner_type = TUNER_ABSENT,
450 .input = {{
451 .type = CX88_VMUX_DVB,
452 .vmux = 0,
453 }},
454 .dvb = 1,
455 },
456 [CX88_BOARD_PROVIDEO_PV259] = {
457 .name = "Provideo PV259",
458 .tuner_type = TUNER_PHILIPS_FQ1216ME,
459 .input = {{
460 .type = CX88_VMUX_TELEVISION,
461 .vmux = 0,
462 }},
463 .blackbird = 1,
464 },
465 [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
466 .name = "DVICO FusionHDTV DVB-T Plus",
467 .tuner_type = TUNER_ABSENT, /* No analog tuner */
468 .input = {{
469 .type = CX88_VMUX_COMPOSITE1,
470 .vmux = 1,
471 .gpio0 = 0x000027df,
472 },{
473 .type = CX88_VMUX_SVIDEO,
474 .vmux = 2,
475 .gpio0 = 0x000027df,
476 }},
477 .dvb = 1,
478 },
479 [CX88_BOARD_DNTV_LIVE_DVB_T] = {
480 .name = "digitalnow DNTV Live! DVB-T",
481 .tuner_type = TUNER_ABSENT,
482 .input = {{
483 .type = CX88_VMUX_COMPOSITE1,
484 .vmux = 1,
485 .gpio0 = 0x00000700,
486 .gpio2 = 0x00000101,
487 },{
488 .type = CX88_VMUX_SVIDEO,
489 .vmux = 2,
490 .gpio0 = 0x00000700,
491 .gpio2 = 0x00000101,
492 }},
493 .dvb = 1,
494 },
495 [CX88_BOARD_PCHDTV_HD3000] = {
496 .name = "pcHDTV HD3000 HDTV",
497 .tuner_type = TUNER_THOMSON_DTT7610,
498 .input = {{
499 .type = CX88_VMUX_TELEVISION,
500 .vmux = 0,
501 .gpio0 = 0x00008484,
502 .gpio1 = 0x00000000,
503 .gpio2 = 0x00000000,
504 .gpio3 = 0x00000000,
505 },{
506 .type = CX88_VMUX_COMPOSITE1,
507 .vmux = 1,
508 .gpio0 = 0x00008400,
509 .gpio1 = 0x00000000,
510 .gpio2 = 0x00000000,
511 .gpio3 = 0x00000000,
512 },{
513 .type = CX88_VMUX_SVIDEO,
514 .vmux = 2,
515 .gpio0 = 0x00008400,
516 .gpio1 = 0x00000000,
517 .gpio2 = 0x00000000,
518 .gpio3 = 0x00000000,
519 }},
520 .radio = {
521 .type = CX88_RADIO,
522 .vmux = 2,
523 .gpio0 = 0x00008400,
524 .gpio1 = 0x00000000,
525 .gpio2 = 0x00000000,
526 .gpio3 = 0x00000000,
527 },
528 .dvb = 1,
529 },
530 [CX88_BOARD_HAUPPAUGE_ROSLYN] = {
531 // entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu>
532 // GPIO values obtained from regspy, courtesy Sean Covel
533 .name = "Hauppauge WinTV 28xxx (Roslyn) models",
534 .tuner_type = UNSET,
535 .input = {{
536 .type = CX88_VMUX_TELEVISION,
537 .vmux = 0,
538 .gpio0 = 0xed12, // internal decoder
539 .gpio2 = 0x00ff,
540 },{
541 .type = CX88_VMUX_DEBUG,
542 .vmux = 0,
543 .gpio0 = 0xff01, // mono from tuner chip
544 },{
545 .type = CX88_VMUX_COMPOSITE1,
546 .vmux = 1,
547 .gpio0 = 0xff02,
548 },{
549 .type = CX88_VMUX_SVIDEO,
550 .vmux = 2,
551 .gpio0 = 0xed92,
552 .gpio2 = 0x00ff,
553 }},
554 .radio = {
555 .type = CX88_RADIO,
556 .gpio0 = 0xed96,
557 .gpio2 = 0x00ff,
558 },
559 .blackbird = 1,
560 },
561 [CX88_BOARD_DIGITALLOGIC_MEC] = {
562 /* params copied over from Leadtek PVR 2000 */
563 .name = "Digital-Logic MICROSPACE Entertainment Center (MEC)",
564 /* not sure yet about the tuner type */
565 .tuner_type = 38,
566 .tda9887_conf = TDA9887_PRESENT,
567 .input = {{
568 .type = CX88_VMUX_TELEVISION,
569 .vmux = 0,
570 .gpio0 = 0x0000bde6,
571 },{
572 .type = CX88_VMUX_COMPOSITE1,
573 .vmux = 1,
574 .gpio0 = 0x0000bde6,
575 },{
576 .type = CX88_VMUX_SVIDEO,
577 .vmux = 2,
578 .gpio0 = 0x0000bde6,
579 }},
580 .radio = {
581 .type = CX88_RADIO,
582 .gpio0 = 0x0000bd62,
583 },
584 .blackbird = 1,
585 },
586 [CX88_BOARD_IODATA_GVBCTV7E] = {
587 .name = "IODATA GV/BCTV7E",
588 .tuner_type = TUNER_PHILIPS_FQ1286,
589 .tda9887_conf = TDA9887_PRESENT,
590 .input = {{
591 .type = CX88_VMUX_TELEVISION,
592 .vmux = 1,
593 .gpio1 = 0x0000e03f,
594 },{
595 .type = CX88_VMUX_COMPOSITE1,
596 .vmux = 2,
597 .gpio1 = 0x0000e07f,
598 },{
599 .type = CX88_VMUX_SVIDEO,
600 .vmux = 3,
601 .gpio1 = 0x0000e07f,
602 }}
603 },
604};
605const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
606
607/* ------------------------------------------------------------------ */
608/* PCI subsystem IDs */
609
610struct cx88_subid cx88_subids[] = {
611 {
612 .subvendor = 0x0070,
613 .subdevice = 0x3400,
614 .card = CX88_BOARD_HAUPPAUGE,
615 },{
616 .subvendor = 0x0070,
617 .subdevice = 0x3401,
618 .card = CX88_BOARD_HAUPPAUGE,
619 },{
620 .subvendor = 0x14c7,
621 .subdevice = 0x0106,
622 .card = CX88_BOARD_GDI,
623 },{
624 .subvendor = 0x14c7,
625 .subdevice = 0x0107, /* with mpeg encoder */
626 .card = CX88_BOARD_GDI,
627 },{
628 .subvendor = PCI_VENDOR_ID_ATI,
629 .subdevice = 0x00f8,
630 .card = CX88_BOARD_ATI_WONDER_PRO,
631 },{
632 .subvendor = 0x107d,
633 .subdevice = 0x6611,
634 .card = CX88_BOARD_WINFAST2000XP_EXPERT,
635 },{
636 .subvendor = 0x107d,
637 .subdevice = 0x6613, /* NTSC */
638 .card = CX88_BOARD_WINFAST2000XP_EXPERT,
639 },{
640 .subvendor = 0x107d,
641 .subdevice = 0x6620,
642 .card = CX88_BOARD_WINFAST_DV2000,
643 },{
644 .subvendor = 0x107d,
645 .subdevice = 0x663b,
646 .card = CX88_BOARD_LEADTEK_PVR2000,
647 },{
648 .subvendor = 0x107d,
649 .subdevice = 0x663C,
650 .card = CX88_BOARD_LEADTEK_PVR2000,
651 },{
652 .subvendor = 0x1461,
653 .subdevice = 0x000b,
654 .card = CX88_BOARD_AVERTV_303,
655 },{
656 .subvendor = 0x1462,
657 .subdevice = 0x8606,
658 .card = CX88_BOARD_MSI_TVANYWHERE_MASTER,
659 },{
660 .subvendor = 0x10fc,
661 .subdevice = 0xd003,
662 .card = CX88_BOARD_IODATA_GVVCP3PCI,
663 },{
664 .subvendor = 0x1043,
665 .subdevice = 0x4823, /* with mpeg encoder */
666 .card = CX88_BOARD_ASUS_PVR_416,
667 },{
668 .subvendor = 0x17de,
669 .subdevice = 0x08a6,
670 .card = CX88_BOARD_KWORLD_DVB_T,
671 },{
672 .subvendor = 0x18ac,
673 .subdevice = 0xd810,
674 .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD,
675 },{
676 .subvendor = 0x18AC,
677 .subdevice = 0xDB00,
678 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1,
679 },{
680 .subvendor = 0x0070,
681 .subdevice = 0x9002,
682 .card = CX88_BOARD_HAUPPAUGE_DVB_T1,
683 },{
684 .subvendor = 0x14f1,
685 .subdevice = 0x0187,
686 .card = CX88_BOARD_CONEXANT_DVB_T1,
687 },{
688 .subvendor = 0x1540,
689 .subdevice = 0x2580,
690 .card = CX88_BOARD_PROVIDEO_PV259,
691 },{
692 .subvendor = 0x18AC,
693 .subdevice = 0xDB10,
694 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
695 },{
696 .subvendor = 0x1554,
697 .subdevice = 0x4811,
698 .card = CX88_BOARD_PIXELVIEW,
699 },{
700 .subvendor = 0x7063,
701 .subdevice = 0x3000, /* HD-3000 card */
702 .card = CX88_BOARD_PCHDTV_HD3000,
703 },{
704 .subvendor = 0x17DE,
705 .subdevice = 0xA8A6,
706 .card = CX88_BOARD_DNTV_LIVE_DVB_T,
707 },{
708 .subvendor = 0x0070,
709 .subdevice = 0x2801,
710 .card = CX88_BOARD_HAUPPAUGE_ROSLYN,
711 },{
712 .subvendor = 0x14F1,
713 .subdevice = 0x0342,
714 .card = CX88_BOARD_DIGITALLOGIC_MEC,
715 },{
716 .subvendor = 0x10fc,
717 .subdevice = 0xd035,
718 .card = CX88_BOARD_IODATA_GVBCTV7E,
719 }
720};
721const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
722
723/* ----------------------------------------------------------------------- */
724/* some leadtek specific stuff */
725
726static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
727{
728 /* This is just for the "Winfast 2000XP Expert" board ATM; I don't have data on
729 * any others.
730 *
731 * Byte 0 is 1 on the NTSC board.
732 */
733
734 if (eeprom_data[4] != 0x7d ||
735 eeprom_data[5] != 0x10 ||
736 eeprom_data[7] != 0x66) {
737 printk(KERN_WARNING "%s: Leadtek eeprom invalid.\n",
738 core->name);
739 return;
740 }
741
742 core->has_radio = 1;
743 core->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38;
744
745 printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: "
746 "tuner=%d, eeprom[0]=0x%02x\n",
747 core->name, core->tuner_type, eeprom_data[0]);
748}
749
750
751/* ----------------------------------------------------------------------- */
752
753static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
754{
755 struct tveeprom tv;
756
757 tveeprom_hauppauge_analog(&tv, eeprom_data);
758 core->tuner_type = tv.tuner_type;
759 core->has_radio = tv.has_radio;
760}
761
762static int hauppauge_eeprom_dvb(struct cx88_core *core, u8 *ee)
763{
764 int model;
765 int tuner;
766
767 /* Make sure we support the board model */
768 model = ee[0x1f] << 24 | ee[0x1e] << 16 | ee[0x1d] << 8 | ee[0x1c];
769 switch(model) {
770 case 90002:
771 case 90500:
772 case 90501:
773 /* known */
774 break;
775 default:
776 printk("%s: warning: unknown hauppauge model #%d\n",
777 core->name, model);
778 break;
779 }
780
781 /* Make sure we support the tuner */
782 tuner = ee[0x2d];
783 switch(tuner) {
784 case 0x4B: /* dtt 7595 */
785 case 0x4C: /* dtt 7592 */
786 break;
787 default:
788 printk("%s: error: unknown hauppauge tuner 0x%02x\n",
789 core->name, tuner);
790 return -ENODEV;
791 }
792 printk(KERN_INFO "%s: hauppauge eeprom: model=%d, tuner=%d\n",
793 core->name, model, tuner);
794 return 0;
795}
796
797/* ----------------------------------------------------------------------- */
798/* some GDI (was: Modular Technology) specific stuff */
799
800static struct {
801 int id;
802 int fm;
803 char *name;
804} gdi_tuner[] = {
805 [ 0x01 ] = { .id = TUNER_ABSENT,
806 .name = "NTSC_M" },
807 [ 0x02 ] = { .id = TUNER_ABSENT,
808 .name = "PAL_B" },
809 [ 0x03 ] = { .id = TUNER_ABSENT,
810 .name = "PAL_I" },
811 [ 0x04 ] = { .id = TUNER_ABSENT,
812 .name = "PAL_D" },
813 [ 0x05 ] = { .id = TUNER_ABSENT,
814 .name = "SECAM" },
815
816 [ 0x10 ] = { .id = TUNER_ABSENT,
817 .fm = 1,
818 .name = "TEMIC_4049" },
819 [ 0x11 ] = { .id = TUNER_TEMIC_4136FY5,
820 .name = "TEMIC_4136" },
821 [ 0x12 ] = { .id = TUNER_ABSENT,
822 .name = "TEMIC_4146" },
823
824 [ 0x20 ] = { .id = TUNER_PHILIPS_FQ1216ME,
825 .fm = 1,
826 .name = "PHILIPS_FQ1216_MK3" },
827 [ 0x21 ] = { .id = TUNER_ABSENT, .fm = 1,
828 .name = "PHILIPS_FQ1236_MK3" },
829 [ 0x22 ] = { .id = TUNER_ABSENT,
830 .name = "PHILIPS_FI1236_MK3" },
831 [ 0x23 ] = { .id = TUNER_ABSENT,
832 .name = "PHILIPS_FI1216_MK3" },
833};
834
835static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
836{
837 char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner))
838 ? gdi_tuner[eeprom_data[0x0d]].name : NULL;
839
840 printk(KERN_INFO "%s: GDI: tuner=%s\n", core->name,
841 name ? name : "unknown");
842 if (NULL == name)
843 return;
844 core->tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
845 core->has_radio = gdi_tuner[eeprom_data[0x0d]].fm;
846}
847
848/* ----------------------------------------------------------------------- */
849
850void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
851{
852 int i;
853
854 if (0 == pci->subsystem_vendor &&
855 0 == pci->subsystem_device) {
856 printk("%s: Your board has no valid PCI Subsystem ID and thus can't\n"
857 "%s: be autodetected. Please pass card=<n> insmod option to\n"
858 "%s: workaround that. Redirect complaints to the vendor of\n"
859 "%s: the TV card. Best regards,\n"
860 "%s: -- tux\n",
861 core->name,core->name,core->name,core->name,core->name);
862 } else {
863 printk("%s: Your board isn't known (yet) to the driver. You can\n"
864 "%s: try to pick one of the existing card configs via\n"
865 "%s: card=<n> insmod option. Updating to the latest\n"
866 "%s: version might help as well.\n",
867 core->name,core->name,core->name,core->name);
868 }
869 printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
870 core->name);
871 for (i = 0; i < cx88_bcount; i++)
872 printk("%s: card=%d -> %s\n",
873 core->name, i, cx88_boards[i].name);
874}
875
876void cx88_card_setup(struct cx88_core *core)
877{
878 static u8 eeprom[128];
879
880 if (0 == core->i2c_rc) {
881 core->i2c_client.addr = 0xa0 >> 1;
882 tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom));
883 }
884
885 switch (core->board) {
886 case CX88_BOARD_HAUPPAUGE:
887 case CX88_BOARD_HAUPPAUGE_ROSLYN:
888 if (0 == core->i2c_rc)
889 hauppauge_eeprom(core,eeprom+8);
890 break;
891 case CX88_BOARD_GDI:
892 if (0 == core->i2c_rc)
893 gdi_eeprom(core,eeprom);
894 break;
895 case CX88_BOARD_WINFAST2000XP_EXPERT:
896 if (0 == core->i2c_rc)
897 leadtek_eeprom(core,eeprom);
898 break;
899 case CX88_BOARD_HAUPPAUGE_DVB_T1:
900 if (0 == core->i2c_rc)
901 hauppauge_eeprom_dvb(core,eeprom);
902 break;
903 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
904 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
905 /* GPIO0:0 is hooked to mt352 reset pin */
906 cx_set(MO_GP0_IO, 0x00000101);
907 cx_clear(MO_GP0_IO, 0x00000001);
908 msleep(1);
909 cx_set(MO_GP0_IO, 0x00000101);
910 break;
911 case CX88_BOARD_KWORLD_DVB_T:
912 case CX88_BOARD_DNTV_LIVE_DVB_T:
913 cx_set(MO_GP0_IO, 0x00000707);
914 cx_set(MO_GP2_IO, 0x00000101);
915 cx_clear(MO_GP2_IO, 0x00000001);
916 msleep(1);
917 cx_clear(MO_GP0_IO, 0x00000007);
918 cx_set(MO_GP2_IO, 0x00000101);
919 break;
920 }
921 if (cx88_boards[core->board].radio.type == CX88_RADIO)
922 core->has_radio = 1;
923}
924
925/* ------------------------------------------------------------------ */
926
927EXPORT_SYMBOL(cx88_boards);
928EXPORT_SYMBOL(cx88_bcount);
929EXPORT_SYMBOL(cx88_subids);
930EXPORT_SYMBOL(cx88_idcount);
931EXPORT_SYMBOL(cx88_card_list);
932EXPORT_SYMBOL(cx88_card_setup);
933
934/*
935 * Local variables:
936 * c-basic-offset: 8
937 * End:
938 */
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
new file mode 100644
index 000000000000..26a6138015cb
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -0,0 +1,1239 @@
1/*
2 * $Id: cx88-core.c,v 1.24 2005/01/19 12:01:55 kraxel Exp $
3 *
4 * device driver for Conexant 2388x based TV cards
5 * driver core
6 *
7 * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/init.h>
25#include <linux/list.h>
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/kernel.h>
29#include <linux/slab.h>
30#include <linux/kmod.h>
31#include <linux/sound.h>
32#include <linux/interrupt.h>
33#include <linux/pci.h>
34#include <linux/delay.h>
35#include <linux/videodev.h>
36
37#include "cx88.h"
38
39MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
40MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
41MODULE_LICENSE("GPL");
42
43/* ------------------------------------------------------------------ */
44
45static unsigned int core_debug = 0;
46module_param(core_debug,int,0644);
47MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
48
49static unsigned int latency = UNSET;
50module_param(latency,int,0444);
51MODULE_PARM_DESC(latency,"pci latency timer");
52
53static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
54static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
55
56module_param_array(tuner, int, NULL, 0444);
57module_param_array(card, int, NULL, 0444);
58
59MODULE_PARM_DESC(tuner,"tuner type");
60MODULE_PARM_DESC(card,"card type");
61
62static unsigned int nicam = 0;
63module_param(nicam,int,0644);
64MODULE_PARM_DESC(nicam,"tv audio is nicam");
65
66static unsigned int nocomb = 0;
67module_param(nocomb,int,0644);
68MODULE_PARM_DESC(nocomb,"disable comb filter");
69
70#define dprintk(level,fmt, arg...) if (core_debug >= level) \
71 printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
72
73static unsigned int cx88_devcount;
74static LIST_HEAD(cx88_devlist);
75static DECLARE_MUTEX(devlist);
76
77/* ------------------------------------------------------------------ */
78/* debug help functions */
79
80static const char *v4l1_ioctls[] = {
81 "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
82 "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
83 "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
84 "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
85 "SMICROCODE", "GVBIFMT", "SVBIFMT" };
86#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
87
88static const char *v4l2_ioctls[] = {
89 "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
90 "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
91 "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
92 "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
93 "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
94 "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
95 "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
96 "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
97 "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
98 "S_MODULATOR"
99};
100#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
101
102void cx88_print_ioctl(char *name, unsigned int cmd)
103{
104 char *dir;
105
106 switch (_IOC_DIR(cmd)) {
107 case _IOC_NONE: dir = "--"; break;
108 case _IOC_READ: dir = "r-"; break;
109 case _IOC_WRITE: dir = "-w"; break;
110 case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
111 default: dir = "??"; break;
112 }
113 switch (_IOC_TYPE(cmd)) {
114 case 'v':
115 printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
116 name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
117 v4l1_ioctls[_IOC_NR(cmd)] : "???");
118 break;
119 case 'V':
120 printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
121 name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
122 v4l2_ioctls[_IOC_NR(cmd)] : "???");
123 break;
124 default:
125 printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
126 name, cmd, dir, _IOC_NR(cmd));
127 }
128}
129
130/* ------------------------------------------------------------------ */
131#define NO_SYNC_LINE (-1U)
132
133static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
134 unsigned int offset, u32 sync_line,
135 unsigned int bpl, unsigned int padding,
136 unsigned int lines)
137{
138 struct scatterlist *sg;
139 unsigned int line,todo;
140
141 /* sync instruction */
142 if (sync_line != NO_SYNC_LINE)
143 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
144
145 /* scan lines */
146 sg = sglist;
147 for (line = 0; line < lines; line++) {
148 while (offset && offset >= sg_dma_len(sg)) {
149 offset -= sg_dma_len(sg);
150 sg++;
151 }
152 if (bpl <= sg_dma_len(sg)-offset) {
153 /* fits into current chunk */
154 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
155 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
156 offset+=bpl;
157 } else {
158 /* scanline needs to be splitted */
159 todo = bpl;
160 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|
161 (sg_dma_len(sg)-offset));
162 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
163 todo -= (sg_dma_len(sg)-offset);
164 offset = 0;
165 sg++;
166 while (todo > sg_dma_len(sg)) {
167 *(rp++)=cpu_to_le32(RISC_WRITE|
168 sg_dma_len(sg));
169 *(rp++)=cpu_to_le32(sg_dma_address(sg));
170 todo -= sg_dma_len(sg);
171 sg++;
172 }
173 *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
174 *(rp++)=cpu_to_le32(sg_dma_address(sg));
175 offset += todo;
176 }
177 offset += padding;
178 }
179
180 return rp;
181}
182
183int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
184 struct scatterlist *sglist,
185 unsigned int top_offset, unsigned int bottom_offset,
186 unsigned int bpl, unsigned int padding, unsigned int lines)
187{
188 u32 instructions,fields;
189 u32 *rp;
190 int rc;
191
192 fields = 0;
193 if (UNSET != top_offset)
194 fields++;
195 if (UNSET != bottom_offset)
196 fields++;
197
198 /* estimate risc mem: worst case is one write per page border +
199 one write per scan line + syncs + jump (all 2 dwords) */
200 instructions = (bpl * lines * fields) / PAGE_SIZE + lines * fields;
201 instructions += 3 + 4;
202 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
203 return rc;
204
205 /* write risc instructions */
206 rp = risc->cpu;
207 if (UNSET != top_offset)
208 rp = cx88_risc_field(rp, sglist, top_offset, 0,
209 bpl, padding, lines);
210 if (UNSET != bottom_offset)
211 rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
212 bpl, padding, lines);
213
214 /* save pointer to jmp instruction address */
215 risc->jmp = rp;
216 BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
217 return 0;
218}
219
220int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
221 struct scatterlist *sglist, unsigned int bpl,
222 unsigned int lines)
223{
224 u32 instructions;
225 u32 *rp;
226 int rc;
227
228 /* estimate risc mem: worst case is one write per page border +
229 one write per scan line + syncs + jump (all 2 dwords) */
230 instructions = (bpl * lines) / PAGE_SIZE + lines;
231 instructions += 3 + 4;
232 if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
233 return rc;
234
235 /* write risc instructions */
236 rp = risc->cpu;
237 rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
238
239 /* save pointer to jmp instruction address */
240 risc->jmp = rp;
241 BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
242 return 0;
243}
244
245int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
246 u32 reg, u32 mask, u32 value)
247{
248 u32 *rp;
249 int rc;
250
251 if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
252 return rc;
253
254 /* write risc instructions */
255 rp = risc->cpu;
256 *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2 | RISC_IMM);
257 *(rp++) = cpu_to_le32(reg);
258 *(rp++) = cpu_to_le32(value);
259 *(rp++) = cpu_to_le32(mask);
260 *(rp++) = cpu_to_le32(RISC_JUMP);
261 *(rp++) = cpu_to_le32(risc->dma);
262 return 0;
263}
264
265void
266cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf)
267{
268 if (in_interrupt())
269 BUG();
270 videobuf_waiton(&buf->vb,0,0);
271 videobuf_dma_pci_unmap(pci, &buf->vb.dma);
272 videobuf_dma_free(&buf->vb.dma);
273 btcx_riscmem_free(pci, &buf->risc);
274 buf->vb.state = STATE_NEEDS_INIT;
275}
276
277/* ------------------------------------------------------------------ */
278/* our SRAM memory layout */
279
280/* we are going to put all thr risc programs into host memory, so we
281 * can use the whole SDRAM for the DMA fifos. To simplify things, we
282 * use a static memory layout. That surely will waste memory in case
283 * we don't use all DMA channels at the same time (which will be the
284 * case most of the time). But that still gives us enougth FIFO space
285 * to be able to deal with insane long pci latencies ...
286 *
287 * FIFO space allocations:
288 * channel 21 (y video) - 10.0k
289 * channel 22 (u video) - 2.0k
290 * channel 23 (v video) - 2.0k
291 * channel 24 (vbi) - 4.0k
292 * channels 25+26 (audio) - 0.5k
293 * channel 28 (mpeg) - 4.0k
294 * TOTAL = 25.5k
295 *
296 * Every channel has 160 bytes control data (64 bytes instruction
297 * queue and 6 CDT entries), which is close to 2k total.
298 *
299 * Address layout:
300 * 0x0000 - 0x03ff CMDs / reserved
301 * 0x0400 - 0x0bff instruction queues + CDs
302 * 0x0c00 - FIFOs
303 */
304
305struct sram_channel cx88_sram_channels[] = {
306 [SRAM_CH21] = {
307 .name = "video y / packed",
308 .cmds_start = 0x180040,
309 .ctrl_start = 0x180400,
310 .cdt = 0x180400 + 64,
311 .fifo_start = 0x180c00,
312 .fifo_size = 0x002800,
313 .ptr1_reg = MO_DMA21_PTR1,
314 .ptr2_reg = MO_DMA21_PTR2,
315 .cnt1_reg = MO_DMA21_CNT1,
316 .cnt2_reg = MO_DMA21_CNT2,
317 },
318 [SRAM_CH22] = {
319 .name = "video u",
320 .cmds_start = 0x180080,
321 .ctrl_start = 0x1804a0,
322 .cdt = 0x1804a0 + 64,
323 .fifo_start = 0x183400,
324 .fifo_size = 0x000800,
325 .ptr1_reg = MO_DMA22_PTR1,
326 .ptr2_reg = MO_DMA22_PTR2,
327 .cnt1_reg = MO_DMA22_CNT1,
328 .cnt2_reg = MO_DMA22_CNT2,
329 },
330 [SRAM_CH23] = {
331 .name = "video v",
332 .cmds_start = 0x1800c0,
333 .ctrl_start = 0x180540,
334 .cdt = 0x180540 + 64,
335 .fifo_start = 0x183c00,
336 .fifo_size = 0x000800,
337 .ptr1_reg = MO_DMA23_PTR1,
338 .ptr2_reg = MO_DMA23_PTR2,
339 .cnt1_reg = MO_DMA23_CNT1,
340 .cnt2_reg = MO_DMA23_CNT2,
341 },
342 [SRAM_CH24] = {
343 .name = "vbi",
344 .cmds_start = 0x180100,
345 .ctrl_start = 0x1805e0,
346 .cdt = 0x1805e0 + 64,
347 .fifo_start = 0x184400,
348 .fifo_size = 0x001000,
349 .ptr1_reg = MO_DMA24_PTR1,
350 .ptr2_reg = MO_DMA24_PTR2,
351 .cnt1_reg = MO_DMA24_CNT1,
352 .cnt2_reg = MO_DMA24_CNT2,
353 },
354 [SRAM_CH25] = {
355 .name = "audio from",
356 .cmds_start = 0x180140,
357 .ctrl_start = 0x180680,
358 .cdt = 0x180680 + 64,
359 .fifo_start = 0x185400,
360 .fifo_size = 0x000200,
361 .ptr1_reg = MO_DMA25_PTR1,
362 .ptr2_reg = MO_DMA25_PTR2,
363 .cnt1_reg = MO_DMA25_CNT1,
364 .cnt2_reg = MO_DMA25_CNT2,
365 },
366 [SRAM_CH26] = {
367 .name = "audio to",
368 .cmds_start = 0x180180,
369 .ctrl_start = 0x180720,
370 .cdt = 0x180680 + 64, /* same as audio IN */
371 .fifo_start = 0x185400, /* same as audio IN */
372 .fifo_size = 0x000200, /* same as audio IN */
373 .ptr1_reg = MO_DMA26_PTR1,
374 .ptr2_reg = MO_DMA26_PTR2,
375 .cnt1_reg = MO_DMA26_CNT1,
376 .cnt2_reg = MO_DMA26_CNT2,
377 },
378 [SRAM_CH28] = {
379 .name = "mpeg",
380 .cmds_start = 0x180200,
381 .ctrl_start = 0x1807C0,
382 .cdt = 0x1807C0 + 64,
383 .fifo_start = 0x185600,
384 .fifo_size = 0x001000,
385 .ptr1_reg = MO_DMA28_PTR1,
386 .ptr2_reg = MO_DMA28_PTR2,
387 .cnt1_reg = MO_DMA28_CNT1,
388 .cnt2_reg = MO_DMA28_CNT2,
389 },
390};
391
392int cx88_sram_channel_setup(struct cx88_core *core,
393 struct sram_channel *ch,
394 unsigned int bpl, u32 risc)
395{
396 unsigned int i,lines;
397 u32 cdt;
398
399 bpl = (bpl + 7) & ~7; /* alignment */
400 cdt = ch->cdt;
401 lines = ch->fifo_size / bpl;
402 if (lines > 6)
403 lines = 6;
404 BUG_ON(lines < 2);
405
406 /* write CDT */
407 for (i = 0; i < lines; i++)
408 cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
409
410 /* write CMDS */
411 cx_write(ch->cmds_start + 0, risc);
412 cx_write(ch->cmds_start + 4, cdt);
413 cx_write(ch->cmds_start + 8, (lines*16) >> 3);
414 cx_write(ch->cmds_start + 12, ch->ctrl_start);
415 cx_write(ch->cmds_start + 16, 64 >> 2);
416 for (i = 20; i < 64; i += 4)
417 cx_write(ch->cmds_start + i, 0);
418
419 /* fill registers */
420 cx_write(ch->ptr1_reg, ch->fifo_start);
421 cx_write(ch->ptr2_reg, cdt);
422 cx_write(ch->cnt1_reg, (bpl >> 3) -1);
423 cx_write(ch->cnt2_reg, (lines*16) >> 3);
424
425 dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
426 return 0;
427}
428
429/* ------------------------------------------------------------------ */
430/* debug helper code */
431
432int cx88_risc_decode(u32 risc)
433{
434 static char *instr[16] = {
435 [ RISC_SYNC >> 28 ] = "sync",
436 [ RISC_WRITE >> 28 ] = "write",
437 [ RISC_WRITEC >> 28 ] = "writec",
438 [ RISC_READ >> 28 ] = "read",
439 [ RISC_READC >> 28 ] = "readc",
440 [ RISC_JUMP >> 28 ] = "jump",
441 [ RISC_SKIP >> 28 ] = "skip",
442 [ RISC_WRITERM >> 28 ] = "writerm",
443 [ RISC_WRITECM >> 28 ] = "writecm",
444 [ RISC_WRITECR >> 28 ] = "writecr",
445 };
446 static int incr[16] = {
447 [ RISC_WRITE >> 28 ] = 2,
448 [ RISC_JUMP >> 28 ] = 2,
449 [ RISC_WRITERM >> 28 ] = 3,
450 [ RISC_WRITECM >> 28 ] = 3,
451 [ RISC_WRITECR >> 28 ] = 4,
452 };
453 static char *bits[] = {
454 "12", "13", "14", "resync",
455 "cnt0", "cnt1", "18", "19",
456 "20", "21", "22", "23",
457 "irq1", "irq2", "eol", "sol",
458 };
459 int i;
460
461 printk("0x%08x [ %s", risc,
462 instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
463 for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
464 if (risc & (1 << (i + 12)))
465 printk(" %s",bits[i]);
466 printk(" count=%d ]\n", risc & 0xfff);
467 return incr[risc >> 28] ? incr[risc >> 28] : 1;
468}
469
470#if 0 /* currently unused, but useful for debugging */
471void cx88_risc_disasm(struct cx88_core *core,
472 struct btcx_riscmem *risc)
473{
474 unsigned int i,j,n;
475
476 printk("%s: risc disasm: %p [dma=0x%08lx]\n",
477 core->name, risc->cpu, (unsigned long)risc->dma);
478 for (i = 0; i < (risc->size >> 2); i += n) {
479 printk("%s: %04d: ", core->name, i);
480 n = cx88_risc_decode(risc->cpu[i]);
481 for (j = 1; j < n; j++)
482 printk("%s: %04d: 0x%08x [ arg #%d ]\n",
483 core->name, i+j, risc->cpu[i+j], j);
484 if (risc->cpu[i] == RISC_JUMP)
485 break;
486 }
487}
488#endif
489
490void cx88_sram_channel_dump(struct cx88_core *core,
491 struct sram_channel *ch)
492{
493 static char *name[] = {
494 "initial risc",
495 "cdt base",
496 "cdt size",
497 "iq base",
498 "iq size",
499 "risc pc",
500 "iq wr ptr",
501 "iq rd ptr",
502 "cdt current",
503 "pci target",
504 "line / byte",
505 };
506 u32 risc;
507 unsigned int i,j,n;
508
509 printk("%s: %s - dma channel status dump\n",
510 core->name,ch->name);
511 for (i = 0; i < ARRAY_SIZE(name); i++)
512 printk("%s: cmds: %-12s: 0x%08x\n",
513 core->name,name[i],
514 cx_read(ch->cmds_start + 4*i));
515 for (i = 0; i < 4; i++) {
516 risc = cx_read(ch->cmds_start + 4 * (i+11));
517 printk("%s: risc%d: ", core->name, i);
518 cx88_risc_decode(risc);
519 }
520 for (i = 0; i < 16; i += n) {
521 risc = cx_read(ch->ctrl_start + 4 * i);
522 printk("%s: iq %x: ", core->name, i);
523 n = cx88_risc_decode(risc);
524 for (j = 1; j < n; j++) {
525 risc = cx_read(ch->ctrl_start + 4 * (i+j));
526 printk("%s: iq %x: 0x%08x [ arg #%d ]\n",
527 core->name, i+j, risc, j);
528 }
529 }
530
531 printk("%s: fifo: 0x%08x -> 0x%x\n",
532 core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
533 printk("%s: ctrl: 0x%08x -> 0x%x\n",
534 core->name, ch->ctrl_start, ch->ctrl_start+6*16);
535 printk("%s: ptr1_reg: 0x%08x\n",
536 core->name,cx_read(ch->ptr1_reg));
537 printk("%s: ptr2_reg: 0x%08x\n",
538 core->name,cx_read(ch->ptr2_reg));
539 printk("%s: cnt1_reg: 0x%08x\n",
540 core->name,cx_read(ch->cnt1_reg));
541 printk("%s: cnt2_reg: 0x%08x\n",
542 core->name,cx_read(ch->cnt2_reg));
543}
544
545char *cx88_pci_irqs[32] = {
546 "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
547 "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
548 "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
549 "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
550};
551char *cx88_vid_irqs[32] = {
552 "y_risci1", "u_risci1", "v_risci1", "vbi_risc1",
553 "y_risci2", "u_risci2", "v_risci2", "vbi_risc2",
554 "y_oflow", "u_oflow", "v_oflow", "vbi_oflow",
555 "y_sync", "u_sync", "v_sync", "vbi_sync",
556 "opc_err", "par_err", "rip_err", "pci_abort",
557};
558char *cx88_mpeg_irqs[32] = {
559 "ts_risci1", NULL, NULL, NULL,
560 "ts_risci2", NULL, NULL, NULL,
561 "ts_oflow", NULL, NULL, NULL,
562 "ts_sync", NULL, NULL, NULL,
563 "opc_err", "par_err", "rip_err", "pci_abort",
564 "ts_err?",
565};
566
567void cx88_print_irqbits(char *name, char *tag, char **strings,
568 u32 bits, u32 mask)
569{
570 unsigned int i;
571
572 printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
573 for (i = 0; i < 32; i++) {
574 if (!(bits & (1 << i)))
575 continue;
576 if (strings[i])
577 printk(" %s", strings[i]);
578 else
579 printk(" %d", i);
580 if (!(mask & (1 << i)))
581 continue;
582 printk("*");
583 }
584 printk("\n");
585}
586
587/* ------------------------------------------------------------------ */
588
589int cx88_core_irq(struct cx88_core *core, u32 status)
590{
591 int handled = 0;
592
593 if (status & (1<<18)) {
594 cx88_ir_irq(core);
595 handled++;
596 }
597 if (!handled)
598 cx88_print_irqbits(core->name, "irq pci",
599 cx88_pci_irqs, status,
600 core->pci_irqmask);
601 return handled;
602}
603
604void cx88_wakeup(struct cx88_core *core,
605 struct cx88_dmaqueue *q, u32 count)
606{
607 struct cx88_buffer *buf;
608 int bc;
609
610 for (bc = 0;; bc++) {
611 if (list_empty(&q->active))
612 break;
613 buf = list_entry(q->active.next,
614 struct cx88_buffer, vb.queue);
615#if 0
616 if (buf->count > count)
617 break;
618#else
619 /* count comes from the hw and is is 16bit wide --
620 * this trick handles wrap-arounds correctly for
621 * up to 32767 buffers in flight... */
622 if ((s16) (count - buf->count) < 0)
623 break;
624#endif
625 do_gettimeofday(&buf->vb.ts);
626 dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
627 count, buf->count);
628 buf->vb.state = STATE_DONE;
629 list_del(&buf->vb.queue);
630 wake_up(&buf->vb.done);
631 }
632 if (list_empty(&q->active)) {
633 del_timer(&q->timeout);
634 } else {
635 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
636 }
637 if (bc != 1)
638 printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
639}
640
641void cx88_shutdown(struct cx88_core *core)
642{
643 /* disable RISC controller + IRQs */
644 cx_write(MO_DEV_CNTRL2, 0);
645
646 /* stop dma transfers */
647 cx_write(MO_VID_DMACNTRL, 0x0);
648 cx_write(MO_AUD_DMACNTRL, 0x0);
649 cx_write(MO_TS_DMACNTRL, 0x0);
650 cx_write(MO_VIP_DMACNTRL, 0x0);
651 cx_write(MO_GPHST_DMACNTRL, 0x0);
652
653 /* stop interrupts */
654 cx_write(MO_PCI_INTMSK, 0x0);
655 cx_write(MO_VID_INTMSK, 0x0);
656 cx_write(MO_AUD_INTMSK, 0x0);
657 cx_write(MO_TS_INTMSK, 0x0);
658 cx_write(MO_VIP_INTMSK, 0x0);
659 cx_write(MO_GPHST_INTMSK, 0x0);
660
661 /* stop capturing */
662 cx_write(VID_CAPTURE_CONTROL, 0);
663}
664
665int cx88_reset(struct cx88_core *core)
666{
667 dprintk(1,"%s\n",__FUNCTION__);
668 cx88_shutdown(core);
669
670 /* clear irq status */
671 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
672 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
673 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
674
675 /* wait a bit */
676 msleep(100);
677
678 /* init sram */
679 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
680 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
681 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
682 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
683 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
684 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
685 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
686
687 /* misc init ... */
688 cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable
689 (1 << 12) | // agc gain
690 (1 << 11) | // adaptibe agc
691 (0 << 10) | // chroma agc
692 (0 << 9) | // ckillen
693 (7)));
694
695 /* setup image format */
696 cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
697
698 /* setup FIFO Threshholds */
699 cx_write(MO_PDMA_STHRSH, 0x0807);
700 cx_write(MO_PDMA_DTHRSH, 0x0807);
701
702 /* fixes flashing of image */
703 cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
704 cx_write(MO_AGC_BACK_VBI, 0x00E00555);
705
706 cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
707 cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
708 cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int
709
710 /* Reset on-board parts */
711 cx_write(MO_SRST_IO, 0);
712 msleep(10);
713 cx_write(MO_SRST_IO, 1);
714
715 return 0;
716}
717
718/* ------------------------------------------------------------------ */
719
720static unsigned int inline norm_swidth(struct cx88_tvnorm *norm)
721{
722 return (norm->id & V4L2_STD_625_50) ? 922 : 754;
723}
724
725static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm)
726{
727 return (norm->id & V4L2_STD_625_50) ? 186 : 135;
728}
729
730static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm)
731{
732 return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18;
733}
734
735static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
736{
737 static const unsigned int ntsc = 28636360;
738 static const unsigned int pal = 35468950;
739
740 return (norm->id & V4L2_STD_625_50) ? pal : ntsc;
741}
742
743static unsigned int inline norm_notchfilter(struct cx88_tvnorm *norm)
744{
745 return (norm->id & V4L2_STD_625_50)
746 ? HLNotchFilter135PAL
747 : HLNotchFilter135NTSC;
748}
749
750static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
751{
752 return (norm->id & V4L2_STD_625_50) ? 1135 : 910;
753}
754
755static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm)
756{
757 return (norm->id & V4L2_STD_625_50) ? 511 : 288;
758}
759
760int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
761 enum v4l2_field field)
762{
763 unsigned int swidth = norm_swidth(core->tvnorm);
764 unsigned int sheight = norm_maxh(core->tvnorm);
765 u32 value;
766
767 dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
768 V4L2_FIELD_HAS_TOP(field) ? "T" : "",
769 V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
770 core->tvnorm->name);
771 if (!V4L2_FIELD_HAS_BOTH(field))
772 height *= 2;
773
774 // recalc H delay and scale registers
775 value = (width * norm_hdelay(core->tvnorm)) / swidth;
776 value &= 0x3fe;
777 cx_write(MO_HDELAY_EVEN, value);
778 cx_write(MO_HDELAY_ODD, value);
779 dprintk(1,"set_scale: hdelay 0x%04x\n", value);
780
781 value = (swidth * 4096 / width) - 4096;
782 cx_write(MO_HSCALE_EVEN, value);
783 cx_write(MO_HSCALE_ODD, value);
784 dprintk(1,"set_scale: hscale 0x%04x\n", value);
785
786 cx_write(MO_HACTIVE_EVEN, width);
787 cx_write(MO_HACTIVE_ODD, width);
788 dprintk(1,"set_scale: hactive 0x%04x\n", width);
789
790 // recalc V scale Register (delay is constant)
791 cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
792 cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm));
793 dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm));
794
795 value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
796 cx_write(MO_VSCALE_EVEN, value);
797 cx_write(MO_VSCALE_ODD, value);
798 dprintk(1,"set_scale: vscale 0x%04x\n", value);
799
800 cx_write(MO_VACTIVE_EVEN, sheight);
801 cx_write(MO_VACTIVE_ODD, sheight);
802 dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
803
804 // setup filters
805 value = 0;
806 value |= (1 << 19); // CFILT (default)
807 if (core->tvnorm->id & V4L2_STD_SECAM) {
808 value |= (1 << 15);
809 value |= (1 << 16);
810 }
811 if (INPUT(core->input)->type == CX88_VMUX_SVIDEO)
812 value |= (1 << 13) | (1 << 5);
813 if (V4L2_FIELD_INTERLACED == field)
814 value |= (1 << 3); // VINT (interlaced vertical scaling)
815 if (width < 385)
816 value |= (1 << 0); // 3-tap interpolation
817 if (width < 193)
818 value |= (1 << 1); // 5-tap interpolation
819 if (nocomb)
820 value |= (3 << 5); // disable comb filter
821
822 cx_write(MO_FILTER_EVEN, value);
823 cx_write(MO_FILTER_ODD, value);
824 dprintk(1,"set_scale: filter 0x%04x\n", value);
825
826 return 0;
827}
828
829static const u32 xtal = 28636363;
830
831static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
832{
833 static u32 pre[] = { 0, 0, 0, 3, 2, 1 };
834 u64 pll;
835 u32 reg;
836 int i;
837
838 if (prescale < 2)
839 prescale = 2;
840 if (prescale > 5)
841 prescale = 5;
842
843 pll = ofreq * 8 * prescale * (u64)(1 << 20);
844 do_div(pll,xtal);
845 reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
846 if (((reg >> 20) & 0x3f) < 14) {
847 printk("%s/0: pll out of range\n",core->name);
848 return -1;
849 }
850
851 dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n",
852 reg, cx_read(MO_PLL_REG), ofreq);
853 cx_write(MO_PLL_REG, reg);
854 for (i = 0; i < 100; i++) {
855 reg = cx_read(MO_DEVICE_STATUS);
856 if (reg & (1<<2)) {
857 dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
858 prescale,ofreq);
859 return 0;
860 }
861 dprintk(1,"pll not locked yet, waiting ...\n");
862 msleep(10);
863 }
864 dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
865 return -1;
866}
867
868static int set_tvaudio(struct cx88_core *core)
869{
870 struct cx88_tvnorm *norm = core->tvnorm;
871
872 if (CX88_VMUX_TELEVISION != INPUT(core->input)->type)
873 return 0;
874
875 if (V4L2_STD_PAL_BG & norm->id) {
876 core->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_BG;
877
878 } else if (V4L2_STD_PAL_DK & norm->id) {
879 core->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_DK;
880
881 } else if (V4L2_STD_PAL_I & norm->id) {
882 core->tvaudio = WW_NICAM_I;
883
884 } else if (V4L2_STD_SECAM_L & norm->id) {
885 core->tvaudio = WW_SYSTEM_L_AM;
886
887 } else if (V4L2_STD_SECAM_DK & norm->id) {
888 core->tvaudio = WW_A2_DK;
889
890 } else if ((V4L2_STD_NTSC_M & norm->id) ||
891 (V4L2_STD_PAL_M & norm->id)) {
892 core->tvaudio = WW_BTSC;
893
894 } else if (V4L2_STD_NTSC_M_JP & norm->id) {
895 core->tvaudio = WW_EIAJ;
896
897 } else {
898 printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
899 core->name, norm->name);
900 core->tvaudio = 0;
901 return 0;
902 }
903
904 cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
905 cx88_set_tvaudio(core);
906 // cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
907
908 cx_write(MO_AUDD_LNGTH, 128); /* fifo size */
909 cx_write(MO_AUDR_LNGTH, 128); /* fifo size */
910 cx_write(MO_AUD_DMACNTRL, 0x03); /* need audio fifo */
911 return 0;
912}
913
914int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
915{
916 u32 fsc8;
917 u32 adc_clock;
918 u32 vdec_clock;
919 u32 step_db,step_dr;
920 u64 tmp64;
921 u32 bdelay,agcdelay,htotal;
922
923 core->tvnorm = norm;
924 fsc8 = norm_fsc8(norm);
925 adc_clock = xtal;
926 vdec_clock = fsc8;
927 step_db = fsc8;
928 step_dr = fsc8;
929
930 if (norm->id & V4L2_STD_SECAM) {
931 step_db = 4250000 * 8;
932 step_dr = 4406250 * 8;
933 }
934
935 dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
936 norm->name, fsc8, adc_clock, vdec_clock, step_db, step_dr);
937 set_pll(core,2,vdec_clock);
938
939 dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
940 norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
941 cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat);
942
943#if 1
944 // FIXME: as-is from DScaler
945 dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
946 norm->cxoformat, cx_read(MO_OUTPUT_FORMAT));
947 cx_write(MO_OUTPUT_FORMAT, norm->cxoformat);
948#endif
949
950 // MO_SCONV_REG = adc clock / video dec clock * 2^17
951 tmp64 = adc_clock * (u64)(1 << 17);
952 do_div(tmp64, vdec_clock);
953 dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n",
954 (u32)tmp64, cx_read(MO_SCONV_REG));
955 cx_write(MO_SCONV_REG, (u32)tmp64);
956
957 // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
958 tmp64 = step_db * (u64)(1 << 22);
959 do_div(tmp64, vdec_clock);
960 dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n",
961 (u32)tmp64, cx_read(MO_SUB_STEP));
962 cx_write(MO_SUB_STEP, (u32)tmp64);
963
964 // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
965 tmp64 = step_dr * (u64)(1 << 22);
966 do_div(tmp64, vdec_clock);
967 dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n",
968 (u32)tmp64, cx_read(MO_SUB_STEP_DR));
969 cx_write(MO_SUB_STEP_DR, (u32)tmp64);
970
971 // bdelay + agcdelay
972 bdelay = vdec_clock * 65 / 20000000 + 21;
973 agcdelay = vdec_clock * 68 / 20000000 + 15;
974 dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
975 (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
976 cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
977
978 // htotal
979 tmp64 = norm_htotal(norm) * (u64)vdec_clock;
980 do_div(tmp64, fsc8);
981 htotal = (u32)tmp64 | (norm_notchfilter(norm) << 11);
982 dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n",
983 htotal, cx_read(MO_HTOTAL), (u32)tmp64);
984 cx_write(MO_HTOTAL, htotal);
985
986 // vbi stuff
987 cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */
988 norm_vbipack(norm)));
989
990 // this is needed as well to set all tvnorm parameter
991 cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
992
993 // audio
994 set_tvaudio(core);
995
996 // tell i2c chips
997#ifdef V4L2_I2C_CLIENTS
998 cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm->id);
999#else
1000 {
1001 struct video_channel c;
1002 memset(&c,0,sizeof(c));
1003 c.channel = core->input;
1004 c.norm = VIDEO_MODE_PAL;
1005 if ((norm->id & (V4L2_STD_NTSC_M|V4L2_STD_NTSC_M_JP)))
1006 c.norm = VIDEO_MODE_NTSC;
1007 if (norm->id & V4L2_STD_SECAM)
1008 c.norm = VIDEO_MODE_SECAM;
1009 cx88_call_i2c_clients(core,VIDIOCSCHAN,&c);
1010 }
1011#endif
1012
1013 // done
1014 return 0;
1015}
1016
1017/* ------------------------------------------------------------------ */
1018
1019static int cx88_pci_quirks(char *name, struct pci_dev *pci)
1020{
1021 unsigned int lat = UNSET;
1022 u8 ctrl = 0;
1023 u8 value;
1024
1025 /* check pci quirks */
1026 if (pci_pci_problems & PCIPCI_TRITON) {
1027 printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
1028 name);
1029 ctrl |= CX88X_EN_TBFX;
1030 }
1031 if (pci_pci_problems & PCIPCI_NATOMA) {
1032 printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
1033 name);
1034 ctrl |= CX88X_EN_TBFX;
1035 }
1036 if (pci_pci_problems & PCIPCI_VIAETBF) {
1037 printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
1038 name);
1039 ctrl |= CX88X_EN_TBFX;
1040 }
1041 if (pci_pci_problems & PCIPCI_VSFX) {
1042 printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
1043 name);
1044 ctrl |= CX88X_EN_VSFX;
1045 }
1046#ifdef PCIPCI_ALIMAGIK
1047 if (pci_pci_problems & PCIPCI_ALIMAGIK) {
1048 printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
1049 name);
1050 lat = 0x0A;
1051 }
1052#endif
1053
1054 /* check insmod options */
1055 if (UNSET != latency)
1056 lat = latency;
1057
1058 /* apply stuff */
1059 if (ctrl) {
1060 pci_read_config_byte(pci, CX88X_DEVCTRL, &value);
1061 value |= ctrl;
1062 pci_write_config_byte(pci, CX88X_DEVCTRL, value);
1063 }
1064 if (UNSET != lat) {
1065 printk(KERN_INFO "%s: setting pci latency timer to %d\n",
1066 name, latency);
1067 pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);
1068 }
1069 return 0;
1070}
1071
1072/* ------------------------------------------------------------------ */
1073
1074struct video_device *cx88_vdev_init(struct cx88_core *core,
1075 struct pci_dev *pci,
1076 struct video_device *template,
1077 char *type)
1078{
1079 struct video_device *vfd;
1080
1081 vfd = video_device_alloc();
1082 if (NULL == vfd)
1083 return NULL;
1084 *vfd = *template;
1085 vfd->minor = -1;
1086 vfd->dev = &pci->dev;
1087 vfd->release = video_device_release;
1088 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1089 core->name, type, cx88_boards[core->board].name);
1090 return vfd;
1091}
1092
1093static int get_ressources(struct cx88_core *core, struct pci_dev *pci)
1094{
1095 if (request_mem_region(pci_resource_start(pci,0),
1096 pci_resource_len(pci,0),
1097 core->name))
1098 return 0;
1099 printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n",
1100 core->name,pci_resource_start(pci,0));
1101 return -EBUSY;
1102}
1103
1104struct cx88_core* cx88_core_get(struct pci_dev *pci)
1105{
1106 struct cx88_core *core;
1107 struct list_head *item;
1108 int i;
1109
1110 down(&devlist);
1111 list_for_each(item,&cx88_devlist) {
1112 core = list_entry(item, struct cx88_core, devlist);
1113 if (pci->bus->number != core->pci_bus)
1114 continue;
1115 if (PCI_SLOT(pci->devfn) != core->pci_slot)
1116 continue;
1117
1118 if (0 != get_ressources(core,pci))
1119 goto fail_unlock;
1120 atomic_inc(&core->refcount);
1121 up(&devlist);
1122 return core;
1123 }
1124 core = kmalloc(sizeof(*core),GFP_KERNEL);
1125 if (NULL == core)
1126 goto fail_unlock;
1127
1128 memset(core,0,sizeof(*core));
1129 atomic_inc(&core->refcount);
1130 core->pci_bus = pci->bus->number;
1131 core->pci_slot = PCI_SLOT(pci->devfn);
1132 core->pci_irqmask = 0x00fc00;
1133
1134 core->nr = cx88_devcount++;
1135 sprintf(core->name,"cx88[%d]",core->nr);
1136 if (0 != get_ressources(core,pci)) {
1137 cx88_devcount--;
1138 goto fail_free;
1139 }
1140 list_add_tail(&core->devlist,&cx88_devlist);
1141
1142 /* PCI stuff */
1143 cx88_pci_quirks(core->name, pci);
1144 core->lmmio = ioremap(pci_resource_start(pci,0),
1145 pci_resource_len(pci,0));
1146 core->bmmio = (u8 __iomem *)core->lmmio;
1147
1148 /* board config */
1149 core->board = UNSET;
1150 if (card[core->nr] < cx88_bcount)
1151 core->board = card[core->nr];
1152 for (i = 0; UNSET == core->board && i < cx88_idcount; i++)
1153 if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
1154 pci->subsystem_device == cx88_subids[i].subdevice)
1155 core->board = cx88_subids[i].card;
1156 if (UNSET == core->board) {
1157 core->board = CX88_BOARD_UNKNOWN;
1158 cx88_card_list(core,pci);
1159 }
1160 printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
1161 core->name,pci->subsystem_vendor,
1162 pci->subsystem_device,cx88_boards[core->board].name,
1163 core->board, card[core->nr] == core->board ?
1164 "insmod option" : "autodetected");
1165
1166 core->tuner_type = tuner[core->nr];
1167 if (UNSET == core->tuner_type)
1168 core->tuner_type = cx88_boards[core->board].tuner_type;
1169 core->tda9887_conf = cx88_boards[core->board].tda9887_conf;
1170
1171 /* init hardware */
1172 cx88_reset(core);
1173 cx88_i2c_init(core,pci);
1174 cx88_card_setup(core);
1175 cx88_ir_init(core,pci);
1176
1177 up(&devlist);
1178 return core;
1179
1180fail_free:
1181 kfree(core);
1182fail_unlock:
1183 up(&devlist);
1184 return NULL;
1185}
1186
1187void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1188{
1189 release_mem_region(pci_resource_start(pci,0),
1190 pci_resource_len(pci,0));
1191
1192 if (!atomic_dec_and_test(&core->refcount))
1193 return;
1194
1195 down(&devlist);
1196 cx88_ir_fini(core);
1197 if (0 == core->i2c_rc)
1198 i2c_bit_del_bus(&core->i2c_adap);
1199 list_del(&core->devlist);
1200 iounmap(core->lmmio);
1201 cx88_devcount--;
1202 up(&devlist);
1203 kfree(core);
1204}
1205
1206/* ------------------------------------------------------------------ */
1207
1208EXPORT_SYMBOL(cx88_print_ioctl);
1209EXPORT_SYMBOL(cx88_pci_irqs);
1210EXPORT_SYMBOL(cx88_vid_irqs);
1211EXPORT_SYMBOL(cx88_mpeg_irqs);
1212EXPORT_SYMBOL(cx88_print_irqbits);
1213
1214EXPORT_SYMBOL(cx88_core_irq);
1215EXPORT_SYMBOL(cx88_wakeup);
1216EXPORT_SYMBOL(cx88_reset);
1217EXPORT_SYMBOL(cx88_shutdown);
1218
1219EXPORT_SYMBOL(cx88_risc_buffer);
1220EXPORT_SYMBOL(cx88_risc_databuffer);
1221EXPORT_SYMBOL(cx88_risc_stopper);
1222EXPORT_SYMBOL(cx88_free_buffer);
1223
1224EXPORT_SYMBOL(cx88_sram_channels);
1225EXPORT_SYMBOL(cx88_sram_channel_setup);
1226EXPORT_SYMBOL(cx88_sram_channel_dump);
1227
1228EXPORT_SYMBOL(cx88_set_tvnorm);
1229EXPORT_SYMBOL(cx88_set_scale);
1230
1231EXPORT_SYMBOL(cx88_vdev_init);
1232EXPORT_SYMBOL(cx88_core_get);
1233EXPORT_SYMBOL(cx88_core_put);
1234
1235/*
1236 * Local variables:
1237 * c-basic-offset: 8
1238 * End:
1239 */
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
new file mode 100644
index 000000000000..bc6f18c45357
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -0,0 +1,381 @@
1/*
2 * $Id: cx88-dvb.c,v 1.31 2005/03/07 15:58:05 kraxel Exp $
3 *
4 * device driver for Conexant 2388x based TV cards
5 * MPEG Transport Stream (DVB) routines
6 *
7 * (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au>
8 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
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/module.h>
26#include <linux/init.h>
27#include <linux/device.h>
28#include <linux/fs.h>
29#include <linux/kthread.h>
30#include <linux/file.h>
31#include <linux/suspend.h>
32
33/* those two frontends need merging via linuxtv cvs ... */
34#define HAVE_CX22702 0
35#define HAVE_OR51132 1
36
37#include "cx88.h"
38#include "dvb-pll.h"
39#include "mt352.h"
40#include "mt352_priv.h"
41#if HAVE_CX22702
42# include "cx22702.h"
43#endif
44#if HAVE_OR51132
45# include "or51132.h"
46#endif
47
48MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
49MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
50MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
51MODULE_LICENSE("GPL");
52
53static unsigned int debug = 0;
54module_param(debug, int, 0644);
55MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
56
57#define dprintk(level,fmt, arg...) if (debug >= level) \
58 printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->core->name , ## arg)
59
60/* ------------------------------------------------------------------ */
61
62static int dvb_buf_setup(struct videobuf_queue *q,
63 unsigned int *count, unsigned int *size)
64{
65 struct cx8802_dev *dev = q->priv_data;
66
67 dev->ts_packet_size = 188 * 4;
68 dev->ts_packet_count = 32;
69
70 *size = dev->ts_packet_size * dev->ts_packet_count;
71 *count = 32;
72 return 0;
73}
74
75static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
76 enum v4l2_field field)
77{
78 struct cx8802_dev *dev = q->priv_data;
79 return cx8802_buf_prepare(dev, (struct cx88_buffer*)vb);
80}
81
82static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
83{
84 struct cx8802_dev *dev = q->priv_data;
85 cx8802_buf_queue(dev, (struct cx88_buffer*)vb);
86}
87
88static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
89{
90 struct cx8802_dev *dev = q->priv_data;
91 cx88_free_buffer(dev->pci, (struct cx88_buffer*)vb);
92}
93
94struct videobuf_queue_ops dvb_qops = {
95 .buf_setup = dvb_buf_setup,
96 .buf_prepare = dvb_buf_prepare,
97 .buf_queue = dvb_buf_queue,
98 .buf_release = dvb_buf_release,
99};
100
101/* ------------------------------------------------------------------ */
102
103static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
104{
105 static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 };
106 static u8 reset [] = { RESET, 0x80 };
107 static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
108 static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 };
109 static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
110 static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
111
112 mt352_write(fe, clock_config, sizeof(clock_config));
113 udelay(200);
114 mt352_write(fe, reset, sizeof(reset));
115 mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
116
117 mt352_write(fe, agc_cfg, sizeof(agc_cfg));
118 mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
119 mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
120 return 0;
121}
122
123static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
124{
125 static u8 clock_config [] = { 0x89, 0x38, 0x39 };
126 static u8 reset [] = { 0x50, 0x80 };
127 static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
128 static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
129 0x00, 0xFF, 0x00, 0x40, 0x40 };
130 static u8 dntv_extra[] = { 0xB5, 0x7A };
131 static u8 capt_range_cfg[] = { 0x75, 0x32 };
132
133 mt352_write(fe, clock_config, sizeof(clock_config));
134 udelay(2000);
135 mt352_write(fe, reset, sizeof(reset));
136 mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
137
138 mt352_write(fe, agc_cfg, sizeof(agc_cfg));
139 udelay(2000);
140 mt352_write(fe, dntv_extra, sizeof(dntv_extra));
141 mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
142
143 return 0;
144}
145
146static int mt352_pll_set(struct dvb_frontend* fe,
147 struct dvb_frontend_parameters* params,
148 u8* pllbuf)
149{
150 struct cx8802_dev *dev= fe->dvb->priv;
151
152 pllbuf[0] = dev->core->pll_addr << 1;
153 dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
154 params->frequency,
155 params->u.ofdm.bandwidth);
156 return 0;
157}
158
159static struct mt352_config dvico_fusionhdtv = {
160 .demod_address = 0x0F,
161 .demod_init = dvico_fusionhdtv_demod_init,
162 .pll_set = mt352_pll_set,
163};
164
165static struct mt352_config dntv_live_dvbt_config = {
166 .demod_address = 0x0f,
167 .demod_init = dntv_live_dvbt_demod_init,
168 .pll_set = mt352_pll_set,
169};
170
171#if HAVE_CX22702
172static struct cx22702_config connexant_refboard_config = {
173 .demod_address = 0x43,
174 .pll_address = 0x60,
175 .pll_desc = &dvb_pll_thomson_dtt7579,
176};
177
178static struct cx22702_config hauppauge_novat_config = {
179 .demod_address = 0x43,
180 .pll_address = 0x61,
181 .pll_desc = &dvb_pll_thomson_dtt759x,
182};
183#endif
184
185#if HAVE_OR51132
186static int or51132_set_ts_param(struct dvb_frontend* fe,
187 int is_punctured)
188{
189 struct cx8802_dev *dev= fe->dvb->priv;
190 dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
191 return 0;
192}
193
194struct or51132_config pchdtv_hd3000 = {
195 .demod_address = 0x15,
196 .pll_address = 0x61,
197 .pll_desc = &dvb_pll_thomson_dtt7610,
198 .set_ts_params = or51132_set_ts_param,
199};
200#endif
201
202static int dvb_register(struct cx8802_dev *dev)
203{
204 /* init struct videobuf_dvb */
205 dev->dvb.name = dev->core->name;
206 dev->ts_gen_cntrl = 0x0c;
207
208 /* init frontend */
209 switch (dev->core->board) {
210#if HAVE_CX22702
211 case CX88_BOARD_HAUPPAUGE_DVB_T1:
212 dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config,
213 &dev->core->i2c_adap);
214 break;
215 case CX88_BOARD_CONEXANT_DVB_T1:
216 dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
217 &dev->core->i2c_adap);
218 break;
219#endif
220 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
221 dev->core->pll_addr = 0x61;
222 dev->core->pll_desc = &dvb_pll_lg_z201;
223 dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
224 &dev->core->i2c_adap);
225 break;
226 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
227 dev->core->pll_addr = 0x60;
228 dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
229 dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
230 &dev->core->i2c_adap);
231 break;
232 case CX88_BOARD_KWORLD_DVB_T:
233 case CX88_BOARD_DNTV_LIVE_DVB_T:
234 dev->core->pll_addr = 0x61;
235 dev->core->pll_desc = &dvb_pll_unknown_1;
236 dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
237 &dev->core->i2c_adap);
238 break;
239#if HAVE_OR51132
240 case CX88_BOARD_PCHDTV_HD3000:
241 dev->dvb.frontend = or51132_attach(&pchdtv_hd3000,
242 &dev->core->i2c_adap);
243 break;
244#endif
245 default:
246 printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n"
247 "%s: you might want to look out for patches here:\n"
248 "%s: http://dl.bytesex.org/patches/\n",
249 dev->core->name, dev->core->name, dev->core->name);
250 break;
251 }
252 if (NULL == dev->dvb.frontend) {
253 printk("%s: frontend initialization failed\n",dev->core->name);
254 return -1;
255 }
256
257 if (dev->core->pll_desc) {
258 dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min;
259 dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
260 }
261
262 /* Copy the board name into the DVB structure */
263 strlcpy(dev->dvb.frontend->ops->info.name,
264 cx88_boards[dev->core->board].name,
265 sizeof(dev->dvb.frontend->ops->info.name));
266
267 /* register everything */
268 return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
269}
270
271/* ----------------------------------------------------------- */
272
273static int __devinit dvb_probe(struct pci_dev *pci_dev,
274 const struct pci_device_id *pci_id)
275{
276 struct cx8802_dev *dev;
277 struct cx88_core *core;
278 int err;
279
280 /* general setup */
281 core = cx88_core_get(pci_dev);
282 if (NULL == core)
283 return -EINVAL;
284
285 err = -ENODEV;
286 if (!cx88_boards[core->board].dvb)
287 goto fail_core;
288
289 err = -ENOMEM;
290 dev = kmalloc(sizeof(*dev),GFP_KERNEL);
291 if (NULL == dev)
292 goto fail_core;
293 memset(dev,0,sizeof(*dev));
294 dev->pci = pci_dev;
295 dev->core = core;
296
297 err = cx8802_init_common(dev);
298 if (0 != err)
299 goto fail_free;
300
301 /* dvb stuff */
302 printk("%s/2: cx2388x based dvb card\n", core->name);
303 videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops,
304 dev->pci, &dev->slock,
305 V4L2_BUF_TYPE_VIDEO_CAPTURE,
306 V4L2_FIELD_TOP,
307 sizeof(struct cx88_buffer),
308 dev);
309 err = dvb_register(dev);
310 if (0 != err)
311 goto fail_free;
312 return 0;
313
314 fail_free:
315 kfree(dev);
316 fail_core:
317 cx88_core_put(core,pci_dev);
318 return err;
319}
320
321static void __devexit dvb_remove(struct pci_dev *pci_dev)
322{
323 struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
324
325 /* dvb */
326 videobuf_dvb_unregister(&dev->dvb);
327
328 /* common */
329 cx8802_fini_common(dev);
330 cx88_core_put(dev->core,dev->pci);
331 kfree(dev);
332}
333
334static struct pci_device_id cx8802_pci_tbl[] = {
335 {
336 .vendor = 0x14f1,
337 .device = 0x8802,
338 .subvendor = PCI_ANY_ID,
339 .subdevice = PCI_ANY_ID,
340 },{
341 /* --- end of list --- */
342 }
343};
344MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
345
346static struct pci_driver dvb_pci_driver = {
347 .name = "cx88-dvb",
348 .id_table = cx8802_pci_tbl,
349 .probe = dvb_probe,
350 .remove = __devexit_p(dvb_remove),
351 .suspend = cx8802_suspend_common,
352 .resume = cx8802_resume_common,
353};
354
355static int dvb_init(void)
356{
357 printk(KERN_INFO "cx2388x dvb driver version %d.%d.%d loaded\n",
358 (CX88_VERSION_CODE >> 16) & 0xff,
359 (CX88_VERSION_CODE >> 8) & 0xff,
360 CX88_VERSION_CODE & 0xff);
361#ifdef SNAPSHOT
362 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
363 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
364#endif
365 return pci_register_driver(&dvb_pci_driver);
366}
367
368static void dvb_fini(void)
369{
370 pci_unregister_driver(&dvb_pci_driver);
371}
372
373module_init(dvb_init);
374module_exit(dvb_fini);
375
376/*
377 * Local variables:
378 * c-basic-offset: 8
379 * compile-command: "make DVB=1"
380 * End:
381 */
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
new file mode 100644
index 000000000000..60800172c026
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -0,0 +1,213 @@
1/*
2 $Id: cx88-i2c.c,v 1.20 2005/02/15 15:59:35 kraxel Exp $
3
4 cx88-i2c.c -- all the i2c code is here
5
6 Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
7 & Marcus Metzler (mocm@thp.uni-koeln.de)
8 (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
9 (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
25*/
26
27#include <linux/module.h>
28#include <linux/moduleparam.h>
29#include <linux/init.h>
30
31#include <asm/io.h>
32
33#include "cx88.h"
34
35static unsigned int i2c_debug = 0;
36module_param(i2c_debug, int, 0644);
37MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
38
39static unsigned int i2c_scan = 0;
40module_param(i2c_scan, int, 0444);
41MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
42
43#define dprintk(level,fmt, arg...) if (i2c_debug >= level) \
44 printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
45
46/* ----------------------------------------------------------------------- */
47
48void cx8800_bit_setscl(void *data, int state)
49{
50 struct cx88_core *core = data;
51
52 if (state)
53 core->i2c_state |= 0x02;
54 else
55 core->i2c_state &= ~0x02;
56 cx_write(MO_I2C, core->i2c_state);
57 cx_read(MO_I2C);
58}
59
60void cx8800_bit_setsda(void *data, int state)
61{
62 struct cx88_core *core = data;
63
64 if (state)
65 core->i2c_state |= 0x01;
66 else
67 core->i2c_state &= ~0x01;
68 cx_write(MO_I2C, core->i2c_state);
69 cx_read(MO_I2C);
70}
71
72static int cx8800_bit_getscl(void *data)
73{
74 struct cx88_core *core = data;
75 u32 state;
76
77 state = cx_read(MO_I2C);
78 return state & 0x02 ? 1 : 0;
79}
80
81static int cx8800_bit_getsda(void *data)
82{
83 struct cx88_core *core = data;
84 u32 state;
85
86 state = cx_read(MO_I2C);
87 return state & 0x01;
88}
89
90/* ----------------------------------------------------------------------- */
91
92static int attach_inform(struct i2c_client *client)
93{
94 struct cx88_core *core = i2c_get_adapdata(client->adapter);
95
96 dprintk(1, "i2c attach [addr=0x%x,client=%s]\n",
97 client->addr, i2c_clientname(client));
98 if (!client->driver->command)
99 return 0;
100
101 if (core->tuner_type != UNSET)
102 client->driver->command(client, TUNER_SET_TYPE, &core->tuner_type);
103 if (core->tda9887_conf)
104 client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf);
105 return 0;
106}
107
108static int detach_inform(struct i2c_client *client)
109{
110 struct cx88_core *core = i2c_get_adapdata(client->adapter);
111
112 dprintk(1, "i2c detach [client=%s]\n", i2c_clientname(client));
113 return 0;
114}
115
116void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
117{
118 if (0 != core->i2c_rc)
119 return;
120 i2c_clients_command(&core->i2c_adap, cmd, arg);
121}
122
123static struct i2c_algo_bit_data cx8800_i2c_algo_template = {
124 .setsda = cx8800_bit_setsda,
125 .setscl = cx8800_bit_setscl,
126 .getsda = cx8800_bit_getsda,
127 .getscl = cx8800_bit_getscl,
128 .udelay = 16,
129 .mdelay = 10,
130 .timeout = 200,
131};
132
133/* ----------------------------------------------------------------------- */
134
135static struct i2c_adapter cx8800_i2c_adap_template = {
136 I2C_DEVNAME("cx2388x"),
137 .owner = THIS_MODULE,
138 .id = I2C_HW_B_CX2388x,
139 .client_register = attach_inform,
140 .client_unregister = detach_inform,
141};
142
143static struct i2c_client cx8800_i2c_client_template = {
144 I2C_DEVNAME("cx88xx internal"),
145};
146
147static char *i2c_devs[128] = {
148 [ 0x86 >> 1 ] = "tda9887/cx22702",
149 [ 0xa0 >> 1 ] = "eeprom",
150 [ 0xc0 >> 1 ] = "tuner (analog)",
151 [ 0xc2 >> 1 ] = "tuner (analog/dvb)",
152};
153
154static void do_i2c_scan(char *name, struct i2c_client *c)
155{
156 unsigned char buf;
157 int i,rc;
158
159 for (i = 0; i < 128; i++) {
160 c->addr = i;
161 rc = i2c_master_recv(c,&buf,0);
162 if (rc < 0)
163 continue;
164 printk("%s: i2c scan: found device @ 0x%x [%s]\n",
165 name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
166 }
167}
168
169/* init + register i2c algo-bit adapter */
170int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
171{
172 memcpy(&core->i2c_adap, &cx8800_i2c_adap_template,
173 sizeof(core->i2c_adap));
174 memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,
175 sizeof(core->i2c_algo));
176 memcpy(&core->i2c_client, &cx8800_i2c_client_template,
177 sizeof(core->i2c_client));
178
179 if (core->tuner_type != TUNER_ABSENT)
180 core->i2c_adap.class |= I2C_CLASS_TV_ANALOG;
181 if (cx88_boards[core->board].dvb)
182 core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL;
183
184 core->i2c_adap.dev.parent = &pci->dev;
185 strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name));
186 core->i2c_algo.data = core;
187 i2c_set_adapdata(&core->i2c_adap,core);
188 core->i2c_adap.algo_data = &core->i2c_algo;
189 core->i2c_client.adapter = &core->i2c_adap;
190
191 cx8800_bit_setscl(core,1);
192 cx8800_bit_setsda(core,1);
193
194 core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap);
195 if (0 == core->i2c_rc) {
196 dprintk(1, "i2c register ok\n");
197 if (i2c_scan)
198 do_i2c_scan(core->name,&core->i2c_client);
199 } else
200 printk("%s: i2c register FAILED\n", core->name);
201 return core->i2c_rc;
202}
203
204/* ----------------------------------------------------------------------- */
205
206EXPORT_SYMBOL(cx88_call_i2c_clients);
207EXPORT_SYMBOL(cx88_i2c_init);
208
209/*
210 * Local variables:
211 * c-basic-offset: 8
212 * End:
213 */
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
new file mode 100644
index 000000000000..af6ad8cdbdb7
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -0,0 +1,396 @@
1/*
2 * $Id: cx88-input.c,v 1.9 2005/03/04 09:12:23 kraxel Exp $
3 *
4 * Device driver for GPIO attached remote control interfaces
5 * on Conexant 2388x based TV/DVB cards.
6 *
7 * Copyright (c) 2003 Pavel Machek
8 * Copyright (c) 2004 Gerd Knorr
9 * Copyright (c) 2004 Chris Pascoe
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#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/input.h>
29#include <linux/pci.h>
30#include <linux/module.h>
31#include <linux/moduleparam.h>
32
33#include <media/ir-common.h>
34
35#include "cx88.h"
36
37/* ---------------------------------------------------------------------- */
38
39/* DigitalNow DNTV Live DVB-T Remote */
40static IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = {
41 [ 0x00 ] = KEY_ESC, // 'go up a level?'
42 [ 0x01 ] = KEY_KP1, // '1'
43 [ 0x02 ] = KEY_KP2, // '2'
44 [ 0x03 ] = KEY_KP3, // '3'
45 [ 0x04 ] = KEY_KP4, // '4'
46 [ 0x05 ] = KEY_KP5, // '5'
47 [ 0x06 ] = KEY_KP6, // '6'
48 [ 0x07 ] = KEY_KP7, // '7'
49 [ 0x08 ] = KEY_KP8, // '8'
50 [ 0x09 ] = KEY_KP9, // '9'
51 [ 0x0a ] = KEY_KP0, // '0'
52 [ 0x0b ] = KEY_TUNER, // 'tv/fm'
53 [ 0x0c ] = KEY_SEARCH, // 'scan'
54 [ 0x0d ] = KEY_STOP, // 'stop'
55 [ 0x0e ] = KEY_PAUSE, // 'pause'
56 [ 0x0f ] = KEY_LIST, // 'source'
57
58 [ 0x10 ] = KEY_MUTE, // 'mute'
59 [ 0x11 ] = KEY_REWIND, // 'backward <<'
60 [ 0x12 ] = KEY_POWER, // 'power'
61 [ 0x13 ] = KEY_S, // 'snap'
62 [ 0x14 ] = KEY_AUDIO, // 'stereo'
63 [ 0x15 ] = KEY_CLEAR, // 'reset'
64 [ 0x16 ] = KEY_PLAY, // 'play'
65 [ 0x17 ] = KEY_ENTER, // 'enter'
66 [ 0x18 ] = KEY_ZOOM, // 'full screen'
67 [ 0x19 ] = KEY_FASTFORWARD, // 'forward >>'
68 [ 0x1a ] = KEY_CHANNELUP, // 'channel +'
69 [ 0x1b ] = KEY_VOLUMEUP, // 'volume +'
70 [ 0x1c ] = KEY_INFO, // 'preview'
71 [ 0x1d ] = KEY_RECORD, // 'record'
72 [ 0x1e ] = KEY_CHANNELDOWN, // 'channel -'
73 [ 0x1f ] = KEY_VOLUMEDOWN, // 'volume -'
74};
75
76/* ---------------------------------------------------------------------- */
77
78/* IO-DATA BCTV7E Remote */
79static IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = {
80 [ 0x40 ] = KEY_TV, // TV
81 [ 0x20 ] = KEY_RADIO, // FM
82 [ 0x60 ] = KEY_EPG, // EPG
83 [ 0x00 ] = KEY_POWER, // power
84
85 [ 0x50 ] = KEY_KP1, // 1
86 [ 0x30 ] = KEY_KP2, // 2
87 [ 0x70 ] = KEY_KP3, // 3
88 [ 0x10 ] = KEY_L, // Live
89
90 [ 0x48 ] = KEY_KP4, // 4
91 [ 0x28 ] = KEY_KP5, // 5
92 [ 0x68 ] = KEY_KP6, // 6
93 [ 0x08 ] = KEY_T, // Time Shift
94
95 [ 0x58 ] = KEY_KP7, // 7
96 [ 0x38 ] = KEY_KP8, // 8
97 [ 0x78 ] = KEY_KP9, // 9
98 [ 0x18 ] = KEY_PLAYPAUSE, // Play
99
100 [ 0x44 ] = KEY_KP0, // 10
101 [ 0x24 ] = KEY_ENTER, // 11
102 [ 0x64 ] = KEY_ESC, // 12
103 [ 0x04 ] = KEY_M, // Multi
104
105 [ 0x54 ] = KEY_VIDEO, // VIDEO
106 [ 0x34 ] = KEY_CHANNELUP, // channel +
107 [ 0x74 ] = KEY_VOLUMEUP, // volume +
108 [ 0x14 ] = KEY_MUTE, // Mute
109
110 [ 0x4c ] = KEY_S, // SVIDEO
111 [ 0x2c ] = KEY_CHANNELDOWN, // channel -
112 [ 0x6c ] = KEY_VOLUMEDOWN, // volume -
113 [ 0x0c ] = KEY_ZOOM, // Zoom
114
115 [ 0x5c ] = KEY_PAUSE, // pause
116 [ 0x3c ] = KEY_C, // || (red)
117 [ 0x7c ] = KEY_RECORD, // recording
118 [ 0x1c ] = KEY_STOP, // stop
119
120 [ 0x41 ] = KEY_REWIND, // backward <<
121 [ 0x21 ] = KEY_PLAY, // play
122 [ 0x61 ] = KEY_FASTFORWARD, // forward >>
123 [ 0x01 ] = KEY_NEXT, // skip >|
124};
125
126/* ---------------------------------------------------------------------- */
127
128struct cx88_IR {
129 struct cx88_core *core;
130 struct input_dev input;
131 struct ir_input_state ir;
132 char name[32];
133 char phys[32];
134
135 /* sample from gpio pin 16 */
136 int sampling;
137 u32 samples[16];
138 int scount;
139 unsigned long release;
140
141 /* poll external decoder */
142 int polling;
143 struct work_struct work;
144 struct timer_list timer;
145 u32 gpio_addr;
146 u32 last_gpio;
147 u32 mask_keycode;
148 u32 mask_keydown;
149 u32 mask_keyup;
150};
151
152static int ir_debug = 0;
153module_param(ir_debug, int, 0644); /* debug level [IR] */
154MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
155
156#define ir_dprintk(fmt, arg...) if (ir_debug) \
157 printk(KERN_DEBUG "%s IR: " fmt , ir->core->name, ## arg)
158
159/* ---------------------------------------------------------------------- */
160
161static void cx88_ir_handle_key(struct cx88_IR *ir)
162{
163 struct cx88_core *core = ir->core;
164 u32 gpio, data;
165
166 /* read gpio value */
167 gpio = cx_read(ir->gpio_addr);
168 if (ir->polling) {
169 if (ir->last_gpio == gpio)
170 return;
171 ir->last_gpio = gpio;
172 }
173
174 /* extract data */
175 data = ir_extract_bits(gpio, ir->mask_keycode);
176 ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
177 gpio, data,
178 ir->polling ? "poll" : "irq",
179 (gpio & ir->mask_keydown) ? " down" : "",
180 (gpio & ir->mask_keyup) ? " up" : "");
181
182 if (ir->mask_keydown) {
183 /* bit set on keydown */
184 if (gpio & ir->mask_keydown) {
185 ir_input_keydown(&ir->input,&ir->ir,data,data);
186 } else {
187 ir_input_nokey(&ir->input,&ir->ir);
188 }
189
190 } else if (ir->mask_keyup) {
191 /* bit cleared on keydown */
192 if (0 == (gpio & ir->mask_keyup)) {
193 ir_input_keydown(&ir->input,&ir->ir,data,data);
194 } else {
195 ir_input_nokey(&ir->input,&ir->ir);
196 }
197
198 } else {
199 /* can't distinguish keydown/up :-/ */
200 ir_input_keydown(&ir->input,&ir->ir,data,data);
201 ir_input_nokey(&ir->input,&ir->ir);
202 }
203}
204
205static void ir_timer(unsigned long data)
206{
207 struct cx88_IR *ir = (struct cx88_IR*)data;
208
209 schedule_work(&ir->work);
210}
211
212static void cx88_ir_work(void *data)
213{
214 struct cx88_IR *ir = data;
215 unsigned long timeout;
216
217 cx88_ir_handle_key(ir);
218 timeout = jiffies + (ir->polling * HZ / 1000);
219 mod_timer(&ir->timer, timeout);
220}
221
222/* ---------------------------------------------------------------------- */
223
224int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
225{
226 struct cx88_IR *ir;
227 IR_KEYTAB_TYPE *ir_codes = NULL;
228 int ir_type = IR_TYPE_OTHER;
229
230 ir = kmalloc(sizeof(*ir),GFP_KERNEL);
231 if (NULL == ir)
232 return -ENOMEM;
233 memset(ir,0,sizeof(*ir));
234
235 /* detect & configure */
236 switch (core->board) {
237 case CX88_BOARD_DNTV_LIVE_DVB_T:
238 ir_codes = ir_codes_dntv_live_dvb_t;
239 ir->gpio_addr = MO_GP1_IO;
240 ir->mask_keycode = 0x1f;
241 ir->mask_keyup = 0x60;
242 ir->polling = 50; // ms
243 break;
244 case CX88_BOARD_HAUPPAUGE:
245 case CX88_BOARD_HAUPPAUGE_DVB_T1:
246 ir_codes = ir_codes_hauppauge_new;
247 ir_type = IR_TYPE_RC5;
248 ir->sampling = 1;
249 break;
250 case CX88_BOARD_WINFAST2000XP_EXPERT:
251 ir_codes = ir_codes_winfast;
252 ir->gpio_addr = MO_GP0_IO;
253 ir->mask_keycode = 0x8f8;
254 ir->mask_keyup = 0x100;
255 ir->polling = 1; // ms
256 break;
257 case CX88_BOARD_IODATA_GVBCTV7E:
258 ir_codes = ir_codes_iodata_bctv7e;
259 ir->gpio_addr = MO_GP0_IO;
260 ir->mask_keycode = 0xfd;
261 ir->mask_keydown = 0x02;
262 ir->polling = 5; // ms
263 break;
264 }
265 if (NULL == ir_codes) {
266 kfree(ir);
267 return -ENODEV;
268 }
269
270 /* init input device */
271 snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)",
272 cx88_boards[core->board].name);
273 snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
274 pci_name(pci));
275
276 ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes);
277 ir->input.name = ir->name;
278 ir->input.phys = ir->phys;
279 ir->input.id.bustype = BUS_PCI;
280 ir->input.id.version = 1;
281 if (pci->subsystem_vendor) {
282 ir->input.id.vendor = pci->subsystem_vendor;
283 ir->input.id.product = pci->subsystem_device;
284 } else {
285 ir->input.id.vendor = pci->vendor;
286 ir->input.id.product = pci->device;
287 }
288
289 /* record handles to ourself */
290 ir->core = core;
291 core->ir = ir;
292
293 if (ir->polling) {
294 INIT_WORK(&ir->work, cx88_ir_work, ir);
295 init_timer(&ir->timer);
296 ir->timer.function = ir_timer;
297 ir->timer.data = (unsigned long)ir;
298 schedule_work(&ir->work);
299 }
300 if (ir->sampling) {
301 core->pci_irqmask |= (1<<18); // IR_SMP_INT
302 cx_write(MO_DDS_IO, 0xa80a80); // 4 kHz sample rate
303 cx_write(MO_DDSCFG_IO, 0x5); // enable
304 }
305
306 /* all done */
307 input_register_device(&ir->input);
308 printk("%s: registered IR remote control\n", core->name);
309
310 return 0;
311}
312
313int cx88_ir_fini(struct cx88_core *core)
314{
315 struct cx88_IR *ir = core->ir;
316
317 /* skip detach on non attached boards */
318 if (NULL == ir)
319 return 0;
320
321 if (ir->polling) {
322 del_timer(&ir->timer);
323 flush_scheduled_work();
324 }
325
326 input_unregister_device(&ir->input);
327 kfree(ir);
328
329 /* done */
330 core->ir = NULL;
331 return 0;
332}
333
334/* ---------------------------------------------------------------------- */
335
336void cx88_ir_irq(struct cx88_core *core)
337{
338 struct cx88_IR *ir = core->ir;
339 u32 samples,rc5;
340 int i;
341
342 if (NULL == ir)
343 return;
344 if (!ir->sampling)
345 return;
346
347 samples = cx_read(MO_SAMPLE_IO);
348 if (0 != samples && 0xffffffff != samples) {
349 /* record sample data */
350 if (ir->scount < ARRAY_SIZE(ir->samples))
351 ir->samples[ir->scount++] = samples;
352 return;
353 }
354 if (!ir->scount) {
355 /* nothing to sample */
356 if (ir->ir.keypressed && time_after(jiffies,ir->release))
357 ir_input_nokey(&ir->input,&ir->ir);
358 return;
359 }
360
361 /* have a complete sample */
362 if (ir->scount < ARRAY_SIZE(ir->samples))
363 ir->samples[ir->scount++] = samples;
364 for (i = 0; i < ir->scount; i++)
365 ir->samples[i] = ~ir->samples[i];
366 if (ir_debug)
367 ir_dump_samples(ir->samples,ir->scount);
368
369 /* decode it */
370 switch (core->board) {
371 case CX88_BOARD_HAUPPAUGE:
372 case CX88_BOARD_HAUPPAUGE_DVB_T1:
373 rc5 = ir_decode_biphase(ir->samples,ir->scount,5,7);
374 ir_dprintk("biphase decoded: %x\n",rc5);
375 if ((rc5 & 0xfffff000) != 0x3000)
376 break;
377 ir_input_keydown(&ir->input, &ir->ir, rc5 & 0x3f, rc5);
378 ir->release = jiffies + msecs_to_jiffies(120);
379 break;
380 }
381
382 ir->scount = 0;
383 return;
384}
385
386/* ---------------------------------------------------------------------- */
387
388MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");
389MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");
390MODULE_LICENSE("GPL");
391
392/*
393 * Local variables:
394 * c-basic-offset: 8
395 * End:
396 */
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
new file mode 100644
index 000000000000..07aae1899e17
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -0,0 +1,466 @@
1/*
2 * $Id: cx88-mpeg.c,v 1.25 2005/03/07 14:18:00 kraxel Exp $
3 *
4 * Support for the mpeg transport stream transfers
5 * PCI function #2 of the cx2388x.
6 *
7 * (c) 2004 Jelle Foks <jelle@foks.8m.com>
8 * (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au>
9 * (c) 2004 Gerd Knorr <kraxel@bytesex.org>
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/moduleparam.h>
28#include <linux/init.h>
29#include <linux/device.h>
30#include <linux/interrupt.h>
31#include <asm/delay.h>
32
33#include "cx88.h"
34
35/* ------------------------------------------------------------------ */
36
37MODULE_DESCRIPTION("mpeg driver for cx2388x based TV cards");
38MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>");
39MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
40MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
41MODULE_LICENSE("GPL");
42
43static unsigned int debug = 0;
44module_param(debug,int,0644);
45MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
46
47#define dprintk(level,fmt, arg...) if (debug >= level) \
48 printk(KERN_DEBUG "%s/2: " fmt, dev->core->name , ## arg)
49
50/* ------------------------------------------------------------------ */
51
52static int cx8802_start_dma(struct cx8802_dev *dev,
53 struct cx88_dmaqueue *q,
54 struct cx88_buffer *buf)
55{
56 struct cx88_core *core = dev->core;
57
58 dprintk(1, "cx8802_start_mpegport_dma %d\n", buf->vb.width);
59
60 /* setup fifo + format */
61 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
62 dev->ts_packet_size, buf->risc.dma);
63
64 /* write TS length to chip */
65 cx_write(MO_TS_LNGTH, buf->vb.width);
66
67#if 1
68 /* FIXME: this needs a review.
69 * also: move to cx88-blackbird + cx88-dvb source files? */
70
71 if (cx88_boards[core->board].dvb) {
72 /* negedge driven & software reset */
73 cx_write(TS_GEN_CNTRL, 0x40);
74 udelay(100);
75 cx_write(MO_PINMUX_IO, 0x00);
76 cx_write(TS_HW_SOP_CNTRL,47<<16|188<<4|0x00);
77 cx_write(TS_SOP_STAT,0x00);
78 cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
79 udelay(100);
80 }
81
82 if (cx88_boards[core->board].blackbird) {
83 cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
84
85 // cx_write(TS_F2_CMD_STAT_MM, 0x2900106); /* F2_CMD_STAT_MM defaults + master + memory space */
86 cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
87 udelay(100);
88
89 cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */
90 //cx_write(TS_HW_SOP_CNTRL, 0x2F0BC0); /* mpeg start byte ts: 0x2F0BC0 ? */
91 cx_write(TS_VALERR_CNTRL, 0x2000);
92
93 cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
94 udelay(100);
95 }
96#endif
97
98 /* reset counter */
99 cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET);
100 q->count = 1;
101
102 /* enable irqs */
103 cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
104 cx_write(MO_TS_INTMSK, 0x1f0011);
105
106 /* start dma */
107 cx_write(MO_DEV_CNTRL2, (1<<5)); /* FIXME: s/write/set/ ??? */
108 cx_write(MO_TS_DMACNTRL, 0x11);
109 return 0;
110}
111
112static int cx8802_stop_dma(struct cx8802_dev *dev)
113{
114 struct cx88_core *core = dev->core;
115
116 /* stop dma */
117 cx_clear(MO_TS_DMACNTRL, 0x11);
118
119 /* disable irqs */
120 cx_clear(MO_PCI_INTMSK, 0x000004);
121 cx_clear(MO_TS_INTMSK, 0x1f0011);
122
123 /* Reset the controller */
124 cx_write(TS_GEN_CNTRL, 0xcd);
125 return 0;
126}
127
128static int cx8802_restart_queue(struct cx8802_dev *dev,
129 struct cx88_dmaqueue *q)
130{
131 struct cx88_buffer *buf;
132 struct list_head *item;
133
134 if (list_empty(&q->active))
135 return 0;
136
137 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
138 dprintk(2,"restart_queue [%p/%d]: restart dma\n",
139 buf, buf->vb.i);
140 cx8802_start_dma(dev, q, buf);
141 list_for_each(item,&q->active) {
142 buf = list_entry(item, struct cx88_buffer, vb.queue);
143 buf->count = q->count++;
144 }
145 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
146 return 0;
147}
148
149/* ------------------------------------------------------------------ */
150
151int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf)
152{
153 int size = dev->ts_packet_size * dev->ts_packet_count;
154 int rc;
155
156 dprintk(1, "%s: %p\n", __FUNCTION__, buf);
157 if (0 != buf->vb.baddr && buf->vb.bsize < size)
158 return -EINVAL;
159
160 if (STATE_NEEDS_INIT == buf->vb.state) {
161 buf->vb.width = dev->ts_packet_size;
162 buf->vb.height = dev->ts_packet_count;
163 buf->vb.size = size;
164 buf->vb.field = V4L2_FIELD_TOP;
165
166 if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL)))
167 goto fail;
168 cx88_risc_databuffer(dev->pci, &buf->risc,
169 buf->vb.dma.sglist,
170 buf->vb.width, buf->vb.height);
171 }
172 buf->vb.state = STATE_PREPARED;
173 return 0;
174
175 fail:
176 cx88_free_buffer(dev->pci,buf);
177 return rc;
178}
179
180void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
181{
182 struct cx88_buffer *prev;
183 struct cx88_dmaqueue *q = &dev->mpegq;
184
185 /* add jump to stopper */
186 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
187 buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
188
189 if (list_empty(&q->active)) {
190 list_add_tail(&buf->vb.queue,&q->active);
191 cx8802_start_dma(dev, q, buf);
192 buf->vb.state = STATE_ACTIVE;
193 buf->count = q->count++;
194 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
195 dprintk(2,"[%p/%d] %s - first active\n",
196 buf, buf->vb.i, __FUNCTION__);
197
198 } else {
199 prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
200 list_add_tail(&buf->vb.queue,&q->active);
201 buf->vb.state = STATE_ACTIVE;
202 buf->count = q->count++;
203 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
204 dprintk(2,"[%p/%d] %s - append to active\n",
205 buf, buf->vb.i, __FUNCTION__);
206 }
207}
208
209/* ----------------------------------------------------------- */
210
211static void do_cancel_buffers(struct cx8802_dev *dev, char *reason, int restart)
212{
213 struct cx88_dmaqueue *q = &dev->mpegq;
214 struct cx88_buffer *buf;
215 unsigned long flags;
216
217 spin_lock_irqsave(&dev->slock,flags);
218 while (!list_empty(&q->active)) {
219 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
220 list_del(&buf->vb.queue);
221 buf->vb.state = STATE_ERROR;
222 wake_up(&buf->vb.done);
223 dprintk(1,"[%p/%d] %s - dma=0x%08lx\n",
224 buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
225 }
226 if (restart)
227 cx8802_restart_queue(dev,q);
228 spin_unlock_irqrestore(&dev->slock,flags);
229}
230
231void cx8802_cancel_buffers(struct cx8802_dev *dev)
232{
233 struct cx88_dmaqueue *q = &dev->mpegq;
234
235 del_timer_sync(&q->timeout);
236 cx8802_stop_dma(dev);
237 do_cancel_buffers(dev,"cancel",0);
238}
239
240static void cx8802_timeout(unsigned long data)
241{
242 struct cx8802_dev *dev = (struct cx8802_dev*)data;
243
244 dprintk(1, "%s\n",__FUNCTION__);
245
246 if (debug)
247 cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
248 cx8802_stop_dma(dev);
249 do_cancel_buffers(dev,"timeout",1);
250}
251
252static void cx8802_mpeg_irq(struct cx8802_dev *dev)
253{
254 struct cx88_core *core = dev->core;
255 u32 status, mask, count;
256
257 status = cx_read(MO_TS_INTSTAT);
258 mask = cx_read(MO_TS_INTMSK);
259 if (0 == (status & mask))
260 return;
261
262 cx_write(MO_TS_INTSTAT, status);
263 if (debug || (status & mask & ~0xff))
264 cx88_print_irqbits(core->name, "irq mpeg ",
265 cx88_mpeg_irqs, status, mask);
266
267 /* risc op code error */
268 if (status & (1 << 16)) {
269 printk(KERN_WARNING "%s: mpeg risc op code error\n",core->name);
270 cx_clear(MO_TS_DMACNTRL, 0x11);
271 cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
272 }
273
274 /* risc1 y */
275 if (status & 0x01) {
276 spin_lock(&dev->slock);
277 count = cx_read(MO_TS_GPCNT);
278 cx88_wakeup(dev->core, &dev->mpegq, count);
279 spin_unlock(&dev->slock);
280 }
281
282 /* risc2 y */
283 if (status & 0x10) {
284 spin_lock(&dev->slock);
285 cx8802_restart_queue(dev,&dev->mpegq);
286 spin_unlock(&dev->slock);
287 }
288
289 /* other general errors */
290 if (status & 0x1f0100) {
291 spin_lock(&dev->slock);
292 cx8802_stop_dma(dev);
293 cx8802_restart_queue(dev,&dev->mpegq);
294 spin_unlock(&dev->slock);
295 }
296}
297
298static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
299{
300 struct cx8802_dev *dev = dev_id;
301 struct cx88_core *core = dev->core;
302 u32 status;
303 int loop, handled = 0;
304
305 for (loop = 0; loop < 10; loop++) {
306 status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04);
307 if (0 == status)
308 goto out;
309 handled = 1;
310 cx_write(MO_PCI_INTSTAT, status);
311
312 if (status & core->pci_irqmask)
313 cx88_core_irq(core,status);
314 if (status & 0x04)
315 cx8802_mpeg_irq(dev);
316 };
317 if (10 == loop) {
318 printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
319 core->name);
320 cx_write(MO_PCI_INTMSK,0);
321 }
322
323 out:
324 return IRQ_RETVAL(handled);
325}
326
327/* ----------------------------------------------------------- */
328/* exported stuff */
329
330int cx8802_init_common(struct cx8802_dev *dev)
331{
332 struct cx88_core *core = dev->core;
333 int err;
334
335 /* pci init */
336 if (pci_enable_device(dev->pci))
337 return -EIO;
338 pci_set_master(dev->pci);
339 if (!pci_dma_supported(dev->pci,0xffffffff)) {
340 printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name);
341 return -EIO;
342 }
343
344 pci_read_config_byte(dev->pci, PCI_CLASS_REVISION, &dev->pci_rev);
345 pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat);
346 printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, "
347 "latency: %d, mmio: 0x%lx\n", dev->core->name,
348 pci_name(dev->pci), dev->pci_rev, dev->pci->irq,
349 dev->pci_lat,pci_resource_start(dev->pci,0));
350
351 /* initialize driver struct */
352 init_MUTEX(&dev->lock);
353 spin_lock_init(&dev->slock);
354
355 /* init dma queue */
356 INIT_LIST_HEAD(&dev->mpegq.active);
357 INIT_LIST_HEAD(&dev->mpegq.queued);
358 dev->mpegq.timeout.function = cx8802_timeout;
359 dev->mpegq.timeout.data = (unsigned long)dev;
360 init_timer(&dev->mpegq.timeout);
361 cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
362 MO_TS_DMACNTRL,0x11,0x00);
363
364 /* get irq */
365 err = request_irq(dev->pci->irq, cx8802_irq,
366 SA_SHIRQ | SA_INTERRUPT, dev->core->name, dev);
367 if (err < 0) {
368 printk(KERN_ERR "%s: can't get IRQ %d\n",
369 dev->core->name, dev->pci->irq);
370 return err;
371 }
372 cx_set(MO_PCI_INTMSK, core->pci_irqmask);
373
374 /* everything worked */
375 pci_set_drvdata(dev->pci,dev);
376 return 0;
377}
378
379void cx8802_fini_common(struct cx8802_dev *dev)
380{
381 cx8802_stop_dma(dev);
382 pci_disable_device(dev->pci);
383
384 /* unregister stuff */
385 free_irq(dev->pci->irq, dev);
386 pci_set_drvdata(dev->pci, NULL);
387
388 /* free memory */
389 btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);
390}
391
392/* ----------------------------------------------------------- */
393
394int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
395{
396 struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
397 struct cx88_core *core = dev->core;
398
399 /* stop mpeg dma */
400 spin_lock(&dev->slock);
401 if (!list_empty(&dev->mpegq.active)) {
402 printk("%s: suspend mpeg\n", core->name);
403 cx8802_stop_dma(dev);
404 del_timer(&dev->mpegq.timeout);
405 }
406 spin_unlock(&dev->slock);
407
408#if 1
409 /* FIXME -- shutdown device */
410 cx88_shutdown(dev->core);
411#endif
412
413 pci_save_state(pci_dev);
414 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
415 pci_disable_device(pci_dev);
416 dev->state.disabled = 1;
417 }
418 return 0;
419}
420
421int cx8802_resume_common(struct pci_dev *pci_dev)
422{
423 struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
424 struct cx88_core *core = dev->core;
425
426 if (dev->state.disabled) {
427 pci_enable_device(pci_dev);
428 dev->state.disabled = 0;
429 }
430 pci_set_power_state(pci_dev, PCI_D0);
431 pci_restore_state(pci_dev);
432
433#if 1
434 /* FIXME: re-initialize hardware */
435 cx88_reset(dev->core);
436#endif
437
438 /* restart video+vbi capture */
439 spin_lock(&dev->slock);
440 if (!list_empty(&dev->mpegq.active)) {
441 printk("%s: resume mpeg\n", core->name);
442 cx8802_restart_queue(dev,&dev->mpegq);
443 }
444 spin_unlock(&dev->slock);
445
446 return 0;
447}
448
449/* ----------------------------------------------------------- */
450
451EXPORT_SYMBOL(cx8802_buf_prepare);
452EXPORT_SYMBOL(cx8802_buf_queue);
453EXPORT_SYMBOL(cx8802_cancel_buffers);
454
455EXPORT_SYMBOL(cx8802_init_common);
456EXPORT_SYMBOL(cx8802_fini_common);
457
458EXPORT_SYMBOL(cx8802_suspend_common);
459EXPORT_SYMBOL(cx8802_resume_common);
460
461/* ----------------------------------------------------------- */
462/*
463 * Local variables:
464 * c-basic-offset: 8
465 * End:
466 */
diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h
new file mode 100644
index 000000000000..8638ce57d84c
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-reg.h
@@ -0,0 +1,787 @@
1/*
2 $Id: cx88-reg.h,v 1.6 2004/10/13 10:39:00 kraxel Exp $
3
4 cx88x-hw.h - CX2388x register offsets
5
6 Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
7 2001 Michael Eskin
8 2002 Yurij Sysoev <yurij@naturesoft.net>
9 2003 Gerd Knorr <kraxel@bytesex.org>
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#ifndef _CX88_REG_H_
27#define _CX88_REG_H_
28
29/* ---------------------------------------------------------------------- */
30/* PCI IDs and config space */
31
32#ifndef PCI_VENDOR_ID_CONEXANT
33# define PCI_VENDOR_ID_CONEXANT 0x14F1
34#endif
35#ifndef PCI_DEVICE_ID_CX2300_VID
36# define PCI_DEVICE_ID_CX2300_VID 0x8800
37#endif
38
39#define CX88X_DEVCTRL 0x40
40#define CX88X_EN_TBFX 0x02
41#define CX88X_EN_VSFX 0x04
42
43
44/* ---------------------------------------------------------------------- */
45/* DMA Controller registers */
46
47#define MO_PDMA_STHRSH 0x200000 // Source threshold
48#define MO_PDMA_STADRS 0x200004 // Source target address
49#define MO_PDMA_SIADRS 0x200008 // Source internal address
50#define MO_PDMA_SCNTRL 0x20000C // Source control
51#define MO_PDMA_DTHRSH 0x200010 // Destination threshold
52#define MO_PDMA_DTADRS 0x200014 // Destination target address
53#define MO_PDMA_DIADRS 0x200018 // Destination internal address
54#define MO_PDMA_DCNTRL 0x20001C // Destination control
55#define MO_LD_SSID 0x200030 // Load subsystem ID
56#define MO_DEV_CNTRL2 0x200034 // Device control
57#define MO_PCI_INTMSK 0x200040 // PCI interrupt mask
58#define MO_PCI_INTSTAT 0x200044 // PCI interrupt status
59#define MO_PCI_INTMSTAT 0x200048 // PCI interrupt masked status
60#define MO_VID_INTMSK 0x200050 // Video interrupt mask
61#define MO_VID_INTSTAT 0x200054 // Video interrupt status
62#define MO_VID_INTMSTAT 0x200058 // Video interrupt masked status
63#define MO_VID_INTSSTAT 0x20005C // Video interrupt set status
64#define MO_AUD_INTMSK 0x200060 // Audio interrupt mask
65#define MO_AUD_INTSTAT 0x200064 // Audio interrupt status
66#define MO_AUD_INTMSTAT 0x200068 // Audio interrupt masked status
67#define MO_AUD_INTSSTAT 0x20006C // Audio interrupt set status
68#define MO_TS_INTMSK 0x200070 // Transport stream interrupt mask
69#define MO_TS_INTSTAT 0x200074 // Transport stream interrupt status
70#define MO_TS_INTMSTAT 0x200078 // Transport stream interrupt mask status
71#define MO_TS_INTSSTAT 0x20007C // Transport stream interrupt set status
72#define MO_VIP_INTMSK 0x200080 // VIP interrupt mask
73#define MO_VIP_INTSTAT 0x200084 // VIP interrupt status
74#define MO_VIP_INTMSTAT 0x200088 // VIP interrupt masked status
75#define MO_VIP_INTSSTAT 0x20008C // VIP interrupt set status
76#define MO_GPHST_INTMSK 0x200090 // Host interrupt mask
77#define MO_GPHST_INTSTAT 0x200094 // Host interrupt status
78#define MO_GPHST_INTMSTAT 0x200098 // Host interrupt masked status
79#define MO_GPHST_INTSSTAT 0x20009C // Host interrupt set status
80
81// DMA Channels 1-6 belong to SPIPE
82#define MO_DMA7_PTR1 0x300018 // {24}RW* DMA Current Ptr : Ch#7
83#define MO_DMA8_PTR1 0x30001C // {24}RW* DMA Current Ptr : Ch#8
84
85// DMA Channels 9-20 belong to SPIPE
86#define MO_DMA21_PTR1 0x300080 // {24}R0* DMA Current Ptr : Ch#21
87#define MO_DMA22_PTR1 0x300084 // {24}R0* DMA Current Ptr : Ch#22
88#define MO_DMA23_PTR1 0x300088 // {24}R0* DMA Current Ptr : Ch#23
89#define MO_DMA24_PTR1 0x30008C // {24}R0* DMA Current Ptr : Ch#24
90#define MO_DMA25_PTR1 0x300090 // {24}R0* DMA Current Ptr : Ch#25
91#define MO_DMA26_PTR1 0x300094 // {24}R0* DMA Current Ptr : Ch#26
92#define MO_DMA27_PTR1 0x300098 // {24}R0* DMA Current Ptr : Ch#27
93#define MO_DMA28_PTR1 0x30009C // {24}R0* DMA Current Ptr : Ch#28
94#define MO_DMA29_PTR1 0x3000A0 // {24}R0* DMA Current Ptr : Ch#29
95#define MO_DMA30_PTR1 0x3000A4 // {24}R0* DMA Current Ptr : Ch#30
96#define MO_DMA31_PTR1 0x3000A8 // {24}R0* DMA Current Ptr : Ch#31
97#define MO_DMA32_PTR1 0x3000AC // {24}R0* DMA Current Ptr : Ch#32
98
99#define MO_DMA21_PTR2 0x3000C0 // {24}RW* DMA Tab Ptr : Ch#21
100#define MO_DMA22_PTR2 0x3000C4 // {24}RW* DMA Tab Ptr : Ch#22
101#define MO_DMA23_PTR2 0x3000C8 // {24}RW* DMA Tab Ptr : Ch#23
102#define MO_DMA24_PTR2 0x3000CC // {24}RW* DMA Tab Ptr : Ch#24
103#define MO_DMA25_PTR2 0x3000D0 // {24}RW* DMA Tab Ptr : Ch#25
104#define MO_DMA26_PTR2 0x3000D4 // {24}RW* DMA Tab Ptr : Ch#26
105#define MO_DMA27_PTR2 0x3000D8 // {24}RW* DMA Tab Ptr : Ch#27
106#define MO_DMA28_PTR2 0x3000DC // {24}RW* DMA Tab Ptr : Ch#28
107#define MO_DMA29_PTR2 0x3000E0 // {24}RW* DMA Tab Ptr : Ch#29
108#define MO_DMA30_PTR2 0x3000E4 // {24}RW* DMA Tab Ptr : Ch#30
109#define MO_DMA31_PTR2 0x3000E8 // {24}RW* DMA Tab Ptr : Ch#31
110#define MO_DMA32_PTR2 0x3000EC // {24}RW* DMA Tab Ptr : Ch#32
111
112#define MO_DMA21_CNT1 0x300100 // {11}RW* DMA Buffer Size : Ch#21
113#define MO_DMA22_CNT1 0x300104 // {11}RW* DMA Buffer Size : Ch#22
114#define MO_DMA23_CNT1 0x300108 // {11}RW* DMA Buffer Size : Ch#23
115#define MO_DMA24_CNT1 0x30010C // {11}RW* DMA Buffer Size : Ch#24
116#define MO_DMA25_CNT1 0x300110 // {11}RW* DMA Buffer Size : Ch#25
117#define MO_DMA26_CNT1 0x300114 // {11}RW* DMA Buffer Size : Ch#26
118#define MO_DMA27_CNT1 0x300118 // {11}RW* DMA Buffer Size : Ch#27
119#define MO_DMA28_CNT1 0x30011C // {11}RW* DMA Buffer Size : Ch#28
120#define MO_DMA29_CNT1 0x300120 // {11}RW* DMA Buffer Size : Ch#29
121#define MO_DMA30_CNT1 0x300124 // {11}RW* DMA Buffer Size : Ch#30
122#define MO_DMA31_CNT1 0x300128 // {11}RW* DMA Buffer Size : Ch#31
123#define MO_DMA32_CNT1 0x30012C // {11}RW* DMA Buffer Size : Ch#32
124
125#define MO_DMA21_CNT2 0x300140 // {11}RW* DMA Table Size : Ch#21
126#define MO_DMA22_CNT2 0x300144 // {11}RW* DMA Table Size : Ch#22
127#define MO_DMA23_CNT2 0x300148 // {11}RW* DMA Table Size : Ch#23
128#define MO_DMA24_CNT2 0x30014C // {11}RW* DMA Table Size : Ch#24
129#define MO_DMA25_CNT2 0x300150 // {11}RW* DMA Table Size : Ch#25
130#define MO_DMA26_CNT2 0x300154 // {11}RW* DMA Table Size : Ch#26
131#define MO_DMA27_CNT2 0x300158 // {11}RW* DMA Table Size : Ch#27
132#define MO_DMA28_CNT2 0x30015C // {11}RW* DMA Table Size : Ch#28
133#define MO_DMA29_CNT2 0x300160 // {11}RW* DMA Table Size : Ch#29
134#define MO_DMA30_CNT2 0x300164 // {11}RW* DMA Table Size : Ch#30
135#define MO_DMA31_CNT2 0x300168 // {11}RW* DMA Table Size : Ch#31
136#define MO_DMA32_CNT2 0x30016C // {11}RW* DMA Table Size : Ch#32
137
138
139/* ---------------------------------------------------------------------- */
140/* Video registers */
141
142#define MO_VIDY_DMA 0x310000 // {64}RWp Video Y
143#define MO_VIDU_DMA 0x310008 // {64}RWp Video U
144#define MO_VIDV_DMA 0x310010 // {64}RWp Video V
145#define MO_VBI_DMA 0x310018 // {64}RWp VBI (Vertical blanking interval)
146
147#define MO_DEVICE_STATUS 0x310100
148#define MO_INPUT_FORMAT 0x310104
149#define MO_AGC_BURST 0x31010c
150#define MO_CONTR_BRIGHT 0x310110
151#define MO_UV_SATURATION 0x310114
152#define MO_HUE 0x310118
153#define MO_HTOTAL 0x310120
154#define MO_HDELAY_EVEN 0x310124
155#define MO_HDELAY_ODD 0x310128
156#define MO_VDELAY_ODD 0x31012c
157#define MO_VDELAY_EVEN 0x310130
158#define MO_HACTIVE_EVEN 0x31013c
159#define MO_HACTIVE_ODD 0x310140
160#define MO_VACTIVE_EVEN 0x310144
161#define MO_VACTIVE_ODD 0x310148
162#define MO_HSCALE_EVEN 0x31014c
163#define MO_HSCALE_ODD 0x310150
164#define MO_VSCALE_EVEN 0x310154
165#define MO_FILTER_EVEN 0x31015c
166#define MO_VSCALE_ODD 0x310158
167#define MO_FILTER_ODD 0x310160
168#define MO_OUTPUT_FORMAT 0x310164
169
170#define MO_PLL_REG 0x310168 // PLL register
171#define MO_PLL_ADJ_CTRL 0x31016c // PLL adjust control register
172#define MO_SCONV_REG 0x310170 // sample rate conversion register
173#define MO_SCONV_FIFO 0x310174 // sample rate conversion fifo
174#define MO_SUB_STEP 0x310178 // subcarrier step size
175#define MO_SUB_STEP_DR 0x31017c // subcarrier step size for DR line
176
177#define MO_CAPTURE_CTRL 0x310180 // capture control
178#define MO_COLOR_CTRL 0x310184
179#define MO_VBI_PACKET 0x310188 // vbi packet size / delay
180#define MO_FIELD_COUNT 0x310190 // field counter
181#define MO_VIP_CONFIG 0x310194
182#define MO_VBOS_CONTROL 0x3101a8
183
184#define MO_AGC_BACK_VBI 0x310200
185#define MO_AGC_SYNC_TIP1 0x310208
186
187#define MO_VIDY_GPCNT 0x31C020 // {16}RO Video Y general purpose counter
188#define MO_VIDU_GPCNT 0x31C024 // {16}RO Video U general purpose counter
189#define MO_VIDV_GPCNT 0x31C028 // {16}RO Video V general purpose counter
190#define MO_VBI_GPCNT 0x31C02C // {16}RO VBI general purpose counter
191#define MO_VIDY_GPCNTRL 0x31C030 // {2}WO Video Y general purpose control
192#define MO_VIDU_GPCNTRL 0x31C034 // {2}WO Video U general purpose control
193#define MO_VIDV_GPCNTRL 0x31C038 // {2}WO Video V general purpose control
194#define MO_VBI_GPCNTRL 0x31C03C // {2}WO VBI general purpose counter
195#define MO_VID_DMACNTRL 0x31C040 // {8}RW Video DMA control
196#define MO_VID_XFR_STAT 0x31C044 // {1}RO Video transfer status
197
198
199/* ---------------------------------------------------------------------- */
200/* audio registers */
201
202#define MO_AUDD_DMA 0x320000 // {64}RWp Audio downstream
203#define MO_AUDU_DMA 0x320008 // {64}RWp Audio upstream
204#define MO_AUDR_DMA 0x320010 // {64}RWp Audio RDS (downstream)
205#define MO_AUDD_GPCNT 0x32C020 // {16}RO Audio down general purpose counter
206#define MO_AUDU_GPCNT 0x32C024 // {16}RO Audio up general purpose counter
207#define MO_AUDR_GPCNT 0x32C028 // {16}RO Audio RDS general purpose counter
208#define MO_AUDD_GPCNTRL 0x32C030 // {2}WO Audio down general purpose control
209#define MO_AUDU_GPCNTRL 0x32C034 // {2}WO Audio up general purpose control
210#define MO_AUDR_GPCNTRL 0x32C038 // {2}WO Audio RDS general purpose control
211#define MO_AUD_DMACNTRL 0x32C040 // {6}RW Audio DMA control
212#define MO_AUD_XFR_STAT 0x32C044 // {1}RO Audio transfer status
213#define MO_AUDD_LNGTH 0x32C048 // {12}RW Audio down line length
214#define MO_AUDR_LNGTH 0x32C04C // {12}RW Audio RDS line length
215
216#define AUD_INIT 0x320100
217#define AUD_INIT_LD 0x320104
218#define AUD_SOFT_RESET 0x320108
219#define AUD_I2SINPUTCNTL 0x320120
220#define AUD_BAUDRATE 0x320124
221#define AUD_I2SOUTPUTCNTL 0x320128
222#define AAGC_HYST 0x320134
223#define AAGC_GAIN 0x320138
224#define AAGC_DEF 0x32013c
225#define AUD_IIR1_0_SEL 0x320150
226#define AUD_IIR1_0_SHIFT 0x320154
227#define AUD_IIR1_1_SEL 0x320158
228#define AUD_IIR1_1_SHIFT 0x32015c
229#define AUD_IIR1_2_SEL 0x320160
230#define AUD_IIR1_2_SHIFT 0x320164
231#define AUD_IIR1_3_SEL 0x320168
232#define AUD_IIR1_3_SHIFT 0x32016c
233#define AUD_IIR1_4_SEL 0x320170
234#define AUD_IIR1_4_SHIFT 0x32017c
235#define AUD_IIR1_5_SEL 0x320180
236#define AUD_IIR1_5_SHIFT 0x320184
237#define AUD_IIR2_0_SEL 0x320190
238#define AUD_IIR2_0_SHIFT 0x320194
239#define AUD_IIR2_1_SEL 0x320198
240#define AUD_IIR2_1_SHIFT 0x32019c
241#define AUD_IIR2_2_SEL 0x3201a0
242#define AUD_IIR2_2_SHIFT 0x3201a4
243#define AUD_IIR2_3_SEL 0x3201a8
244#define AUD_IIR2_3_SHIFT 0x3201ac
245#define AUD_IIR3_0_SEL 0x3201c0
246#define AUD_IIR3_0_SHIFT 0x3201c4
247#define AUD_IIR3_1_SEL 0x3201c8
248#define AUD_IIR3_1_SHIFT 0x3201cc
249#define AUD_IIR3_2_SEL 0x3201d0
250#define AUD_IIR3_2_SHIFT 0x3201d4
251#define AUD_IIR4_0_SEL 0x3201e0
252#define AUD_IIR4_0_SHIFT 0x3201e4
253#define AUD_IIR4_1_SEL 0x3201e8
254#define AUD_IIR4_1_SHIFT 0x3201ec
255#define AUD_IIR4_2_SEL 0x3201f0
256#define AUD_IIR4_2_SHIFT 0x3201f4
257#define AUD_IIR4_0_CA0 0x320200
258#define AUD_IIR4_0_CA1 0x320204
259#define AUD_IIR4_0_CA2 0x320208
260#define AUD_IIR4_0_CB0 0x32020c
261#define AUD_IIR4_0_CB1 0x320210
262#define AUD_IIR4_1_CA0 0x320214
263#define AUD_IIR4_1_CA1 0x320218
264#define AUD_IIR4_1_CA2 0x32021c
265#define AUD_IIR4_1_CB0 0x320220
266#define AUD_IIR4_1_CB1 0x320224
267#define AUD_IIR4_2_CA0 0x320228
268#define AUD_IIR4_2_CA1 0x32022c
269#define AUD_IIR4_2_CA2 0x320230
270#define AUD_IIR4_2_CB0 0x320234
271#define AUD_IIR4_2_CB1 0x320238
272#define AUD_HP_MD_IIR4_1 0x320250
273#define AUD_HP_PROG_IIR4_1 0x320254
274#define AUD_FM_MODE_ENABLE 0x320258
275#define AUD_POLY0_DDS_CONSTANT 0x320270
276#define AUD_DN0_FREQ 0x320274
277#define AUD_DN1_FREQ 0x320278
278#define AUD_DN1_FREQ_SHIFT 0x32027c
279#define AUD_DN1_AFC 0x320280
280#define AUD_DN1_SRC_SEL 0x320284
281#define AUD_DN1_SHFT 0x320288
282#define AUD_DN2_FREQ 0x32028c
283#define AUD_DN2_FREQ_SHIFT 0x320290
284#define AUD_DN2_AFC 0x320294
285#define AUD_DN2_SRC_SEL 0x320298
286#define AUD_DN2_SHFT 0x32029c
287#define AUD_CRDC0_SRC_SEL 0x320300
288#define AUD_CRDC0_SHIFT 0x320304
289#define AUD_CORDIC_SHIFT_0 0x320308
290#define AUD_CRDC1_SRC_SEL 0x32030c
291#define AUD_CRDC1_SHIFT 0x320310
292#define AUD_CORDIC_SHIFT_1 0x320314
293#define AUD_DCOC_0_SRC 0x320320
294#define AUD_DCOC0_SHIFT 0x320324
295#define AUD_DCOC_0_SHIFT_IN0 0x320328
296#define AUD_DCOC_0_SHIFT_IN1 0x32032c
297#define AUD_DCOC_1_SRC 0x320330
298#define AUD_DCOC1_SHIFT 0x320334
299#define AUD_DCOC_1_SHIFT_IN0 0x320338
300#define AUD_DCOC_1_SHIFT_IN1 0x32033c
301#define AUD_DCOC_2_SRC 0x320340
302#define AUD_DCOC2_SHIFT 0x320344
303#define AUD_DCOC_2_SHIFT_IN0 0x320348
304#define AUD_DCOC_2_SHIFT_IN1 0x32034c
305#define AUD_DCOC_PASS_IN 0x320350
306#define AUD_PDET_SRC 0x320370
307#define AUD_PDET_SHIFT 0x320374
308#define AUD_PILOT_BQD_1_K0 0x320380
309#define AUD_PILOT_BQD_1_K1 0x320384
310#define AUD_PILOT_BQD_1_K2 0x320388
311#define AUD_PILOT_BQD_1_K3 0x32038c
312#define AUD_PILOT_BQD_1_K4 0x320390
313#define AUD_PILOT_BQD_2_K0 0x320394
314#define AUD_PILOT_BQD_2_K1 0x320398
315#define AUD_PILOT_BQD_2_K2 0x32039c
316#define AUD_PILOT_BQD_2_K3 0x3203a0
317#define AUD_PILOT_BQD_2_K4 0x3203a4
318#define AUD_THR_FR 0x3203c0
319#define AUD_X_PROG 0x3203c4
320#define AUD_Y_PROG 0x3203c8
321#define AUD_HARMONIC_MULT 0x3203cc
322#define AUD_C1_UP_THR 0x3203d0
323#define AUD_C1_LO_THR 0x3203d4
324#define AUD_C2_UP_THR 0x3203d8
325#define AUD_C2_LO_THR 0x3203dc
326#define AUD_PLL_EN 0x320400
327#define AUD_PLL_SRC 0x320404
328#define AUD_PLL_SHIFT 0x320408
329#define AUD_PLL_IF_SEL 0x32040c
330#define AUD_PLL_IF_SHIFT 0x320410
331#define AUD_BIQUAD_PLL_K0 0x320414
332#define AUD_BIQUAD_PLL_K1 0x320418
333#define AUD_BIQUAD_PLL_K2 0x32041c
334#define AUD_BIQUAD_PLL_K3 0x320420
335#define AUD_BIQUAD_PLL_K4 0x320424
336#define AUD_DEEMPH0_SRC_SEL 0x320440
337#define AUD_DEEMPH0_SHIFT 0x320444
338#define AUD_DEEMPH0_G0 0x320448
339#define AUD_DEEMPH0_A0 0x32044c
340#define AUD_DEEMPH0_B0 0x320450
341#define AUD_DEEMPH0_A1 0x320454
342#define AUD_DEEMPH0_B1 0x320458
343#define AUD_DEEMPH1_SRC_SEL 0x32045c
344#define AUD_DEEMPH1_SHIFT 0x320460
345#define AUD_DEEMPH1_G0 0x320464
346#define AUD_DEEMPH1_A0 0x320468
347#define AUD_DEEMPH1_B0 0x32046c
348#define AUD_DEEMPH1_A1 0x320470
349#define AUD_DEEMPH1_B1 0x320474
350#define AUD_OUT0_SEL 0x320490
351#define AUD_OUT0_SHIFT 0x320494
352#define AUD_OUT1_SEL 0x320498
353#define AUD_OUT1_SHIFT 0x32049c
354#define AUD_RDSI_SEL 0x3204a0
355#define AUD_RDSI_SHIFT 0x3204a4
356#define AUD_RDSQ_SEL 0x3204a8
357#define AUD_RDSQ_SHIFT 0x3204ac
358#define AUD_DBX_IN_GAIN 0x320500
359#define AUD_DBX_WBE_GAIN 0x320504
360#define AUD_DBX_SE_GAIN 0x320508
361#define AUD_DBX_RMS_WBE 0x32050c
362#define AUD_DBX_RMS_SE 0x320510
363#define AUD_DBX_SE_BYPASS 0x320514
364#define AUD_FAWDETCTL 0x320530
365#define AUD_FAWDETWINCTL 0x320534
366#define AUD_DEEMPHGAIN_R 0x320538
367#define AUD_DEEMPHNUMER1_R 0x32053c
368#define AUD_DEEMPHNUMER2_R 0x320540
369#define AUD_DEEMPHDENOM1_R 0x320544
370#define AUD_DEEMPHDENOM2_R 0x320548
371#define AUD_ERRLOGPERIOD_R 0x32054c
372#define AUD_ERRINTRPTTHSHLD1_R 0x320550
373#define AUD_ERRINTRPTTHSHLD2_R 0x320554
374#define AUD_ERRINTRPTTHSHLD3_R 0x320558
375#define AUD_NICAM_STATUS1 0x32055c
376#define AUD_NICAM_STATUS2 0x320560
377#define AUD_ERRLOG1 0x320564
378#define AUD_ERRLOG2 0x320568
379#define AUD_ERRLOG3 0x32056c
380#define AUD_DAC_BYPASS_L 0x320580
381#define AUD_DAC_BYPASS_R 0x320584
382#define AUD_DAC_BYPASS_CTL 0x320588
383#define AUD_CTL 0x32058c
384#define AUD_STATUS 0x320590
385#define AUD_VOL_CTL 0x320594
386#define AUD_BAL_CTL 0x320598
387#define AUD_START_TIMER 0x3205b0
388#define AUD_MODE_CHG_TIMER 0x3205b4
389#define AUD_POLYPH80SCALEFAC 0x3205b8
390#define AUD_DMD_RA_DDS 0x3205bc
391#define AUD_I2S_RA_DDS 0x3205c0
392#define AUD_RATE_THRES_DMD 0x3205d0
393#define AUD_RATE_THRES_I2S 0x3205d4
394#define AUD_RATE_ADJ1 0x3205d8
395#define AUD_RATE_ADJ2 0x3205dc
396#define AUD_RATE_ADJ3 0x3205e0
397#define AUD_RATE_ADJ4 0x3205e4
398#define AUD_RATE_ADJ5 0x3205e8
399#define AUD_APB_IN_RATE_ADJ 0x3205ec
400#define AUD_PHASE_FIX_CTL 0x3205f0
401#define AUD_PLL_PRESCALE 0x320600
402#define AUD_PLL_DDS 0x320604
403#define AUD_PLL_INT 0x320608
404#define AUD_PLL_FRAC 0x32060c
405#define AUD_PLL_JTAG 0x320620
406#define AUD_PLL_SPMP 0x320624
407#define AUD_AFE_12DB_EN 0x320628
408
409// Audio QAM Register Addresses
410#define AUD_PDF_DDS_CNST_BYTE2 0x320d01
411#define AUD_PDF_DDS_CNST_BYTE1 0x320d02
412#define AUD_PDF_DDS_CNST_BYTE0 0x320d03
413#define AUD_PHACC_FREQ_8MSB 0x320d2a
414#define AUD_PHACC_FREQ_8LSB 0x320d2b
415#define AUD_QAM_MODE 0x320d04
416
417
418/* ---------------------------------------------------------------------- */
419/* transport stream registers */
420
421#define MO_TS_DMA 0x330000 // {64}RWp Transport stream downstream
422#define MO_TS_GPCNT 0x33C020 // {16}RO TS general purpose counter
423#define MO_TS_GPCNTRL 0x33C030 // {2}WO TS general purpose control
424#define MO_TS_DMACNTRL 0x33C040 // {6}RW TS DMA control
425#define MO_TS_XFR_STAT 0x33C044 // {1}RO TS transfer status
426#define MO_TS_LNGTH 0x33C048 // {12}RW TS line length
427
428#define TS_HW_SOP_CNTRL 0x33C04C
429#define TS_GEN_CNTRL 0x33C050
430#define TS_BD_PKT_STAT 0x33C054
431#define TS_SOP_STAT 0x33C058
432#define TS_FIFO_OVFL_STAT 0x33C05C
433#define TS_VALERR_CNTRL 0x33C060
434
435
436/* ---------------------------------------------------------------------- */
437/* VIP registers */
438
439#define MO_VIPD_DMA 0x340000 // {64}RWp VIP downstream
440#define MO_VIPU_DMA 0x340008 // {64}RWp VIP upstream
441#define MO_VIPD_GPCNT 0x34C020 // {16}RO VIP down general purpose counter
442#define MO_VIPU_GPCNT 0x34C024 // {16}RO VIP up general purpose counter
443#define MO_VIPD_GPCNTRL 0x34C030 // {2}WO VIP down general purpose control
444#define MO_VIPU_GPCNTRL 0x34C034 // {2}WO VIP up general purpose control
445#define MO_VIP_DMACNTRL 0x34C040 // {6}RW VIP DMA control
446#define MO_VIP_XFR_STAT 0x34C044 // {1}RO VIP transfer status
447#define MO_VIP_CFG 0x340048 // VIP configuration
448#define MO_VIPU_CNTRL 0x34004C // VIP upstream control #1
449#define MO_VIPD_CNTRL 0x340050 // VIP downstream control #2
450#define MO_VIPD_LNGTH 0x340054 // VIP downstream line length
451#define MO_VIP_BRSTLN 0x340058 // VIP burst length
452#define MO_VIP_INTCNTRL 0x34C05C // VIP Interrupt Control
453#define MO_VIP_XFTERM 0x340060 // VIP transfer terminate
454
455
456/* ---------------------------------------------------------------------- */
457/* misc registers */
458
459#define MO_M2M_DMA 0x350000 // {64}RWp Mem2Mem DMA Bfr
460#define MO_GP0_IO 0x350010 // {32}RW* GPIOoutput enablesdata I/O
461#define MO_GP1_IO 0x350014 // {32}RW* GPIOoutput enablesdata I/O
462#define MO_GP2_IO 0x350018 // {32}RW* GPIOoutput enablesdata I/O
463#define MO_GP3_IO 0x35001C // {32}RW* GPIO Mode/Ctrloutput enables
464#define MO_GPIO 0x350020 // {32}RW* GPIO I2C Ctrldata I/O
465#define MO_GPOE 0x350024 // {32}RW GPIO I2C Ctrloutput enables
466#define MO_GP_ISM 0x350028 // {16}WO GPIO Intr Sens/Pol
467
468#define MO_PLL_B 0x35C008 // {32}RW* PLL Control for ASB bus clks
469#define MO_M2M_CNT 0x35C024 // {32}RW Mem2Mem DMA Cnt
470#define MO_M2M_XSUM 0x35C028 // {32}RO M2M XOR-Checksum
471#define MO_CRC 0x35C02C // {16}RW CRC16 init/result
472#define MO_CRC_D 0x35C030 // {32}WO CRC16 new data in
473#define MO_TM_CNT_LDW 0x35C034 // {32}RO Timer : Counter low dword
474#define MO_TM_CNT_UW 0x35C038 // {16}RO Timer : Counter high word
475#define MO_TM_LMT_LDW 0x35C03C // {32}RW Timer : Limit low dword
476#define MO_TM_LMT_UW 0x35C040 // {32}RW Timer : Limit high word
477#define MO_PINMUX_IO 0x35C044 // {8}RW Pin Mux Control
478#define MO_TSTSEL_IO 0x35C048 // {2}RW Pin Mux Control
479#define MO_AFECFG_IO 0x35C04C // AFE configuration reg
480#define MO_DDS_IO 0x35C050 // DDS Increment reg
481#define MO_DDSCFG_IO 0x35C054 // DDS Configuration reg
482#define MO_SAMPLE_IO 0x35C058 // IRIn sample reg
483#define MO_SRST_IO 0x35C05C // Output system reset reg
484
485#define MO_INT1_MSK 0x35C060 // DMA RISC interrupt mask
486#define MO_INT1_STAT 0x35C064 // DMA RISC interrupt status
487#define MO_INT1_MSTAT 0x35C068 // DMA RISC interrupt masked status
488
489
490/* ---------------------------------------------------------------------- */
491/* i2c bus registers */
492
493#define MO_I2C 0x368000 // I2C data/control
494#define MO_I2C_DIV (0xf<<4)
495#define MO_I2C_SYNC (1<<3)
496#define MO_I2C_W3B (1<<2)
497#define MO_I2C_SCL (1<<1)
498#define MO_I2C_SDA (1<<0)
499
500
501/* ---------------------------------------------------------------------- */
502/* general purpose host registers */
503/* FIXME: tyops? s/0x35/0x38/ ?? */
504
505#define MO_GPHSTD_DMA 0x350000 // {64}RWp Host downstream
506#define MO_GPHSTU_DMA 0x350008 // {64}RWp Host upstream
507#define MO_GPHSTU_CNTRL 0x380048 // Host upstream control #1
508#define MO_GPHSTD_CNTRL 0x38004C // Host downstream control #2
509#define MO_GPHSTD_LNGTH 0x380050 // Host downstream line length
510#define MO_GPHST_WSC 0x380054 // Host wait state control
511#define MO_GPHST_XFR 0x380058 // Host transfer control
512#define MO_GPHST_WDTH 0x38005C // Host interface width
513#define MO_GPHST_HDSHK 0x380060 // Host peripheral handshake
514#define MO_GPHST_MUX16 0x380064 // Host muxed 16-bit transfer parameters
515#define MO_GPHST_MODE 0x380068 // Host mode select
516
517#define MO_GPHSTD_GPCNT 0x35C020 // Host down general purpose counter
518#define MO_GPHSTU_GPCNT 0x35C024 // Host up general purpose counter
519#define MO_GPHSTD_GPCNTRL 0x38C030 // Host down general purpose control
520#define MO_GPHSTU_GPCNTRL 0x38C034 // Host up general purpose control
521#define MO_GPHST_DMACNTRL 0x38C040 // Host DMA control
522#define MO_GPHST_XFR_STAT 0x38C044 // Host transfer status
523#define MO_GPHST_SOFT_RST 0x38C06C // Host software reset
524
525
526/* ---------------------------------------------------------------------- */
527/* RISC instructions */
528
529#define RISC_SYNC 0x80000000
530#define RISC_SYNC_ODD 0x80000000
531#define RISC_SYNC_EVEN 0x80000200
532#define RISC_RESYNC 0x80008000
533#define RISC_RESYNC_ODD 0x80008000
534#define RISC_RESYNC_EVEN 0x80008200
535#define RISC_WRITE 0x10000000
536#define RISC_WRITEC 0x50000000
537#define RISC_READ 0x90000000
538#define RISC_READC 0xA0000000
539#define RISC_JUMP 0x70000000
540#define RISC_SKIP 0x20000000
541#define RISC_WRITERM 0xB0000000
542#define RISC_WRITECM 0xC0000000
543#define RISC_WRITECR 0xD0000000
544#define RISC_IMM 0x00000001
545
546#define RISC_SOL 0x08000000
547#define RISC_EOL 0x04000000
548
549#define RISC_IRQ2 0x02000000
550#define RISC_IRQ1 0x01000000
551
552#define RISC_CNT_NONE 0x00000000
553#define RISC_CNT_INC 0x00010000
554#define RISC_CNT_RSVR 0x00020000
555#define RISC_CNT_RESET 0x00030000
556#define RISC_JMP_SRP 0x01
557
558
559/* ---------------------------------------------------------------------- */
560/* various constants */
561
562#define SEL_BTSC 0x01
563#define SEL_EIAJ 0x02
564#define SEL_A2 0x04
565#define SEL_SAP 0x08
566#define SEL_NICAM 0x10
567#define SEL_FMRADIO 0x20
568
569// AUD_CTL
570#define EN_BTSC_FORCE_MONO 0
571#define EN_BTSC_FORCE_STEREO 1
572#define EN_BTSC_FORCE_SAP 2
573#define EN_BTSC_AUTO_STEREO 3
574#define EN_BTSC_AUTO_SAP 4
575
576#define EN_A2_FORCE_MONO1 8
577#define EN_A2_FORCE_MONO2 9
578#define EN_A2_FORCE_STEREO 10
579#define EN_A2_AUTO_MONO2 11
580#define EN_A2_AUTO_STEREO 12
581
582#define EN_EIAJ_FORCE_MONO1 16
583#define EN_EIAJ_FORCE_MONO2 17
584#define EN_EIAJ_FORCE_STEREO 18
585#define EN_EIAJ_AUTO_MONO2 19
586#define EN_EIAJ_AUTO_STEREO 20
587
588#define EN_NICAM_FORCE_MONO1 32
589#define EN_NICAM_FORCE_MONO2 33
590#define EN_NICAM_FORCE_STEREO 34
591#define EN_NICAM_AUTO_MONO2 35
592#define EN_NICAM_AUTO_STEREO 36
593
594#define EN_FMRADIO_FORCE_MONO 24
595#define EN_FMRADIO_FORCE_STEREO 25
596#define EN_FMRADIO_AUTO_STEREO 26
597
598#define EN_NICAM_AUTO_FALLBACK 0x00000040
599#define EN_FMRADIO_EN_RDS 0x00000200
600#define EN_NICAM_TRY_AGAIN_BIT 0x00000400
601#define EN_DAC_ENABLE 0x00001000
602#define EN_I2SOUT_ENABLE 0x00002000
603#define EN_I2SIN_STR2DAC 0x00004000
604#define EN_I2SIN_ENABLE 0x00008000
605
606#if 0
607/* old */
608#define EN_DMTRX_SUMDIFF 0x00000800
609#define EN_DMTRX_SUMR 0x00000880
610#define EN_DMTRX_LR 0x00000900
611#define EN_DMTRX_MONO 0x00000980
612#else
613/* dscaler cvs */
614#define EN_DMTRX_SUMDIFF (0 << 7)
615#define EN_DMTRX_SUMR (1 << 7)
616#define EN_DMTRX_LR (2 << 7)
617#define EN_DMTRX_MONO (3 << 7)
618#define EN_DMTRX_BYPASS (1 << 11)
619#endif
620
621// Video
622#define VID_CAPTURE_CONTROL 0x310180
623
624#define CX23880_CAP_CTL_CAPTURE_VBI_ODD (1<<3)
625#define CX23880_CAP_CTL_CAPTURE_VBI_EVEN (1<<2)
626#define CX23880_CAP_CTL_CAPTURE_ODD (1<<1)
627#define CX23880_CAP_CTL_CAPTURE_EVEN (1<<0)
628
629#define VideoInputMux0 0x0
630#define VideoInputMux1 0x1
631#define VideoInputMux2 0x2
632#define VideoInputMux3 0x3
633#define VideoInputTuner 0x0
634#define VideoInputComposite 0x1
635#define VideoInputSVideo 0x2
636#define VideoInputOther 0x3
637
638#define Xtal0 0x1
639#define Xtal1 0x2
640#define XtalAuto 0x3
641
642#define VideoFormatAuto 0x0
643#define VideoFormatNTSC 0x1
644#define VideoFormatNTSCJapan 0x2
645#define VideoFormatNTSC443 0x3
646#define VideoFormatPAL 0x4
647#define VideoFormatPALB 0x4
648#define VideoFormatPALD 0x4
649#define VideoFormatPALG 0x4
650#define VideoFormatPALH 0x4
651#define VideoFormatPALI 0x4
652#define VideoFormatPALBDGHI 0x4
653#define VideoFormatPALM 0x5
654#define VideoFormatPALN 0x6
655#define VideoFormatPALNC 0x7
656#define VideoFormatPAL60 0x8
657#define VideoFormatSECAM 0x9
658
659#define VideoFormatAuto27MHz 0x10
660#define VideoFormatNTSC27MHz 0x11
661#define VideoFormatNTSCJapan27MHz 0x12
662#define VideoFormatNTSC44327MHz 0x13
663#define VideoFormatPAL27MHz 0x14
664#define VideoFormatPALB27MHz 0x14
665#define VideoFormatPALD27MHz 0x14
666#define VideoFormatPALG27MHz 0x14
667#define VideoFormatPALH27MHz 0x14
668#define VideoFormatPALI27MHz 0x14
669#define VideoFormatPALBDGHI27MHz 0x14
670#define VideoFormatPALM27MHz 0x15
671#define VideoFormatPALN27MHz 0x16
672#define VideoFormatPALNC27MHz 0x17
673#define VideoFormatPAL6027MHz 0x18
674#define VideoFormatSECAM27MHz 0x19
675
676#define NominalUSECAM 0x87
677#define NominalVSECAM 0x85
678#define NominalUNTSC 0xFE
679#define NominalVNTSC 0xB4
680
681#define NominalContrast 0xD8
682
683#define HFilterAutoFormat 0x0
684#define HFilterCIF 0x1
685#define HFilterQCIF 0x2
686#define HFilterICON 0x3
687
688#define VFilter2TapInterpolate 0
689#define VFilter3TapInterpolate 1
690#define VFilter4TapInterpolate 2
691#define VFilter5TapInterpolate 3
692#define VFilter2TapNoInterpolate 4
693#define VFilter3TapNoInterpolate 5
694#define VFilter4TapNoInterpolate 6
695#define VFilter5TapNoInterpolate 7
696
697#define ColorFormatRGB32 0x0000
698#define ColorFormatRGB24 0x0011
699#define ColorFormatRGB16 0x0022
700#define ColorFormatRGB15 0x0033
701#define ColorFormatYUY2 0x0044
702#define ColorFormatBTYUV 0x0055
703#define ColorFormatY8 0x0066
704#define ColorFormatRGB8 0x0077
705#define ColorFormatPL422 0x0088
706#define ColorFormatPL411 0x0099
707#define ColorFormatYUV12 0x00AA
708#define ColorFormatYUV9 0x00BB
709#define ColorFormatRAW 0x00EE
710#define ColorFormatBSWAP 0x0300
711#define ColorFormatWSWAP 0x0c00
712#define ColorFormatEvenMask 0x050f
713#define ColorFormatOddMask 0x0af0
714#define ColorFormatGamma 0x1000
715
716#define Interlaced 0x1
717#define NonInterlaced 0x0
718
719#define FieldEven 0x1
720#define FieldOdd 0x0
721
722#define TGReadWriteMode 0x0
723#define TGEnableMode 0x1
724
725#define DV_CbAlign 0x0
726#define DV_Y0Align 0x1
727#define DV_CrAlign 0x2
728#define DV_Y1Align 0x3
729
730#define DVF_Analog 0x0
731#define DVF_CCIR656 0x1
732#define DVF_ByteStream 0x2
733#define DVF_ExtVSYNC 0x4
734#define DVF_ExtField 0x5
735
736#define CHANNEL_VID_Y 0x1
737#define CHANNEL_VID_U 0x2
738#define CHANNEL_VID_V 0x3
739#define CHANNEL_VID_VBI 0x4
740#define CHANNEL_AUD_DN 0x5
741#define CHANNEL_AUD_UP 0x6
742#define CHANNEL_AUD_RDS_DN 0x7
743#define CHANNEL_MPEG_DN 0x8
744#define CHANNEL_VIP_DN 0x9
745#define CHANNEL_VIP_UP 0xA
746#define CHANNEL_HOST_DN 0xB
747#define CHANNEL_HOST_UP 0xC
748#define CHANNEL_FIRST 0x1
749#define CHANNEL_LAST 0xC
750
751#define GP_COUNT_CONTROL_NONE 0x0
752#define GP_COUNT_CONTROL_INC 0x1
753#define GP_COUNT_CONTROL_RESERVED 0x2
754#define GP_COUNT_CONTROL_RESET 0x3
755
756#define PLL_PRESCALE_BY_2 2
757#define PLL_PRESCALE_BY_3 3
758#define PLL_PRESCALE_BY_4 4
759#define PLL_PRESCALE_BY_5 5
760
761#define HLNotchFilter4xFsc 0
762#define HLNotchFilterSquare 1
763#define HLNotchFilter135NTSC 2
764#define HLNotchFilter135PAL 3
765
766#define NTSC_8x_SUB_CARRIER 28.63636E6
767#define PAL_8x_SUB_CARRIER 35.46895E6
768
769// Default analog settings
770#define DEFAULT_HUE_NTSC 0x00
771#define DEFAULT_BRIGHTNESS_NTSC 0x00
772#define DEFAULT_CONTRAST_NTSC 0x39
773#define DEFAULT_SAT_U_NTSC 0x7F
774#define DEFAULT_SAT_V_NTSC 0x5A
775
776typedef enum
777{
778 SOURCE_TUNER = 0,
779 SOURCE_COMPOSITE,
780 SOURCE_SVIDEO,
781 SOURCE_OTHER1,
782 SOURCE_OTHER2,
783 SOURCE_COMPVIASVIDEO,
784 SOURCE_CCIR656
785} VIDEOSOURCETYPE;
786
787#endif /* _CX88_REG_H_ */
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
new file mode 100644
index 000000000000..f2a9475a2fee
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -0,0 +1,1032 @@
1/*
2 $Id: cx88-tvaudio.c,v 1.34 2005/03/07 16:10:51 kraxel Exp $
3
4 cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
5
6 (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version]
7 (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
8 (c) 2003 Gerd Knorr <kraxel@bytesex.org>
9
10 -----------------------------------------------------------------------
11
12 Lot of voodoo here. Even the data sheet doesn't help to
13 understand what is going on here, the documentation for the audio
14 part of the cx2388x chip is *very* bad.
15
16 Some of this comes from party done linux driver sources I got from
17 [undocumented].
18
19 Some comes from the dscaler sources, one of the dscaler driver guy works
20 for Conexant ...
21
22 -----------------------------------------------------------------------
23
24 This program is free software; you can redistribute it and/or modify
25 it under the terms of the GNU General Public License as published by
26 the Free Software Foundation; either version 2 of the License, or
27 (at your option) any later version.
28
29 This program is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
33
34 You should have received a copy of the GNU General Public License
35 along with this program; if not, write to the Free Software
36 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
37*/
38
39#include <linux/module.h>
40#include <linux/moduleparam.h>
41#include <linux/errno.h>
42#include <linux/kernel.h>
43#include <linux/slab.h>
44#include <linux/mm.h>
45#include <linux/poll.h>
46#include <linux/pci.h>
47#include <linux/signal.h>
48#include <linux/ioport.h>
49#include <linux/sched.h>
50#include <linux/types.h>
51#include <linux/interrupt.h>
52#include <linux/vmalloc.h>
53#include <linux/init.h>
54#include <linux/smp_lock.h>
55#include <linux/delay.h>
56#include <linux/kthread.h>
57
58#include "cx88.h"
59
60static unsigned int audio_debug = 0;
61module_param(audio_debug,int,0644);
62MODULE_PARM_DESC(audio_debug,"enable debug messages [audio]");
63
64#define dprintk(fmt, arg...) if (audio_debug) \
65 printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
66
67/* ----------------------------------------------------------- */
68
69static char *aud_ctl_names[64] =
70{
71 [ EN_BTSC_FORCE_MONO ] = "BTSC_FORCE_MONO",
72 [ EN_BTSC_FORCE_STEREO ] = "BTSC_FORCE_STEREO",
73 [ EN_BTSC_FORCE_SAP ] = "BTSC_FORCE_SAP",
74 [ EN_BTSC_AUTO_STEREO ] = "BTSC_AUTO_STEREO",
75 [ EN_BTSC_AUTO_SAP ] = "BTSC_AUTO_SAP",
76 [ EN_A2_FORCE_MONO1 ] = "A2_FORCE_MONO1",
77 [ EN_A2_FORCE_MONO2 ] = "A2_FORCE_MONO2",
78 [ EN_A2_FORCE_STEREO ] = "A2_FORCE_STEREO",
79 [ EN_A2_AUTO_MONO2 ] = "A2_AUTO_MONO2",
80 [ EN_A2_AUTO_STEREO ] = "A2_AUTO_STEREO",
81 [ EN_EIAJ_FORCE_MONO1 ] = "EIAJ_FORCE_MONO1",
82 [ EN_EIAJ_FORCE_MONO2 ] = "EIAJ_FORCE_MONO2",
83 [ EN_EIAJ_FORCE_STEREO ] = "EIAJ_FORCE_STEREO",
84 [ EN_EIAJ_AUTO_MONO2 ] = "EIAJ_AUTO_MONO2",
85 [ EN_EIAJ_AUTO_STEREO ] = "EIAJ_AUTO_STEREO",
86 [ EN_NICAM_FORCE_MONO1 ] = "NICAM_FORCE_MONO1",
87 [ EN_NICAM_FORCE_MONO2 ] = "NICAM_FORCE_MONO2",
88 [ EN_NICAM_FORCE_STEREO ] = "NICAM_FORCE_STEREO",
89 [ EN_NICAM_AUTO_MONO2 ] = "NICAM_AUTO_MONO2",
90 [ EN_NICAM_AUTO_STEREO ] = "NICAM_AUTO_STEREO",
91 [ EN_FMRADIO_FORCE_MONO ] = "FMRADIO_FORCE_MONO",
92 [ EN_FMRADIO_FORCE_STEREO ] = "FMRADIO_FORCE_STEREO",
93 [ EN_FMRADIO_AUTO_STEREO ] = "FMRADIO_AUTO_STEREO",
94};
95
96struct rlist {
97 u32 reg;
98 u32 val;
99};
100
101static void set_audio_registers(struct cx88_core *core,
102 const struct rlist *l)
103{
104 int i;
105
106 for (i = 0; l[i].reg; i++) {
107 switch (l[i].reg) {
108 case AUD_PDF_DDS_CNST_BYTE2:
109 case AUD_PDF_DDS_CNST_BYTE1:
110 case AUD_PDF_DDS_CNST_BYTE0:
111 case AUD_QAM_MODE:
112 case AUD_PHACC_FREQ_8MSB:
113 case AUD_PHACC_FREQ_8LSB:
114 cx_writeb(l[i].reg, l[i].val);
115 break;
116 default:
117 cx_write(l[i].reg, l[i].val);
118 break;
119 }
120 }
121}
122
123static void set_audio_start(struct cx88_core *core,
124 u32 mode, u32 ctl)
125{
126 // mute
127 cx_write(AUD_VOL_CTL, (1 << 6));
128
129 // increase level of input by 12dB
130 cx_write(AUD_AFE_12DB_EN, 0x0001);
131
132 // start programming
133 cx_write(AUD_CTL, 0x0000);
134 cx_write(AUD_INIT, mode);
135 cx_write(AUD_INIT_LD, 0x0001);
136 cx_write(AUD_SOFT_RESET, 0x0001);
137
138 cx_write(AUD_CTL, ctl);
139}
140
141static void set_audio_finish(struct cx88_core *core)
142{
143 u32 volume;
144
145 if (cx88_boards[core->board].blackbird) {
146 // 'pass-thru mode': this enables the i2s output to the mpeg encoder
147 cx_set(AUD_CTL, 0x2000);
148 cx_write(AUD_I2SOUTPUTCNTL, 1);
149 //cx_write(AUD_APB_IN_RATE_ADJ, 0);
150 }
151
152 // finish programming
153 cx_write(AUD_SOFT_RESET, 0x0000);
154
155 // start audio processing
156 cx_set(AUD_CTL, EN_DAC_ENABLE);
157
158 // unmute
159 volume = cx_sread(SHADOW_AUD_VOL_CTL);
160 cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
161}
162
163/* ----------------------------------------------------------- */
164
165static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap)
166{
167 static const struct rlist btsc[] = {
168 /* from dscaler */
169 { AUD_OUT1_SEL, 0x00000013 },
170 { AUD_OUT1_SHIFT, 0x00000000 },
171 { AUD_POLY0_DDS_CONSTANT, 0x0012010c },
172 { AUD_DMD_RA_DDS, 0x00c3e7aa },
173 { AUD_DBX_IN_GAIN, 0x00004734 },
174 { AUD_DBX_WBE_GAIN, 0x00004640 },
175 { AUD_DBX_SE_GAIN, 0x00008d31 },
176 { AUD_DCOC_0_SRC, 0x0000001a },
177 { AUD_IIR1_4_SEL, 0x00000021 },
178 { AUD_DCOC_PASS_IN, 0x00000003 },
179 { AUD_DCOC_0_SHIFT_IN0, 0x0000000a },
180 { AUD_DCOC_0_SHIFT_IN1, 0x00000008 },
181 { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
182 { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
183 { AUD_DN0_FREQ, 0x0000283b },
184 { AUD_DN2_SRC_SEL, 0x00000008 },
185 { AUD_DN2_FREQ, 0x00003000 },
186 { AUD_DN2_AFC, 0x00000002 },
187 { AUD_DN2_SHFT, 0x00000000 },
188 { AUD_IIR2_2_SEL, 0x00000020 },
189 { AUD_IIR2_2_SHIFT, 0x00000000 },
190 { AUD_IIR2_3_SEL, 0x0000001f },
191 { AUD_IIR2_3_SHIFT, 0x00000000 },
192 { AUD_CRDC1_SRC_SEL, 0x000003ce },
193 { AUD_CRDC1_SHIFT, 0x00000000 },
194 { AUD_CORDIC_SHIFT_1, 0x00000007 },
195 { AUD_DCOC_1_SRC, 0x0000001b },
196 { AUD_DCOC1_SHIFT, 0x00000000 },
197 { AUD_RDSI_SEL, 0x00000008 },
198 { AUD_RDSQ_SEL, 0x00000008 },
199 { AUD_RDSI_SHIFT, 0x00000000 },
200 { AUD_RDSQ_SHIFT, 0x00000000 },
201 { AUD_POLYPH80SCALEFAC, 0x00000003 },
202 { /* end of list */ },
203 };
204 static const struct rlist btsc_sap[] = {
205 { AUD_DBX_IN_GAIN, 0x00007200 },
206 { AUD_DBX_WBE_GAIN, 0x00006200 },
207 { AUD_DBX_SE_GAIN, 0x00006200 },
208 { AUD_IIR1_1_SEL, 0x00000000 },
209 { AUD_IIR1_3_SEL, 0x00000001 },
210 { AUD_DN1_SRC_SEL, 0x00000007 },
211 { AUD_IIR1_4_SHIFT, 0x00000006 },
212 { AUD_IIR2_1_SHIFT, 0x00000000 },
213 { AUD_IIR2_2_SHIFT, 0x00000000 },
214 { AUD_IIR3_0_SHIFT, 0x00000000 },
215 { AUD_IIR3_1_SHIFT, 0x00000000 },
216 { AUD_IIR3_0_SEL, 0x0000000d },
217 { AUD_IIR3_1_SEL, 0x0000000e },
218 { AUD_DEEMPH1_SRC_SEL, 0x00000014 },
219 { AUD_DEEMPH1_SHIFT, 0x00000000 },
220 { AUD_DEEMPH1_G0, 0x00004000 },
221 { AUD_DEEMPH1_A0, 0x00000000 },
222 { AUD_DEEMPH1_B0, 0x00000000 },
223 { AUD_DEEMPH1_A1, 0x00000000 },
224 { AUD_DEEMPH1_B1, 0x00000000 },
225 { AUD_OUT0_SEL, 0x0000003f },
226 { AUD_OUT1_SEL, 0x0000003f },
227 { AUD_DN1_AFC, 0x00000002 },
228 { AUD_DCOC_0_SHIFT_IN0, 0x0000000a },
229 { AUD_DCOC_0_SHIFT_IN1, 0x00000008 },
230 { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
231 { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
232 { AUD_IIR1_0_SEL, 0x0000001d },
233 { AUD_IIR1_2_SEL, 0x0000001e },
234 { AUD_IIR2_1_SEL, 0x00000002 },
235 { AUD_IIR2_2_SEL, 0x00000004 },
236 { AUD_IIR3_2_SEL, 0x0000000f },
237 { AUD_DCOC2_SHIFT, 0x00000001 },
238 { AUD_IIR3_2_SHIFT, 0x00000001 },
239 { AUD_DEEMPH0_SRC_SEL, 0x00000014 },
240 { AUD_CORDIC_SHIFT_1, 0x00000006 },
241 { AUD_POLY0_DDS_CONSTANT, 0x000e4db2 },
242 { AUD_DMD_RA_DDS, 0x00f696e6 },
243 { AUD_IIR2_3_SEL, 0x00000025 },
244 { AUD_IIR1_4_SEL, 0x00000021 },
245 { AUD_DN1_FREQ, 0x0000c965 },
246 { AUD_DCOC_PASS_IN, 0x00000003 },
247 { AUD_DCOC_0_SRC, 0x0000001a },
248 { AUD_DCOC_1_SRC, 0x0000001b },
249 { AUD_DCOC1_SHIFT, 0x00000000 },
250 { AUD_RDSI_SEL, 0x00000009 },
251 { AUD_RDSQ_SEL, 0x00000009 },
252 { AUD_RDSI_SHIFT, 0x00000000 },
253 { AUD_RDSQ_SHIFT, 0x00000000 },
254 { AUD_POLYPH80SCALEFAC, 0x00000003 },
255 { /* end of list */ },
256 };
257
258 // dscaler: exactly taken from driver,
259 // dscaler: don't know why to set EN_FMRADIO_EN_RDS
260 if (sap) {
261 dprintk("%s SAP (status: unknown)\n",__FUNCTION__);
262 set_audio_start(core, 0x0001,
263 EN_FMRADIO_EN_RDS | EN_BTSC_FORCE_SAP);
264 set_audio_registers(core, btsc_sap);
265 } else {
266 dprintk("%s (status: known-good)\n",__FUNCTION__);
267 set_audio_start(core, 0x0001,
268 EN_FMRADIO_EN_RDS | EN_BTSC_AUTO_STEREO);
269 set_audio_registers(core, btsc);
270 }
271 set_audio_finish(core);
272}
273
274#if 0
275static void set_audio_standard_NICAM(struct cx88_core *core)
276{
277 static const struct rlist nicam_common[] = {
278 /* from dscaler */
279 { AUD_RATE_ADJ1, 0x00000010 },
280 { AUD_RATE_ADJ2, 0x00000040 },
281 { AUD_RATE_ADJ3, 0x00000100 },
282 { AUD_RATE_ADJ4, 0x00000400 },
283 { AUD_RATE_ADJ5, 0x00001000 },
284 // { AUD_DMD_RA_DDS, 0x00c0d5ce },
285
286 // Deemphasis 1:
287 { AUD_DEEMPHGAIN_R, 0x000023c2 },
288 { AUD_DEEMPHNUMER1_R, 0x0002a7bc },
289 { AUD_DEEMPHNUMER2_R, 0x0003023e },
290 { AUD_DEEMPHDENOM1_R, 0x0000f3d0 },
291 { AUD_DEEMPHDENOM2_R, 0x00000000 },
292
293#if 0
294 // Deemphasis 2: (other tv norm?)
295 { AUD_DEEMPHGAIN_R, 0x0000c600 },
296 { AUD_DEEMPHNUMER1_R, 0x00066738 },
297 { AUD_DEEMPHNUMER2_R, 0x00066739 },
298 { AUD_DEEMPHDENOM1_R, 0x0001e88c },
299 { AUD_DEEMPHDENOM2_R, 0x0001e88c },
300#endif
301
302 { AUD_DEEMPHDENOM2_R, 0x00000000 },
303 { AUD_ERRLOGPERIOD_R, 0x00000fff },
304 { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff },
305 { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff },
306 { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f },
307 { AUD_POLYPH80SCALEFAC, 0x00000003 },
308
309 // setup QAM registers
310 { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
311 { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
312 { AUD_PDF_DDS_CNST_BYTE0, 0x16 },
313 { AUD_QAM_MODE, 0x05 },
314
315 { /* end of list */ },
316 };
317 static const struct rlist nicam_pal_i[] = {
318 { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
319 { AUD_PHACC_FREQ_8MSB, 0x3a },
320 { AUD_PHACC_FREQ_8LSB, 0x93 },
321
322 { /* end of list */ },
323 };
324 static const struct rlist nicam_default[] = {
325 { AUD_PDF_DDS_CNST_BYTE0, 0x16 },
326 { AUD_PHACC_FREQ_8MSB, 0x34 },
327 { AUD_PHACC_FREQ_8LSB, 0x4c },
328
329 { /* end of list */ },
330 };
331
332 set_audio_start(core, 0x0010,
333 EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
334 set_audio_registers(core, nicam_common);
335 switch (core->tvaudio) {
336 case WW_NICAM_I:
337 dprintk("%s PAL-I NICAM (status: unknown)\n",__FUNCTION__);
338 set_audio_registers(core, nicam_pal_i);
339 break;
340 case WW_NICAM_BGDKL:
341 dprintk("%s PAL-BGDK NICAM (status: unknown)\n",__FUNCTION__);
342 set_audio_registers(core, nicam_default);
343 break;
344 };
345 set_audio_finish(core);
346}
347#endif
348
349static void set_audio_standard_NICAM_L(struct cx88_core *core, int stereo)
350{
351 /* This is probably weird..
352 * Let's operate and find out. */
353
354 static const struct rlist nicam_l_mono[] = {
355 { AUD_ERRLOGPERIOD_R, 0x00000064 },
356 { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
357 { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
358 { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
359
360 { AUD_PDF_DDS_CNST_BYTE2, 0x48 },
361 { AUD_PDF_DDS_CNST_BYTE1, 0x3D },
362 { AUD_QAM_MODE, 0x00 },
363 { AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
364 { AUD_PHACC_FREQ_8MSB, 0x3a },
365 { AUD_PHACC_FREQ_8LSB, 0x4a },
366
367 { AUD_DEEMPHGAIN_R, 0x6680 },
368 { AUD_DEEMPHNUMER1_R, 0x353DE },
369 { AUD_DEEMPHNUMER2_R, 0x1B1 },
370 { AUD_DEEMPHDENOM1_R, 0x0F3D0 },
371 { AUD_DEEMPHDENOM2_R, 0x0 },
372 { AUD_FM_MODE_ENABLE, 0x7 },
373 { AUD_POLYPH80SCALEFAC, 0x3 },
374 { AUD_AFE_12DB_EN, 0x1 },
375 { AAGC_GAIN, 0x0 },
376 { AAGC_HYST, 0x18 },
377 { AAGC_DEF, 0x20 },
378 { AUD_DN0_FREQ, 0x0 },
379 { AUD_POLY0_DDS_CONSTANT, 0x0E4DB2 },
380 { AUD_DCOC_0_SRC, 0x21 },
381 { AUD_IIR1_0_SEL, 0x0 },
382 { AUD_IIR1_0_SHIFT, 0x7 },
383 { AUD_IIR1_1_SEL, 0x2 },
384 { AUD_IIR1_1_SHIFT, 0x0 },
385 { AUD_DCOC_1_SRC, 0x3 },
386 { AUD_DCOC1_SHIFT, 0x0 },
387 { AUD_DCOC_PASS_IN, 0x0 },
388 { AUD_IIR1_2_SEL, 0x23 },
389 { AUD_IIR1_2_SHIFT, 0x0 },
390 { AUD_IIR1_3_SEL, 0x4 },
391 { AUD_IIR1_3_SHIFT, 0x7 },
392 { AUD_IIR1_4_SEL, 0x5 },
393 { AUD_IIR1_4_SHIFT, 0x7 },
394 { AUD_IIR3_0_SEL, 0x7 },
395 { AUD_IIR3_0_SHIFT, 0x0 },
396 { AUD_DEEMPH0_SRC_SEL, 0x11 },
397 { AUD_DEEMPH0_SHIFT, 0x0 },
398 { AUD_DEEMPH0_G0, 0x7000 },
399 { AUD_DEEMPH0_A0, 0x0 },
400 { AUD_DEEMPH0_B0, 0x0 },
401 { AUD_DEEMPH0_A1, 0x0 },
402 { AUD_DEEMPH0_B1, 0x0 },
403 { AUD_DEEMPH1_SRC_SEL, 0x11 },
404 { AUD_DEEMPH1_SHIFT, 0x0 },
405 { AUD_DEEMPH1_G0, 0x7000 },
406 { AUD_DEEMPH1_A0, 0x0 },
407 { AUD_DEEMPH1_B0, 0x0 },
408 { AUD_DEEMPH1_A1, 0x0 },
409 { AUD_DEEMPH1_B1, 0x0 },
410 { AUD_OUT0_SEL, 0x3F },
411 { AUD_OUT1_SEL, 0x3F },
412 { AUD_DMD_RA_DDS, 0x0F5C285 },
413 { AUD_PLL_INT, 0x1E },
414 { AUD_PLL_DDS, 0x0 },
415 { AUD_PLL_FRAC, 0x0E542 },
416
417 // setup QAM registers
418 { AUD_RATE_ADJ1, 0x00000100 },
419 { AUD_RATE_ADJ2, 0x00000200 },
420 { AUD_RATE_ADJ3, 0x00000300 },
421 { AUD_RATE_ADJ4, 0x00000400 },
422 { AUD_RATE_ADJ5, 0x00000500 },
423 { AUD_RATE_THRES_DMD, 0x000000C0 },
424 { /* end of list */ },
425 };
426
427 static const struct rlist nicam_l[] = {
428 // setup QAM registers
429 { AUD_RATE_ADJ1, 0x00000060 },
430 { AUD_RATE_ADJ2, 0x000000F9 },
431 { AUD_RATE_ADJ3, 0x000001CC },
432 { AUD_RATE_ADJ4, 0x000002B3 },
433 { AUD_RATE_ADJ5, 0x00000726 },
434 { AUD_DEEMPHDENOM1_R, 0x0000F3D0 },
435 { AUD_DEEMPHDENOM2_R, 0x00000000 },
436 { AUD_ERRLOGPERIOD_R, 0x00000064 },
437 { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
438 { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
439 { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
440 { AUD_POLYPH80SCALEFAC, 0x00000003 },
441 { AUD_DMD_RA_DDS, 0x00C00000 },
442 { AUD_PLL_INT, 0x0000001E },
443 { AUD_PLL_DDS, 0x00000000 },
444 { AUD_PLL_FRAC, 0x0000E542 },
445 { AUD_START_TIMER, 0x00000000 },
446 { AUD_DEEMPHNUMER1_R, 0x000353DE },
447 { AUD_DEEMPHNUMER2_R, 0x000001B1 },
448 { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
449 { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
450 { AUD_QAM_MODE, 0x05 },
451 { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
452 { AUD_PHACC_FREQ_8MSB, 0x34 },
453 { AUD_PHACC_FREQ_8LSB, 0x4C },
454 { AUD_DEEMPHGAIN_R, 0x00006680 },
455 { AUD_RATE_THRES_DMD, 0x000000C0 },
456 { /* end of list */ },
457 } ;
458 dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
459
460 if (!stereo) {
461 /* AM mono sound */
462 set_audio_start(core, 0x0004,
463 0x100c /* FIXME again */);
464 set_audio_registers(core, nicam_l_mono);
465 } else {
466 set_audio_start(core, 0x0010,
467 0x1924 /* FIXME again */);
468 set_audio_registers(core, nicam_l);
469 }
470 set_audio_finish(core);
471
472}
473
474static void set_audio_standard_PAL_I(struct cx88_core *core, int stereo)
475{
476 static const struct rlist pal_i_fm_mono[] = {
477 {AUD_ERRLOGPERIOD_R, 0x00000064},
478 {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
479 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
480 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
481 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
482 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
483 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
484 {AUD_QAM_MODE, 0x05},
485 {AUD_PHACC_FREQ_8MSB, 0x3a},
486 {AUD_PHACC_FREQ_8LSB, 0x93},
487 {AUD_DMD_RA_DDS, 0x002a4f2f},
488 {AUD_PLL_INT, 0x0000001e},
489 {AUD_PLL_DDS, 0x00000004},
490 {AUD_PLL_FRAC, 0x0000e542},
491 {AUD_RATE_ADJ1, 0x00000100},
492 {AUD_RATE_ADJ2, 0x00000200},
493 {AUD_RATE_ADJ3, 0x00000300},
494 {AUD_RATE_ADJ4, 0x00000400},
495 {AUD_RATE_ADJ5, 0x00000500},
496 {AUD_THR_FR, 0x00000000},
497 {AUD_PILOT_BQD_1_K0, 0x0000755b},
498 {AUD_PILOT_BQD_1_K1, 0x00551340},
499 {AUD_PILOT_BQD_1_K2, 0x006d30be},
500 {AUD_PILOT_BQD_1_K3, 0xffd394af},
501 {AUD_PILOT_BQD_1_K4, 0x00400000},
502 {AUD_PILOT_BQD_2_K0, 0x00040000},
503 {AUD_PILOT_BQD_2_K1, 0x002a4841},
504 {AUD_PILOT_BQD_2_K2, 0x00400000},
505 {AUD_PILOT_BQD_2_K3, 0x00000000},
506 {AUD_PILOT_BQD_2_K4, 0x00000000},
507 {AUD_MODE_CHG_TIMER, 0x00000060},
508 {AUD_AFE_12DB_EN, 0x00000001},
509 {AAGC_HYST, 0x0000000a},
510 {AUD_CORDIC_SHIFT_0, 0x00000007},
511 {AUD_CORDIC_SHIFT_1, 0x00000007},
512 {AUD_C1_UP_THR, 0x00007000},
513 {AUD_C1_LO_THR, 0x00005400},
514 {AUD_C2_UP_THR, 0x00005400},
515 {AUD_C2_LO_THR, 0x00003000},
516 {AUD_DCOC_0_SRC, 0x0000001a},
517 {AUD_DCOC0_SHIFT, 0x00000000},
518 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
519 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
520 {AUD_DCOC_PASS_IN, 0x00000003},
521 {AUD_IIR3_0_SEL, 0x00000021},
522 {AUD_DN2_AFC, 0x00000002},
523 {AUD_DCOC_1_SRC, 0x0000001b},
524 {AUD_DCOC1_SHIFT, 0x00000000},
525 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
526 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
527 {AUD_IIR3_1_SEL, 0x00000023},
528 {AUD_DN0_FREQ, 0x000035a3},
529 {AUD_DN2_FREQ, 0x000029c7},
530 {AUD_CRDC0_SRC_SEL, 0x00000511},
531 {AUD_IIR1_0_SEL, 0x00000001},
532 {AUD_IIR1_1_SEL, 0x00000000},
533 {AUD_IIR3_2_SEL, 0x00000003},
534 {AUD_IIR3_2_SHIFT, 0x00000000},
535 {AUD_IIR3_0_SEL, 0x00000002},
536 {AUD_IIR2_0_SEL, 0x00000021},
537 {AUD_IIR2_0_SHIFT, 0x00000002},
538 {AUD_DEEMPH0_SRC_SEL, 0x0000000b},
539 {AUD_DEEMPH1_SRC_SEL, 0x0000000b},
540 {AUD_POLYPH80SCALEFAC, 0x00000001},
541 {AUD_START_TIMER, 0x00000000},
542 { /* end of list */ },
543 };
544
545 static const struct rlist pal_i_nicam[] = {
546 { AUD_RATE_ADJ1, 0x00000010 },
547 { AUD_RATE_ADJ2, 0x00000040 },
548 { AUD_RATE_ADJ3, 0x00000100 },
549 { AUD_RATE_ADJ4, 0x00000400 },
550 { AUD_RATE_ADJ5, 0x00001000 },
551 // { AUD_DMD_RA_DDS, 0x00c0d5ce },
552 { AUD_DEEMPHGAIN_R, 0x000023c2 },
553 { AUD_DEEMPHNUMER1_R, 0x0002a7bc },
554 { AUD_DEEMPHNUMER2_R, 0x0003023e },
555 { AUD_DEEMPHDENOM1_R, 0x0000f3d0 },
556 { AUD_DEEMPHDENOM2_R, 0x00000000 },
557 { AUD_DEEMPHDENOM2_R, 0x00000000 },
558 { AUD_ERRLOGPERIOD_R, 0x00000fff },
559 { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff },
560 { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff },
561 { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f },
562 { AUD_POLYPH80SCALEFAC, 0x00000003 },
563 { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
564 { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
565 { AUD_PDF_DDS_CNST_BYTE0, 0x16 },
566 { AUD_QAM_MODE, 0x05 },
567 { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
568 { AUD_PHACC_FREQ_8MSB, 0x3a },
569 { AUD_PHACC_FREQ_8LSB, 0x93 },
570 { /* end of list */ },
571 };
572
573 dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
574
575 if (!stereo) {
576 // FM mono
577 set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_FORCE_MONO1);
578 set_audio_registers(core, pal_i_fm_mono);
579 } else {
580 // Nicam Stereo
581 set_audio_start(core, 0x0010, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
582 set_audio_registers(core, pal_i_nicam);
583 }
584 set_audio_finish(core);
585}
586
587static void set_audio_standard_A2(struct cx88_core *core)
588{
589 /* from dscaler cvs */
590 static const struct rlist a2_common[] = {
591 { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
592 { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
593 { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
594 { AUD_QAM_MODE, 0x05 },
595 { AUD_PHACC_FREQ_8MSB, 0x34 },
596 { AUD_PHACC_FREQ_8LSB, 0x4c },
597
598 { AUD_RATE_ADJ1, 0x00001000 },
599 { AUD_RATE_ADJ2, 0x00002000 },
600 { AUD_RATE_ADJ3, 0x00003000 },
601 { AUD_RATE_ADJ4, 0x00004000 },
602 { AUD_RATE_ADJ5, 0x00005000 },
603 { AUD_THR_FR, 0x00000000 },
604 { AAGC_HYST, 0x0000001a },
605 { AUD_PILOT_BQD_1_K0, 0x0000755b },
606 { AUD_PILOT_BQD_1_K1, 0x00551340 },
607 { AUD_PILOT_BQD_1_K2, 0x006d30be },
608 { AUD_PILOT_BQD_1_K3, 0xffd394af },
609 { AUD_PILOT_BQD_1_K4, 0x00400000 },
610 { AUD_PILOT_BQD_2_K0, 0x00040000 },
611 { AUD_PILOT_BQD_2_K1, 0x002a4841 },
612 { AUD_PILOT_BQD_2_K2, 0x00400000 },
613 { AUD_PILOT_BQD_2_K3, 0x00000000 },
614 { AUD_PILOT_BQD_2_K4, 0x00000000 },
615 { AUD_MODE_CHG_TIMER, 0x00000040 },
616 { AUD_START_TIMER, 0x00000200 },
617 { AUD_AFE_12DB_EN, 0x00000000 },
618 { AUD_CORDIC_SHIFT_0, 0x00000007 },
619 { AUD_CORDIC_SHIFT_1, 0x00000007 },
620 { AUD_DEEMPH0_G0, 0x00000380 },
621 { AUD_DEEMPH1_G0, 0x00000380 },
622 { AUD_DCOC_0_SRC, 0x0000001a },
623 { AUD_DCOC0_SHIFT, 0x00000000 },
624 { AUD_DCOC_0_SHIFT_IN0, 0x0000000a },
625 { AUD_DCOC_0_SHIFT_IN1, 0x00000008 },
626 { AUD_DCOC_PASS_IN, 0x00000003 },
627 { AUD_IIR3_0_SEL, 0x00000021 },
628 { AUD_DN2_AFC, 0x00000002 },
629 { AUD_DCOC_1_SRC, 0x0000001b },
630 { AUD_DCOC1_SHIFT, 0x00000000 },
631 { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
632 { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
633 { AUD_IIR3_1_SEL, 0x00000023 },
634 { AUD_RDSI_SEL, 0x00000017 },
635 { AUD_RDSI_SHIFT, 0x00000000 },
636 { AUD_RDSQ_SEL, 0x00000017 },
637 { AUD_RDSQ_SHIFT, 0x00000000 },
638 { AUD_POLYPH80SCALEFAC, 0x00000001 },
639
640 { /* end of list */ },
641 };
642
643 static const struct rlist a2_table1[] = {
644 // PAL-BG
645 { AUD_DMD_RA_DDS, 0x002a73bd },
646 { AUD_C1_UP_THR, 0x00007000 },
647 { AUD_C1_LO_THR, 0x00005400 },
648 { AUD_C2_UP_THR, 0x00005400 },
649 { AUD_C2_LO_THR, 0x00003000 },
650 { /* end of list */ },
651 };
652 static const struct rlist a2_table2[] = {
653 // PAL-DK
654 { AUD_DMD_RA_DDS, 0x002a73bd },
655 { AUD_C1_UP_THR, 0x00007000 },
656 { AUD_C1_LO_THR, 0x00005400 },
657 { AUD_C2_UP_THR, 0x00005400 },
658 { AUD_C2_LO_THR, 0x00003000 },
659 { AUD_DN0_FREQ, 0x00003a1c },
660 { AUD_DN2_FREQ, 0x0000d2e0 },
661 { /* end of list */ },
662 };
663 static const struct rlist a2_table3[] = {
664 // unknown, probably NTSC-M
665 { AUD_DMD_RA_DDS, 0x002a2873 },
666 { AUD_C1_UP_THR, 0x00003c00 },
667 { AUD_C1_LO_THR, 0x00003000 },
668 { AUD_C2_UP_THR, 0x00006000 },
669 { AUD_C2_LO_THR, 0x00003c00 },
670 { AUD_DN0_FREQ, 0x00002836 },
671 { AUD_DN1_FREQ, 0x00003418 },
672 { AUD_DN2_FREQ, 0x000029c7 },
673 { AUD_POLY0_DDS_CONSTANT, 0x000a7540 },
674 { /* end of list */ },
675 };
676
677 set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO);
678 set_audio_registers(core, a2_common);
679 switch (core->tvaudio) {
680 case WW_A2_BG:
681 dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__);
682 set_audio_registers(core, a2_table1);
683 break;
684 case WW_A2_DK:
685 dprintk("%s PAL-DK A2 (status: known-good)\n",__FUNCTION__);
686 set_audio_registers(core, a2_table2);
687 break;
688 case WW_A2_M:
689 dprintk("%s NTSC-M A2 (status: unknown)\n",__FUNCTION__);
690 set_audio_registers(core, a2_table3);
691 break;
692 };
693 set_audio_finish(core);
694}
695
696static void set_audio_standard_EIAJ(struct cx88_core *core)
697{
698 static const struct rlist eiaj[] = {
699 /* TODO: eiaj register settings are not there yet ... */
700
701 { /* end of list */ },
702 };
703 dprintk("%s (status: unknown)\n",__FUNCTION__);
704
705 set_audio_start(core, 0x0002, EN_EIAJ_AUTO_STEREO);
706 set_audio_registers(core, eiaj);
707 set_audio_finish(core);
708}
709
710static void set_audio_standard_FM(struct cx88_core *core)
711{
712#if 0 /* FIXME */
713 switch (dev->audio_properties.FM_deemphasis)
714 {
715 case WW_FM_DEEMPH_50:
716 //Set De-emphasis filter coefficients for 50 usec
717 cx_write(AUD_DEEMPH0_G0, 0x0C45);
718 cx_write(AUD_DEEMPH0_A0, 0x6262);
719 cx_write(AUD_DEEMPH0_B0, 0x1C29);
720 cx_write(AUD_DEEMPH0_A1, 0x3FC66);
721 cx_write(AUD_DEEMPH0_B1, 0x399A);
722
723 cx_write(AUD_DEEMPH1_G0, 0x0D80);
724 cx_write(AUD_DEEMPH1_A0, 0x6262);
725 cx_write(AUD_DEEMPH1_B0, 0x1C29);
726 cx_write(AUD_DEEMPH1_A1, 0x3FC66);
727 cx_write(AUD_DEEMPH1_B1, 0x399A);
728
729 break;
730
731 case WW_FM_DEEMPH_75:
732 //Set De-emphasis filter coefficients for 75 usec
733 cx_write(AUD_DEEMPH0_G0, 0x91B );
734 cx_write(AUD_DEEMPH0_A0, 0x6B68);
735 cx_write(AUD_DEEMPH0_B0, 0x11EC);
736 cx_write(AUD_DEEMPH0_A1, 0x3FC66);
737 cx_write(AUD_DEEMPH0_B1, 0x399A);
738
739 cx_write(AUD_DEEMPH1_G0, 0xAA0 );
740 cx_write(AUD_DEEMPH1_A0, 0x6B68);
741 cx_write(AUD_DEEMPH1_B0, 0x11EC);
742 cx_write(AUD_DEEMPH1_A1, 0x3FC66);
743 cx_write(AUD_DEEMPH1_B1, 0x399A);
744
745 break;
746 }
747#endif
748
749 dprintk("%s (status: unknown)\n",__FUNCTION__);
750 set_audio_start(core, 0x0020, EN_FMRADIO_AUTO_STEREO);
751
752 // AB: 10/2/01: this register is not being reset appropriately on occasion.
753 cx_write(AUD_POLYPH80SCALEFAC,3);
754
755 set_audio_finish(core);
756}
757
758/* ----------------------------------------------------------- */
759
760void cx88_set_tvaudio(struct cx88_core *core)
761{
762 switch (core->tvaudio) {
763 case WW_BTSC:
764 set_audio_standard_BTSC(core,0);
765 break;
766 case WW_NICAM_BGDKL:
767 set_audio_standard_NICAM_L(core,0);
768 break;
769 case WW_NICAM_I:
770 set_audio_standard_PAL_I(core,0);
771 break;
772 case WW_A2_BG:
773 case WW_A2_DK:
774 case WW_A2_M:
775 set_audio_standard_A2(core);
776 break;
777 case WW_EIAJ:
778 set_audio_standard_EIAJ(core);
779 break;
780 case WW_FM:
781 set_audio_standard_FM(core);
782 break;
783 case WW_SYSTEM_L_AM:
784 set_audio_standard_NICAM_L(core, 1);
785 break;
786 case WW_NONE:
787 default:
788 printk("%s/0: unknown tv audio mode [%d]\n",
789 core->name, core->tvaudio);
790 break;
791 }
792 return;
793}
794
795void cx88_newstation(struct cx88_core *core)
796{
797 core->audiomode_manual = UNSET;
798
799 switch (core->tvaudio) {
800 case WW_SYSTEM_L_AM:
801 /* try nicam ... */
802 core->audiomode_current = V4L2_TUNER_MODE_STEREO;
803 set_audio_standard_NICAM_L(core, 1);
804 break;
805 }
806}
807
808void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
809{
810 static char *m[] = {"stereo", "dual mono", "mono", "sap"};
811 static char *p[] = {"no pilot", "pilot c1", "pilot c2", "?"};
812 u32 reg,mode,pilot;
813
814 reg = cx_read(AUD_STATUS);
815 mode = reg & 0x03;
816 pilot = (reg >> 2) & 0x03;
817
818 if (core->astat != reg)
819 dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",
820 reg, m[mode], p[pilot],
821 aud_ctl_names[cx_read(AUD_CTL) & 63]);
822 core->astat = reg;
823
824 t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
825 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
826 t->rxsubchans = V4L2_TUNER_SUB_MONO;
827 t->audmode = V4L2_TUNER_MODE_MONO;
828
829 switch (core->tvaudio) {
830 case WW_BTSC:
831 t->capability = V4L2_TUNER_CAP_STEREO |
832 V4L2_TUNER_CAP_SAP;
833 t->rxsubchans = V4L2_TUNER_SUB_STEREO;
834 if (1 == pilot) {
835 /* SAP */
836 t->rxsubchans |= V4L2_TUNER_SUB_SAP;
837 }
838 break;
839 case WW_A2_BG:
840 case WW_A2_DK:
841 case WW_A2_M:
842 if (1 == pilot) {
843 /* stereo */
844 t->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
845 if (0 == mode)
846 t->audmode = V4L2_TUNER_MODE_STEREO;
847 }
848 if (2 == pilot) {
849 /* dual language -- FIXME */
850 t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
851 t->audmode = V4L2_TUNER_MODE_LANG1;
852 }
853 break;
854 case WW_NICAM_BGDKL:
855 if (0 == mode) {
856 t->audmode = V4L2_TUNER_MODE_STEREO;
857 t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
858 }
859 break;
860 case WW_SYSTEM_L_AM:
861 if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) {
862 t->audmode = V4L2_TUNER_MODE_STEREO;
863 t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
864 }
865 break ;
866 default:
867 /* nothing */
868 break;
869 }
870 return;
871}
872
873void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
874{
875 u32 ctl = UNSET;
876 u32 mask = UNSET;
877
878 if (manual) {
879 core->audiomode_manual = mode;
880 } else {
881 if (UNSET != core->audiomode_manual)
882 return;
883 }
884 core->audiomode_current = mode;
885
886 switch (core->tvaudio) {
887 case WW_BTSC:
888 switch (mode) {
889 case V4L2_TUNER_MODE_MONO:
890 ctl = EN_BTSC_FORCE_MONO;
891 mask = 0x3f;
892 break;
893 case V4L2_TUNER_MODE_SAP:
894 ctl = EN_BTSC_FORCE_SAP;
895 mask = 0x3f;
896 break;
897 case V4L2_TUNER_MODE_STEREO:
898 ctl = EN_BTSC_AUTO_STEREO;
899 mask = 0x3f;
900 break;
901 }
902 break;
903 case WW_A2_BG:
904 case WW_A2_DK:
905 case WW_A2_M:
906 switch (mode) {
907 case V4L2_TUNER_MODE_MONO:
908 case V4L2_TUNER_MODE_LANG1:
909 ctl = EN_A2_FORCE_MONO1;
910 mask = 0x3f;
911 break;
912 case V4L2_TUNER_MODE_LANG2:
913 ctl = EN_A2_AUTO_MONO2;
914 mask = 0x3f;
915 break;
916 case V4L2_TUNER_MODE_STEREO:
917 ctl = EN_A2_AUTO_STEREO | EN_DMTRX_SUMR;
918 mask = 0x8bf;
919 break;
920 }
921 break;
922 case WW_NICAM_BGDKL:
923 switch (mode) {
924 case V4L2_TUNER_MODE_MONO:
925 ctl = EN_NICAM_FORCE_MONO1;
926 mask = 0x3f;
927 break;
928 case V4L2_TUNER_MODE_LANG1:
929 ctl = EN_NICAM_AUTO_MONO2;
930 mask = 0x3f;
931 break;
932 case V4L2_TUNER_MODE_STEREO:
933 ctl = EN_NICAM_FORCE_STEREO | EN_DMTRX_LR;
934 mask = 0x93f;
935 break;
936 }
937 break;
938 case WW_SYSTEM_L_AM:
939 switch (mode) {
940 case V4L2_TUNER_MODE_MONO:
941 case V4L2_TUNER_MODE_LANG1: /* FIXME */
942 set_audio_standard_NICAM_L(core, 0);
943 break;
944 case V4L2_TUNER_MODE_STEREO:
945 set_audio_standard_NICAM_L(core, 1);
946 break;
947 }
948 break;
949 case WW_NICAM_I:
950 switch (mode) {
951 case V4L2_TUNER_MODE_MONO:
952 case V4L2_TUNER_MODE_LANG1:
953 set_audio_standard_PAL_I(core, 0);
954 break;
955 case V4L2_TUNER_MODE_STEREO:
956 set_audio_standard_PAL_I(core, 1);
957 break;
958 }
959 break;
960 case WW_FM:
961 switch (mode) {
962 case V4L2_TUNER_MODE_MONO:
963 ctl = EN_FMRADIO_FORCE_MONO;
964 mask = 0x3f;
965 break;
966 case V4L2_TUNER_MODE_STEREO:
967 ctl = EN_FMRADIO_AUTO_STEREO;
968 mask = 0x3f;
969 break;
970 }
971 break;
972 }
973
974 if (UNSET != ctl) {
975 dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x "
976 "[status=0x%x,ctl=0x%x,vol=0x%x]\n",
977 mask, ctl, cx_read(AUD_STATUS),
978 cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
979 cx_andor(AUD_CTL, mask, ctl);
980 }
981 return;
982}
983
984int cx88_audio_thread(void *data)
985{
986 struct cx88_core *core = data;
987 struct v4l2_tuner t;
988 u32 mode = 0;
989
990 dprintk("cx88: tvaudio thread started\n");
991 for (;;) {
992 msleep_interruptible(1000);
993 if (kthread_should_stop())
994 break;
995
996 /* just monitor the audio status for now ... */
997 memset(&t,0,sizeof(t));
998 cx88_get_stereo(core,&t);
999
1000 if (UNSET != core->audiomode_manual)
1001 /* manually set, don't do anything. */
1002 continue;
1003
1004 /* monitor signal */
1005 if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
1006 mode = V4L2_TUNER_MODE_STEREO;
1007 else
1008 mode = V4L2_TUNER_MODE_MONO;
1009 if (mode == core->audiomode_current)
1010 continue;
1011
1012 /* automatically switch to best available mode */
1013 cx88_set_stereo(core, mode, 0);
1014 }
1015
1016 dprintk("cx88: tvaudio thread exiting\n");
1017 return 0;
1018}
1019
1020/* ----------------------------------------------------------- */
1021
1022EXPORT_SYMBOL(cx88_set_tvaudio);
1023EXPORT_SYMBOL(cx88_newstation);
1024EXPORT_SYMBOL(cx88_set_stereo);
1025EXPORT_SYMBOL(cx88_get_stereo);
1026EXPORT_SYMBOL(cx88_audio_thread);
1027
1028/*
1029 * Local variables:
1030 * c-basic-offset: 8
1031 * End:
1032 */
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
new file mode 100644
index 000000000000..471e508b0746
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -0,0 +1,248 @@
1/*
2 * $Id: cx88-vbi.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $
3 */
4#include <linux/kernel.h>
5#include <linux/module.h>
6#include <linux/moduleparam.h>
7#include <linux/init.h>
8#include <linux/slab.h>
9
10#include "cx88.h"
11
12static unsigned int vbibufs = 4;
13module_param(vbibufs,int,0644);
14MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
15
16static unsigned int vbi_debug = 0;
17module_param(vbi_debug,int,0644);
18MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
19
20#define dprintk(level,fmt, arg...) if (vbi_debug >= level) \
21 printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg)
22
23/* ------------------------------------------------------------------ */
24
25void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f)
26{
27 memset(&f->fmt.vbi,0,sizeof(f->fmt.vbi));
28
29 f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
30 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
31 f->fmt.vbi.offset = 244;
32 f->fmt.vbi.count[0] = VBI_LINE_COUNT;
33 f->fmt.vbi.count[1] = VBI_LINE_COUNT;
34
35 if (dev->core->tvnorm->id & V4L2_STD_525_60) {
36 /* ntsc */
37 f->fmt.vbi.sampling_rate = 28636363;
38 f->fmt.vbi.start[0] = 10 -1;
39 f->fmt.vbi.start[1] = 273 -1;
40
41 } else if (dev->core->tvnorm->id & V4L2_STD_625_50) {
42 /* pal */
43 f->fmt.vbi.sampling_rate = 35468950;
44 f->fmt.vbi.start[0] = 7 -1;
45 f->fmt.vbi.start[1] = 319 -1;
46 }
47}
48
49int cx8800_start_vbi_dma(struct cx8800_dev *dev,
50 struct cx88_dmaqueue *q,
51 struct cx88_buffer *buf)
52{
53 struct cx88_core *core = dev->core;
54
55 /* setup fifo + format */
56 cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24],
57 buf->vb.width, buf->risc.dma);
58
59 cx_write(MO_VBOS_CONTROL, ( (1 << 18) | // comb filter delay fixup
60 (1 << 15) | // enable vbi capture
61 (1 << 11) ));
62
63 /* reset counter */
64 cx_write(MO_VBI_GPCNTRL, GP_COUNT_CONTROL_RESET);
65 q->count = 1;
66
67 /* enable irqs */
68 cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
69 cx_set(MO_VID_INTMSK, 0x0f0088);
70
71 /* enable capture */
72 cx_set(VID_CAPTURE_CONTROL,0x18);
73
74 /* start dma */
75 cx_set(MO_DEV_CNTRL2, (1<<5));
76 cx_set(MO_VID_DMACNTRL, 0x88);
77
78 return 0;
79}
80
81int cx8800_stop_vbi_dma(struct cx8800_dev *dev)
82{
83 struct cx88_core *core = dev->core;
84
85 /* stop dma */
86 cx_clear(MO_VID_DMACNTRL, 0x88);
87
88 /* disable capture */
89 cx_clear(VID_CAPTURE_CONTROL,0x18);
90
91 /* disable irqs */
92 cx_clear(MO_PCI_INTMSK, 0x000001);
93 cx_clear(MO_VID_INTMSK, 0x0f0088);
94 return 0;
95}
96
97int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
98 struct cx88_dmaqueue *q)
99{
100 struct cx88_buffer *buf;
101 struct list_head *item;
102
103 if (list_empty(&q->active))
104 return 0;
105
106 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
107 dprintk(2,"restart_queue [%p/%d]: restart dma\n",
108 buf, buf->vb.i);
109 cx8800_start_vbi_dma(dev, q, buf);
110 list_for_each(item,&q->active) {
111 buf = list_entry(item, struct cx88_buffer, vb.queue);
112 buf->count = q->count++;
113 }
114 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
115 return 0;
116}
117
118void cx8800_vbi_timeout(unsigned long data)
119{
120 struct cx8800_dev *dev = (struct cx8800_dev*)data;
121 struct cx88_core *core = dev->core;
122 struct cx88_dmaqueue *q = &dev->vbiq;
123 struct cx88_buffer *buf;
124 unsigned long flags;
125
126 cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]);
127
128 cx_clear(MO_VID_DMACNTRL, 0x88);
129 cx_clear(VID_CAPTURE_CONTROL, 0x18);
130
131 spin_lock_irqsave(&dev->slock,flags);
132 while (!list_empty(&q->active)) {
133 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
134 list_del(&buf->vb.queue);
135 buf->vb.state = STATE_ERROR;
136 wake_up(&buf->vb.done);
137 printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name,
138 buf, buf->vb.i, (unsigned long)buf->risc.dma);
139 }
140 cx8800_restart_vbi_queue(dev,q);
141 spin_unlock_irqrestore(&dev->slock,flags);
142}
143
144/* ------------------------------------------------------------------ */
145
146static int
147vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
148{
149 *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
150 if (0 == *count)
151 *count = vbibufs;
152 if (*count < 2)
153 *count = 2;
154 if (*count > 32)
155 *count = 32;
156 return 0;
157}
158
159static int
160vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
161 enum v4l2_field field)
162{
163 struct cx8800_fh *fh = q->priv_data;
164 struct cx8800_dev *dev = fh->dev;
165 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
166 unsigned int size;
167 int rc;
168
169 size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
170 if (0 != buf->vb.baddr && buf->vb.bsize < size)
171 return -EINVAL;
172
173 if (STATE_NEEDS_INIT == buf->vb.state) {
174 buf->vb.width = VBI_LINE_LENGTH;
175 buf->vb.height = VBI_LINE_COUNT;
176 buf->vb.size = size;
177 buf->vb.field = V4L2_FIELD_SEQ_TB;
178
179 if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL)))
180 goto fail;
181 cx88_risc_buffer(dev->pci, &buf->risc,
182 buf->vb.dma.sglist,
183 0, buf->vb.width * buf->vb.height,
184 buf->vb.width, 0,
185 buf->vb.height);
186 }
187 buf->vb.state = STATE_PREPARED;
188 return 0;
189
190 fail:
191 cx88_free_buffer(dev->pci,buf);
192 return rc;
193}
194
195static void
196vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
197{
198 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
199 struct cx88_buffer *prev;
200 struct cx8800_fh *fh = vq->priv_data;
201 struct cx8800_dev *dev = fh->dev;
202 struct cx88_dmaqueue *q = &dev->vbiq;
203
204 /* add jump to stopper */
205 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
206 buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
207
208 if (list_empty(&q->active)) {
209 list_add_tail(&buf->vb.queue,&q->active);
210 cx8800_start_vbi_dma(dev, q, buf);
211 buf->vb.state = STATE_ACTIVE;
212 buf->count = q->count++;
213 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
214 dprintk(2,"[%p/%d] vbi_queue - first active\n",
215 buf, buf->vb.i);
216
217 } else {
218 prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
219 list_add_tail(&buf->vb.queue,&q->active);
220 buf->vb.state = STATE_ACTIVE;
221 buf->count = q->count++;
222 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
223 dprintk(2,"[%p/%d] buffer_queue - append to active\n",
224 buf, buf->vb.i);
225 }
226}
227
228static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
229{
230 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
231 struct cx8800_fh *fh = q->priv_data;
232
233 cx88_free_buffer(fh->dev->pci,buf);
234}
235
236struct videobuf_queue_ops cx8800_vbi_qops = {
237 .buf_setup = vbi_setup,
238 .buf_prepare = vbi_prepare,
239 .buf_queue = vbi_queue,
240 .buf_release = vbi_release,
241};
242
243/* ------------------------------------------------------------------ */
244/*
245 * Local variables:
246 * c-basic-offset: 8
247 * End:
248 */
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
new file mode 100644
index 000000000000..701f594e1816
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -0,0 +1,2277 @@
1/*
2 * $Id: cx88-video.c,v 1.58 2005/03/07 15:58:05 kraxel Exp $
3 *
4 * device driver for Conexant 2388x based TV cards
5 * video4linux video interface
6 *
7 * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/init.h>
25#include <linux/list.h>
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/kmod.h>
29#include <linux/kernel.h>
30#include <linux/slab.h>
31#include <linux/interrupt.h>
32#include <linux/delay.h>
33#include <linux/kthread.h>
34#include <asm/div64.h>
35
36#include "cx88.h"
37
38MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
39MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
40MODULE_LICENSE("GPL");
41
42/* ------------------------------------------------------------------ */
43
44static unsigned int video_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
45static unsigned int vbi_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
46static unsigned int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
47
48module_param_array(video_nr, int, NULL, 0444);
49module_param_array(vbi_nr, int, NULL, 0444);
50module_param_array(radio_nr, int, NULL, 0444);
51
52MODULE_PARM_DESC(video_nr,"video device numbers");
53MODULE_PARM_DESC(vbi_nr,"vbi device numbers");
54MODULE_PARM_DESC(radio_nr,"radio device numbers");
55
56static unsigned int video_debug = 0;
57module_param(video_debug,int,0644);
58MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
59
60static unsigned int irq_debug = 0;
61module_param(irq_debug,int,0644);
62MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
63
64static unsigned int vid_limit = 16;
65module_param(vid_limit,int,0644);
66MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
67
68#define dprintk(level,fmt, arg...) if (video_debug >= level) \
69 printk(KERN_DEBUG "%s/0: " fmt, dev->core->name , ## arg)
70
71/* ------------------------------------------------------------------ */
72
73static LIST_HEAD(cx8800_devlist);
74
75/* ------------------------------------------------------------------- */
76/* static data */
77
78static struct cx88_tvnorm tvnorms[] = {
79 {
80 .name = "NTSC-M",
81 .id = V4L2_STD_NTSC_M,
82 .cxiformat = VideoFormatNTSC,
83 .cxoformat = 0x181f0008,
84 },{
85 .name = "NTSC-JP",
86 .id = V4L2_STD_NTSC_M_JP,
87 .cxiformat = VideoFormatNTSCJapan,
88 .cxoformat = 0x181f0008,
89#if 0
90 },{
91 .name = "NTSC-4.43",
92 .id = FIXME,
93 .cxiformat = VideoFormatNTSC443,
94 .cxoformat = 0x181f0008,
95#endif
96 },{
97 .name = "PAL-BG",
98 .id = V4L2_STD_PAL_BG,
99 .cxiformat = VideoFormatPAL,
100 .cxoformat = 0x181f0008,
101 },{
102 .name = "PAL-DK",
103 .id = V4L2_STD_PAL_DK,
104 .cxiformat = VideoFormatPAL,
105 .cxoformat = 0x181f0008,
106 },{
107 .name = "PAL-I",
108 .id = V4L2_STD_PAL_I,
109 .cxiformat = VideoFormatPAL,
110 .cxoformat = 0x181f0008,
111 },{
112 .name = "PAL-M",
113 .id = V4L2_STD_PAL_M,
114 .cxiformat = VideoFormatPALM,
115 .cxoformat = 0x1c1f0008,
116 },{
117 .name = "PAL-N",
118 .id = V4L2_STD_PAL_N,
119 .cxiformat = VideoFormatPALN,
120 .cxoformat = 0x1c1f0008,
121 },{
122 .name = "PAL-Nc",
123 .id = V4L2_STD_PAL_Nc,
124 .cxiformat = VideoFormatPALNC,
125 .cxoformat = 0x1c1f0008,
126 },{
127 .name = "PAL-60",
128 .id = V4L2_STD_PAL_60,
129 .cxiformat = VideoFormatPAL60,
130 .cxoformat = 0x181f0008,
131 },{
132 .name = "SECAM-L",
133 .id = V4L2_STD_SECAM_L,
134 .cxiformat = VideoFormatSECAM,
135 .cxoformat = 0x181f0008,
136 },{
137 .name = "SECAM-DK",
138 .id = V4L2_STD_SECAM_DK,
139 .cxiformat = VideoFormatSECAM,
140 .cxoformat = 0x181f0008,
141 }
142};
143
144static struct cx8800_fmt formats[] = {
145 {
146 .name = "8 bpp, gray",
147 .fourcc = V4L2_PIX_FMT_GREY,
148 .cxformat = ColorFormatY8,
149 .depth = 8,
150 .flags = FORMAT_FLAGS_PACKED,
151 },{
152 .name = "15 bpp RGB, le",
153 .fourcc = V4L2_PIX_FMT_RGB555,
154 .cxformat = ColorFormatRGB15,
155 .depth = 16,
156 .flags = FORMAT_FLAGS_PACKED,
157 },{
158 .name = "15 bpp RGB, be",
159 .fourcc = V4L2_PIX_FMT_RGB555X,
160 .cxformat = ColorFormatRGB15 | ColorFormatBSWAP,
161 .depth = 16,
162 .flags = FORMAT_FLAGS_PACKED,
163 },{
164 .name = "16 bpp RGB, le",
165 .fourcc = V4L2_PIX_FMT_RGB565,
166 .cxformat = ColorFormatRGB16,
167 .depth = 16,
168 .flags = FORMAT_FLAGS_PACKED,
169 },{
170 .name = "16 bpp RGB, be",
171 .fourcc = V4L2_PIX_FMT_RGB565X,
172 .cxformat = ColorFormatRGB16 | ColorFormatBSWAP,
173 .depth = 16,
174 .flags = FORMAT_FLAGS_PACKED,
175 },{
176 .name = "24 bpp RGB, le",
177 .fourcc = V4L2_PIX_FMT_BGR24,
178 .cxformat = ColorFormatRGB24,
179 .depth = 24,
180 .flags = FORMAT_FLAGS_PACKED,
181 },{
182 .name = "32 bpp RGB, le",
183 .fourcc = V4L2_PIX_FMT_BGR32,
184 .cxformat = ColorFormatRGB32,
185 .depth = 32,
186 .flags = FORMAT_FLAGS_PACKED,
187 },{
188 .name = "32 bpp RGB, be",
189 .fourcc = V4L2_PIX_FMT_RGB32,
190 .cxformat = ColorFormatRGB32 | ColorFormatBSWAP | ColorFormatWSWAP,
191 .depth = 32,
192 .flags = FORMAT_FLAGS_PACKED,
193 },{
194 .name = "4:2:2, packed, YUYV",
195 .fourcc = V4L2_PIX_FMT_YUYV,
196 .cxformat = ColorFormatYUY2,
197 .depth = 16,
198 .flags = FORMAT_FLAGS_PACKED,
199 },{
200 .name = "4:2:2, packed, UYVY",
201 .fourcc = V4L2_PIX_FMT_UYVY,
202 .cxformat = ColorFormatYUY2 | ColorFormatBSWAP,
203 .depth = 16,
204 .flags = FORMAT_FLAGS_PACKED,
205 },
206};
207
208static struct cx8800_fmt* format_by_fourcc(unsigned int fourcc)
209{
210 unsigned int i;
211
212 for (i = 0; i < ARRAY_SIZE(formats); i++)
213 if (formats[i].fourcc == fourcc)
214 return formats+i;
215 return NULL;
216}
217
218/* ------------------------------------------------------------------- */
219
220static const struct v4l2_queryctrl no_ctl = {
221 .name = "42",
222 .flags = V4L2_CTRL_FLAG_DISABLED,
223};
224
225static struct cx88_ctrl cx8800_ctls[] = {
226 /* --- video --- */
227 {
228 .v = {
229 .id = V4L2_CID_BRIGHTNESS,
230 .name = "Brightness",
231 .minimum = 0x00,
232 .maximum = 0xff,
233 .step = 1,
234 .default_value = 0,
235 .type = V4L2_CTRL_TYPE_INTEGER,
236 },
237 .off = 128,
238 .reg = MO_CONTR_BRIGHT,
239 .mask = 0x00ff,
240 .shift = 0,
241 },{
242 .v = {
243 .id = V4L2_CID_CONTRAST,
244 .name = "Contrast",
245 .minimum = 0,
246 .maximum = 0xff,
247 .step = 1,
248 .default_value = 0,
249 .type = V4L2_CTRL_TYPE_INTEGER,
250 },
251 .reg = MO_CONTR_BRIGHT,
252 .mask = 0xff00,
253 .shift = 8,
254 },{
255 .v = {
256 .id = V4L2_CID_HUE,
257 .name = "Hue",
258 .minimum = 0,
259 .maximum = 0xff,
260 .step = 1,
261 .default_value = 0,
262 .type = V4L2_CTRL_TYPE_INTEGER,
263 },
264 .off = 0,
265 .reg = MO_HUE,
266 .mask = 0x00ff,
267 .shift = 0,
268 },{
269 /* strictly, this only describes only U saturation.
270 * V saturation is handled specially through code.
271 */
272 .v = {
273 .id = V4L2_CID_SATURATION,
274 .name = "Saturation",
275 .minimum = 0,
276 .maximum = 0xff,
277 .step = 1,
278 .default_value = 0,
279 .type = V4L2_CTRL_TYPE_INTEGER,
280 },
281 .off = 0,
282 .reg = MO_UV_SATURATION,
283 .mask = 0x00ff,
284 .shift = 0,
285 },{
286 /* --- audio --- */
287 .v = {
288 .id = V4L2_CID_AUDIO_MUTE,
289 .name = "Mute",
290 .minimum = 0,
291 .maximum = 1,
292 .type = V4L2_CTRL_TYPE_BOOLEAN,
293 },
294 .reg = AUD_VOL_CTL,
295 .sreg = SHADOW_AUD_VOL_CTL,
296 .mask = (1 << 6),
297 .shift = 6,
298 },{
299 .v = {
300 .id = V4L2_CID_AUDIO_VOLUME,
301 .name = "Volume",
302 .minimum = 0,
303 .maximum = 0x3f,
304 .step = 1,
305 .default_value = 0,
306 .type = V4L2_CTRL_TYPE_INTEGER,
307 },
308 .reg = AUD_VOL_CTL,
309 .sreg = SHADOW_AUD_VOL_CTL,
310 .mask = 0x3f,
311 .shift = 0,
312 },{
313 .v = {
314 .id = V4L2_CID_AUDIO_BALANCE,
315 .name = "Balance",
316 .minimum = 0,
317 .maximum = 0x7f,
318 .step = 1,
319 .default_value = 0x40,
320 .type = V4L2_CTRL_TYPE_INTEGER,
321 },
322 .reg = AUD_BAL_CTL,
323 .sreg = SHADOW_AUD_BAL_CTL,
324 .mask = 0x7f,
325 .shift = 0,
326 }
327};
328const int CX8800_CTLS = ARRAY_SIZE(cx8800_ctls);
329
330/* ------------------------------------------------------------------- */
331/* resource management */
332
333static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit)
334{
335 if (fh->resources & bit)
336 /* have it already allocated */
337 return 1;
338
339 /* is it free? */
340 down(&dev->lock);
341 if (dev->resources & bit) {
342 /* no, someone else uses it */
343 up(&dev->lock);
344 return 0;
345 }
346 /* it's free, grab it */
347 fh->resources |= bit;
348 dev->resources |= bit;
349 dprintk(1,"res: get %d\n",bit);
350 up(&dev->lock);
351 return 1;
352}
353
354static
355int res_check(struct cx8800_fh *fh, unsigned int bit)
356{
357 return (fh->resources & bit);
358}
359
360static
361int res_locked(struct cx8800_dev *dev, unsigned int bit)
362{
363 return (dev->resources & bit);
364}
365
366static
367void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
368{
369 if ((fh->resources & bits) != bits)
370 BUG();
371
372 down(&dev->lock);
373 fh->resources &= ~bits;
374 dev->resources &= ~bits;
375 dprintk(1,"res: put %d\n",bits);
376 up(&dev->lock);
377}
378
379/* ------------------------------------------------------------------ */
380
381static int video_mux(struct cx8800_dev *dev, unsigned int input)
382{
383 struct cx88_core *core = dev->core;
384
385 dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n",
386 input, INPUT(input)->vmux,
387 INPUT(input)->gpio0,INPUT(input)->gpio1,
388 INPUT(input)->gpio2,INPUT(input)->gpio3);
389 dev->core->input = input;
390 cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input)->vmux << 14);
391 cx_write(MO_GP3_IO, INPUT(input)->gpio3);
392 cx_write(MO_GP0_IO, INPUT(input)->gpio0);
393 cx_write(MO_GP1_IO, INPUT(input)->gpio1);
394 cx_write(MO_GP2_IO, INPUT(input)->gpio2);
395
396 switch (INPUT(input)->type) {
397 case CX88_VMUX_SVIDEO:
398 cx_set(MO_AFECFG_IO, 0x00000001);
399 cx_set(MO_INPUT_FORMAT, 0x00010010);
400 cx_set(MO_FILTER_EVEN, 0x00002020);
401 cx_set(MO_FILTER_ODD, 0x00002020);
402 break;
403 default:
404 cx_clear(MO_AFECFG_IO, 0x00000001);
405 cx_clear(MO_INPUT_FORMAT, 0x00010010);
406 cx_clear(MO_FILTER_EVEN, 0x00002020);
407 cx_clear(MO_FILTER_ODD, 0x00002020);
408 break;
409 }
410 return 0;
411}
412
413/* ------------------------------------------------------------------ */
414
415static int start_video_dma(struct cx8800_dev *dev,
416 struct cx88_dmaqueue *q,
417 struct cx88_buffer *buf)
418{
419 struct cx88_core *core = dev->core;
420
421 /* setup fifo + format */
422 cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH21],
423 buf->bpl, buf->risc.dma);
424 cx88_set_scale(dev->core, buf->vb.width, buf->vb.height, buf->vb.field);
425 cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
426
427 /* reset counter */
428 cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET);
429 q->count = 1;
430
431 /* enable irqs */
432 cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
433 cx_set(MO_VID_INTMSK, 0x0f0011);
434
435 /* enable capture */
436 cx_set(VID_CAPTURE_CONTROL,0x06);
437
438 /* start dma */
439 cx_set(MO_DEV_CNTRL2, (1<<5));
440 cx_set(MO_VID_DMACNTRL, 0x11);
441
442 return 0;
443}
444
445static int stop_video_dma(struct cx8800_dev *dev)
446{
447 struct cx88_core *core = dev->core;
448
449 /* stop dma */
450 cx_clear(MO_VID_DMACNTRL, 0x11);
451
452 /* disable capture */
453 cx_clear(VID_CAPTURE_CONTROL,0x06);
454
455 /* disable irqs */
456 cx_clear(MO_PCI_INTMSK, 0x000001);
457 cx_clear(MO_VID_INTMSK, 0x0f0011);
458 return 0;
459}
460
461static int restart_video_queue(struct cx8800_dev *dev,
462 struct cx88_dmaqueue *q)
463{
464 struct cx88_buffer *buf, *prev;
465 struct list_head *item;
466
467 if (!list_empty(&q->active)) {
468 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
469 dprintk(2,"restart_queue [%p/%d]: restart dma\n",
470 buf, buf->vb.i);
471 start_video_dma(dev, q, buf);
472 list_for_each(item,&q->active) {
473 buf = list_entry(item, struct cx88_buffer, vb.queue);
474 buf->count = q->count++;
475 }
476 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
477 return 0;
478 }
479
480 prev = NULL;
481 for (;;) {
482 if (list_empty(&q->queued))
483 return 0;
484 buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
485 if (NULL == prev) {
486 list_del(&buf->vb.queue);
487 list_add_tail(&buf->vb.queue,&q->active);
488 start_video_dma(dev, q, buf);
489 buf->vb.state = STATE_ACTIVE;
490 buf->count = q->count++;
491 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
492 dprintk(2,"[%p/%d] restart_queue - first active\n",
493 buf,buf->vb.i);
494
495 } else if (prev->vb.width == buf->vb.width &&
496 prev->vb.height == buf->vb.height &&
497 prev->fmt == buf->fmt) {
498 list_del(&buf->vb.queue);
499 list_add_tail(&buf->vb.queue,&q->active);
500 buf->vb.state = STATE_ACTIVE;
501 buf->count = q->count++;
502 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
503 dprintk(2,"[%p/%d] restart_queue - move to active\n",
504 buf,buf->vb.i);
505 } else {
506 return 0;
507 }
508 prev = buf;
509 }
510}
511
512/* ------------------------------------------------------------------ */
513
514static int
515buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
516{
517 struct cx8800_fh *fh = q->priv_data;
518
519 *size = fh->fmt->depth*fh->width*fh->height >> 3;
520 if (0 == *count)
521 *count = 32;
522 while (*size * *count > vid_limit * 1024 * 1024)
523 (*count)--;
524 return 0;
525}
526
527static int
528buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
529 enum v4l2_field field)
530{
531 struct cx8800_fh *fh = q->priv_data;
532 struct cx8800_dev *dev = fh->dev;
533 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
534 int rc, init_buffer = 0;
535
536 BUG_ON(NULL == fh->fmt);
537 if (fh->width < 48 || fh->width > norm_maxw(dev->core->tvnorm) ||
538 fh->height < 32 || fh->height > norm_maxh(dev->core->tvnorm))
539 return -EINVAL;
540 buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
541 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
542 return -EINVAL;
543
544 if (buf->fmt != fh->fmt ||
545 buf->vb.width != fh->width ||
546 buf->vb.height != fh->height ||
547 buf->vb.field != field) {
548 buf->fmt = fh->fmt;
549 buf->vb.width = fh->width;
550 buf->vb.height = fh->height;
551 buf->vb.field = field;
552 init_buffer = 1;
553 }
554
555 if (STATE_NEEDS_INIT == buf->vb.state) {
556 init_buffer = 1;
557 if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL)))
558 goto fail;
559 }
560
561 if (init_buffer) {
562 buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
563 switch (buf->vb.field) {
564 case V4L2_FIELD_TOP:
565 cx88_risc_buffer(dev->pci, &buf->risc,
566 buf->vb.dma.sglist, 0, UNSET,
567 buf->bpl, 0, buf->vb.height);
568 break;
569 case V4L2_FIELD_BOTTOM:
570 cx88_risc_buffer(dev->pci, &buf->risc,
571 buf->vb.dma.sglist, UNSET, 0,
572 buf->bpl, 0, buf->vb.height);
573 break;
574 case V4L2_FIELD_INTERLACED:
575 cx88_risc_buffer(dev->pci, &buf->risc,
576 buf->vb.dma.sglist, 0, buf->bpl,
577 buf->bpl, buf->bpl,
578 buf->vb.height >> 1);
579 break;
580 case V4L2_FIELD_SEQ_TB:
581 cx88_risc_buffer(dev->pci, &buf->risc,
582 buf->vb.dma.sglist,
583 0, buf->bpl * (buf->vb.height >> 1),
584 buf->bpl, 0,
585 buf->vb.height >> 1);
586 break;
587 case V4L2_FIELD_SEQ_BT:
588 cx88_risc_buffer(dev->pci, &buf->risc,
589 buf->vb.dma.sglist,
590 buf->bpl * (buf->vb.height >> 1), 0,
591 buf->bpl, 0,
592 buf->vb.height >> 1);
593 break;
594 default:
595 BUG();
596 }
597 }
598 dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
599 buf, buf->vb.i,
600 fh->width, fh->height, fh->fmt->depth, fh->fmt->name,
601 (unsigned long)buf->risc.dma);
602
603 buf->vb.state = STATE_PREPARED;
604 return 0;
605
606 fail:
607 cx88_free_buffer(dev->pci,buf);
608 return rc;
609}
610
611static void
612buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
613{
614 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
615 struct cx88_buffer *prev;
616 struct cx8800_fh *fh = vq->priv_data;
617 struct cx8800_dev *dev = fh->dev;
618 struct cx88_dmaqueue *q = &dev->vidq;
619
620 /* add jump to stopper */
621 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
622 buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
623
624 if (!list_empty(&q->queued)) {
625 list_add_tail(&buf->vb.queue,&q->queued);
626 buf->vb.state = STATE_QUEUED;
627 dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
628 buf, buf->vb.i);
629
630 } else if (list_empty(&q->active)) {
631 list_add_tail(&buf->vb.queue,&q->active);
632 start_video_dma(dev, q, buf);
633 buf->vb.state = STATE_ACTIVE;
634 buf->count = q->count++;
635 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
636 dprintk(2,"[%p/%d] buffer_queue - first active\n",
637 buf, buf->vb.i);
638
639 } else {
640 prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
641 if (prev->vb.width == buf->vb.width &&
642 prev->vb.height == buf->vb.height &&
643 prev->fmt == buf->fmt) {
644 list_add_tail(&buf->vb.queue,&q->active);
645 buf->vb.state = STATE_ACTIVE;
646 buf->count = q->count++;
647 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
648 dprintk(2,"[%p/%d] buffer_queue - append to active\n",
649 buf, buf->vb.i);
650
651 } else {
652 list_add_tail(&buf->vb.queue,&q->queued);
653 buf->vb.state = STATE_QUEUED;
654 dprintk(2,"[%p/%d] buffer_queue - first queued\n",
655 buf, buf->vb.i);
656 }
657 }
658}
659
660static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
661{
662 struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
663 struct cx8800_fh *fh = q->priv_data;
664
665 cx88_free_buffer(fh->dev->pci,buf);
666}
667
668struct videobuf_queue_ops cx8800_video_qops = {
669 .buf_setup = buffer_setup,
670 .buf_prepare = buffer_prepare,
671 .buf_queue = buffer_queue,
672 .buf_release = buffer_release,
673};
674
675/* ------------------------------------------------------------------ */
676
677#if 0 /* overlay support not finished yet */
678static u32* ov_risc_field(struct cx8800_dev *dev, struct cx8800_fh *fh,
679 u32 *rp, struct btcx_skiplist *skips,
680 u32 sync_line, int skip_even, int skip_odd)
681{
682 int line,maxy,start,end,skip,nskips;
683 u32 ri,ra;
684 u32 addr;
685
686 /* sync instruction */
687 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
688
689 addr = (unsigned long)dev->fbuf.base;
690 addr += dev->fbuf.fmt.bytesperline * fh->win.w.top;
691 addr += (fh->fmt->depth >> 3) * fh->win.w.left;
692
693 /* scan lines */
694 for (maxy = -1, line = 0; line < fh->win.w.height;
695 line++, addr += dev->fbuf.fmt.bytesperline) {
696 if ((line%2) == 0 && skip_even)
697 continue;
698 if ((line%2) == 1 && skip_odd)
699 continue;
700
701 /* calculate clipping */
702 if (line > maxy)
703 btcx_calc_skips(line, fh->win.w.width, &maxy,
704 skips, &nskips, fh->clips, fh->nclips);
705
706 /* write out risc code */
707 for (start = 0, skip = 0; start < fh->win.w.width; start = end) {
708 if (skip >= nskips) {
709 ri = RISC_WRITE;
710 end = fh->win.w.width;
711 } else if (start < skips[skip].start) {
712 ri = RISC_WRITE;
713 end = skips[skip].start;
714 } else {
715 ri = RISC_SKIP;
716 end = skips[skip].end;
717 skip++;
718 }
719 if (RISC_WRITE == ri)
720 ra = addr + (fh->fmt->depth>>3)*start;
721 else
722 ra = 0;
723
724 if (0 == start)
725 ri |= RISC_SOL;
726 if (fh->win.w.width == end)
727 ri |= RISC_EOL;
728 ri |= (fh->fmt->depth>>3) * (end-start);
729
730 *(rp++)=cpu_to_le32(ri);
731 if (0 != ra)
732 *(rp++)=cpu_to_le32(ra);
733 }
734 }
735 kfree(skips);
736 return rp;
737}
738
739static int ov_risc_frame(struct cx8800_dev *dev, struct cx8800_fh *fh,
740 struct cx88_buffer *buf)
741{
742 struct btcx_skiplist *skips;
743 u32 instructions,fields;
744 u32 *rp;
745 int rc;
746
747 /* skip list for window clipping */
748 if (NULL == (skips = kmalloc(sizeof(*skips) * fh->nclips,GFP_KERNEL)))
749 return -ENOMEM;
750
751 fields = 0;
752 if (V4L2_FIELD_HAS_TOP(fh->win.field))
753 fields++;
754 if (V4L2_FIELD_HAS_BOTTOM(fh->win.field))
755 fields++;
756
757 /* estimate risc mem: worst case is (clip+1) * lines instructions
758 + syncs + jump (all 2 dwords) */
759 instructions = (fh->nclips+1) * fh->win.w.height;
760 instructions += 3 + 4;
761 if ((rc = btcx_riscmem_alloc(dev->pci,&buf->risc,instructions*8)) < 0) {
762 kfree(skips);
763 return rc;
764 }
765
766 /* write risc instructions */
767 rp = buf->risc.cpu;
768 switch (fh->win.field) {
769 case V4L2_FIELD_TOP:
770 rp = ov_risc_field(dev, fh, rp, skips, 0, 0, 0);
771 break;
772 case V4L2_FIELD_BOTTOM:
773 rp = ov_risc_field(dev, fh, rp, skips, 0x200, 0, 0);
774 break;
775 case V4L2_FIELD_INTERLACED:
776 rp = ov_risc_field(dev, fh, rp, skips, 0, 0, 1);
777 rp = ov_risc_field(dev, fh, rp, skips, 0x200, 1, 0);
778 break;
779 default:
780 BUG();
781 }
782
783 /* save pointer to jmp instruction address */
784 buf->risc.jmp = rp;
785 kfree(skips);
786 return 0;
787}
788
789static int verify_window(struct cx8800_dev *dev, struct v4l2_window *win)
790{
791 enum v4l2_field field;
792 int maxw, maxh;
793
794 if (NULL == dev->fbuf.base)
795 return -EINVAL;
796 if (win->w.width < 48 || win->w.height < 32)
797 return -EINVAL;
798 if (win->clipcount > 2048)
799 return -EINVAL;
800
801 field = win->field;
802 maxw = norm_maxw(core->tvnorm);
803 maxh = norm_maxh(core->tvnorm);
804
805 if (V4L2_FIELD_ANY == field) {
806 field = (win->w.height > maxh/2)
807 ? V4L2_FIELD_INTERLACED
808 : V4L2_FIELD_TOP;
809 }
810 switch (field) {
811 case V4L2_FIELD_TOP:
812 case V4L2_FIELD_BOTTOM:
813 maxh = maxh / 2;
814 break;
815 case V4L2_FIELD_INTERLACED:
816 break;
817 default:
818 return -EINVAL;
819 }
820
821 win->field = field;
822 if (win->w.width > maxw)
823 win->w.width = maxw;
824 if (win->w.height > maxh)
825 win->w.height = maxh;
826 return 0;
827}
828
829static int setup_window(struct cx8800_dev *dev, struct cx8800_fh *fh,
830 struct v4l2_window *win)
831{
832 struct v4l2_clip *clips = NULL;
833 int n,size,retval = 0;
834
835 if (NULL == fh->fmt)
836 return -EINVAL;
837 retval = verify_window(dev,win);
838 if (0 != retval)
839 return retval;
840
841 /* copy clips -- luckily v4l1 + v4l2 are binary
842 compatible here ...*/
843 n = win->clipcount;
844 size = sizeof(*clips)*(n+4);
845 clips = kmalloc(size,GFP_KERNEL);
846 if (NULL == clips)
847 return -ENOMEM;
848 if (n > 0) {
849 if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
850 kfree(clips);
851 return -EFAULT;
852 }
853 }
854
855 /* clip against screen */
856 if (NULL != dev->fbuf.base)
857 n = btcx_screen_clips(dev->fbuf.fmt.width, dev->fbuf.fmt.height,
858 &win->w, clips, n);
859 btcx_sort_clips(clips,n);
860
861 /* 4-byte alignments */
862 switch (fh->fmt->depth) {
863 case 8:
864 case 24:
865 btcx_align(&win->w, clips, n, 3);
866 break;
867 case 16:
868 btcx_align(&win->w, clips, n, 1);
869 break;
870 case 32:
871 /* no alignment fixups needed */
872 break;
873 default:
874 BUG();
875 }
876
877 down(&fh->vidq.lock);
878 if (fh->clips)
879 kfree(fh->clips);
880 fh->clips = clips;
881 fh->nclips = n;
882 fh->win = *win;
883#if 0
884 fh->ov.setup_ok = 1;
885#endif
886
887 /* update overlay if needed */
888 retval = 0;
889#if 0
890 if (check_btres(fh, RESOURCE_OVERLAY)) {
891 struct bttv_buffer *new;
892
893 new = videobuf_alloc(sizeof(*new));
894 bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
895 retval = bttv_switch_overlay(btv,fh,new);
896 }
897#endif
898 up(&fh->vidq.lock);
899 return retval;
900}
901#endif
902
903/* ------------------------------------------------------------------ */
904
905static struct videobuf_queue* get_queue(struct cx8800_fh *fh)
906{
907 switch (fh->type) {
908 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
909 return &fh->vidq;
910 case V4L2_BUF_TYPE_VBI_CAPTURE:
911 return &fh->vbiq;
912 default:
913 BUG();
914 return NULL;
915 }
916}
917
918static int get_ressource(struct cx8800_fh *fh)
919{
920 switch (fh->type) {
921 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
922 return RESOURCE_VIDEO;
923 case V4L2_BUF_TYPE_VBI_CAPTURE:
924 return RESOURCE_VBI;
925 default:
926 BUG();
927 return 0;
928 }
929}
930
931static int video_open(struct inode *inode, struct file *file)
932{
933 int minor = iminor(inode);
934 struct cx8800_dev *h,*dev = NULL;
935 struct cx8800_fh *fh;
936 struct list_head *list;
937 enum v4l2_buf_type type = 0;
938 int radio = 0;
939
940 list_for_each(list,&cx8800_devlist) {
941 h = list_entry(list, struct cx8800_dev, devlist);
942 if (h->video_dev->minor == minor) {
943 dev = h;
944 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
945 }
946 if (h->vbi_dev->minor == minor) {
947 dev = h;
948 type = V4L2_BUF_TYPE_VBI_CAPTURE;
949 }
950 if (h->radio_dev &&
951 h->radio_dev->minor == minor) {
952 radio = 1;
953 dev = h;
954 }
955 }
956 if (NULL == dev)
957 return -ENODEV;
958
959 dprintk(1,"open minor=%d radio=%d type=%s\n",
960 minor,radio,v4l2_type_names[type]);
961
962 /* allocate + initialize per filehandle data */
963 fh = kmalloc(sizeof(*fh),GFP_KERNEL);
964 if (NULL == fh)
965 return -ENOMEM;
966 memset(fh,0,sizeof(*fh));
967 file->private_data = fh;
968 fh->dev = dev;
969 fh->radio = radio;
970 fh->type = type;
971 fh->width = 320;
972 fh->height = 240;
973 fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
974
975 videobuf_queue_init(&fh->vidq, &cx8800_video_qops,
976 dev->pci, &dev->slock,
977 V4L2_BUF_TYPE_VIDEO_CAPTURE,
978 V4L2_FIELD_INTERLACED,
979 sizeof(struct cx88_buffer),
980 fh);
981 videobuf_queue_init(&fh->vbiq, &cx8800_vbi_qops,
982 dev->pci, &dev->slock,
983 V4L2_BUF_TYPE_VBI_CAPTURE,
984 V4L2_FIELD_SEQ_TB,
985 sizeof(struct cx88_buffer),
986 fh);
987
988 if (fh->radio) {
989 struct cx88_core *core = dev->core;
990 int board = core->board;
991 dprintk(1,"video_open: setting radio device\n");
992 cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0);
993 cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1);
994 cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2);
995 cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
996 dev->core->tvaudio = WW_FM;
997 cx88_set_tvaudio(core);
998 cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
999 cx88_call_i2c_clients(dev->core,AUDC_SET_RADIO,NULL);
1000 }
1001
1002 return 0;
1003}
1004
1005static ssize_t
1006video_read(struct file *file, char *data, size_t count, loff_t *ppos)
1007{
1008 struct cx8800_fh *fh = file->private_data;
1009
1010 switch (fh->type) {
1011 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1012 if (res_locked(fh->dev,RESOURCE_VIDEO))
1013 return -EBUSY;
1014 return videobuf_read_one(&fh->vidq, data, count, ppos,
1015 file->f_flags & O_NONBLOCK);
1016 case V4L2_BUF_TYPE_VBI_CAPTURE:
1017 if (!res_get(fh->dev,fh,RESOURCE_VBI))
1018 return -EBUSY;
1019 return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
1020 file->f_flags & O_NONBLOCK);
1021 default:
1022 BUG();
1023 return 0;
1024 }
1025}
1026
1027static unsigned int
1028video_poll(struct file *file, struct poll_table_struct *wait)
1029{
1030 struct cx8800_fh *fh = file->private_data;
1031 struct cx88_buffer *buf;
1032
1033 if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
1034 if (!res_get(fh->dev,fh,RESOURCE_VBI))
1035 return POLLERR;
1036 return videobuf_poll_stream(file, &fh->vbiq, wait);
1037 }
1038
1039 if (res_check(fh,RESOURCE_VIDEO)) {
1040 /* streaming capture */
1041 if (list_empty(&fh->vidq.stream))
1042 return POLLERR;
1043 buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream);
1044 } else {
1045 /* read() capture */
1046 buf = (struct cx88_buffer*)fh->vidq.read_buf;
1047 if (NULL == buf)
1048 return POLLERR;
1049 }
1050 poll_wait(file, &buf->vb.done, wait);
1051 if (buf->vb.state == STATE_DONE ||
1052 buf->vb.state == STATE_ERROR)
1053 return POLLIN|POLLRDNORM;
1054 return 0;
1055}
1056
1057static int video_release(struct inode *inode, struct file *file)
1058{
1059 struct cx8800_fh *fh = file->private_data;
1060 struct cx8800_dev *dev = fh->dev;
1061
1062 /* turn off overlay */
1063 if (res_check(fh, RESOURCE_OVERLAY)) {
1064 /* FIXME */
1065 res_free(dev,fh,RESOURCE_OVERLAY);
1066 }
1067
1068 /* stop video capture */
1069 if (res_check(fh, RESOURCE_VIDEO)) {
1070 videobuf_queue_cancel(&fh->vidq);
1071 res_free(dev,fh,RESOURCE_VIDEO);
1072 }
1073 if (fh->vidq.read_buf) {
1074 buffer_release(&fh->vidq,fh->vidq.read_buf);
1075 kfree(fh->vidq.read_buf);
1076 }
1077
1078 /* stop vbi capture */
1079 if (res_check(fh, RESOURCE_VBI)) {
1080 if (fh->vbiq.streaming)
1081 videobuf_streamoff(&fh->vbiq);
1082 if (fh->vbiq.reading)
1083 videobuf_read_stop(&fh->vbiq);
1084 res_free(dev,fh,RESOURCE_VBI);
1085 }
1086
1087 videobuf_mmap_free(&fh->vidq);
1088 videobuf_mmap_free(&fh->vbiq);
1089 file->private_data = NULL;
1090 kfree(fh);
1091 return 0;
1092}
1093
1094static int
1095video_mmap(struct file *file, struct vm_area_struct * vma)
1096{
1097 struct cx8800_fh *fh = file->private_data;
1098
1099 return videobuf_mmap_mapper(get_queue(fh), vma);
1100}
1101
1102/* ------------------------------------------------------------------ */
1103
1104static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
1105{
1106 struct cx88_core *core = dev->core;
1107 struct cx88_ctrl *c = NULL;
1108 u32 value;
1109 int i;
1110
1111 for (i = 0; i < CX8800_CTLS; i++)
1112 if (cx8800_ctls[i].v.id == ctl->id)
1113 c = &cx8800_ctls[i];
1114 if (NULL == c)
1115 return -EINVAL;
1116
1117 value = c->sreg ? cx_sread(c->sreg) : cx_read(c->reg);
1118 switch (ctl->id) {
1119 case V4L2_CID_AUDIO_BALANCE:
1120 ctl->value = (value & 0x40) ? (value & 0x3f) : (0x40 - (value & 0x3f));
1121 break;
1122 case V4L2_CID_AUDIO_VOLUME:
1123 ctl->value = 0x3f - (value & 0x3f);
1124 break;
1125 default:
1126 ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift;
1127 break;
1128 }
1129 return 0;
1130}
1131
1132static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
1133{
1134 struct cx88_core *core = dev->core;
1135 struct cx88_ctrl *c = NULL;
1136 u32 v_sat_value;
1137 u32 value;
1138 int i;
1139
1140 for (i = 0; i < CX8800_CTLS; i++)
1141 if (cx8800_ctls[i].v.id == ctl->id)
1142 c = &cx8800_ctls[i];
1143 if (NULL == c)
1144 return -EINVAL;
1145
1146 if (ctl->value < c->v.minimum)
1147 return -ERANGE;
1148 if (ctl->value > c->v.maximum)
1149 return -ERANGE;
1150 switch (ctl->id) {
1151 case V4L2_CID_AUDIO_BALANCE:
1152 value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value;
1153 break;
1154 case V4L2_CID_AUDIO_VOLUME:
1155 value = 0x3f - (ctl->value & 0x3f);
1156 break;
1157 case V4L2_CID_SATURATION:
1158 /* special v_sat handling */
1159 v_sat_value = ctl->value - (0x7f - 0x5a);
1160 if (v_sat_value > 0xff)
1161 v_sat_value = 0xff;
1162 if (v_sat_value < 0x00)
1163 v_sat_value = 0x00;
1164 cx_andor(MO_UV_SATURATION, 0xff00, v_sat_value << 8);
1165 /* fall through to default route for u_sat */
1166 default:
1167 value = ((ctl->value - c->off) << c->shift) & c->mask;
1168 break;
1169 }
1170 dprintk(1,"set_control id=0x%X reg=0x%x val=0x%x%s\n",
1171 ctl->id, c->reg, value, c->sreg ? " [shadowed]" : "");
1172 if (c->sreg) {
1173 cx_sandor(c->sreg, c->reg, c->mask, value);
1174 } else {
1175 cx_andor(c->reg, c->mask, value);
1176 }
1177 return 0;
1178}
1179
1180static void init_controls(struct cx8800_dev *dev)
1181{
1182 static struct v4l2_control mute = {
1183 .id = V4L2_CID_AUDIO_MUTE,
1184 .value = 1,
1185 };
1186 static struct v4l2_control volume = {
1187 .id = V4L2_CID_AUDIO_VOLUME,
1188 .value = 0x3f,
1189 };
1190
1191 set_control(dev,&mute);
1192 set_control(dev,&volume);
1193}
1194
1195/* ------------------------------------------------------------------ */
1196
1197static int cx8800_g_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
1198 struct v4l2_format *f)
1199{
1200 switch (f->type) {
1201 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1202 memset(&f->fmt.pix,0,sizeof(f->fmt.pix));
1203 f->fmt.pix.width = fh->width;
1204 f->fmt.pix.height = fh->height;
1205 f->fmt.pix.field = fh->vidq.field;
1206 f->fmt.pix.pixelformat = fh->fmt->fourcc;
1207 f->fmt.pix.bytesperline =
1208 (f->fmt.pix.width * fh->fmt->depth) >> 3;
1209 f->fmt.pix.sizeimage =
1210 f->fmt.pix.height * f->fmt.pix.bytesperline;
1211 return 0;
1212 case V4L2_BUF_TYPE_VBI_CAPTURE:
1213 cx8800_vbi_fmt(dev, f);
1214 return 0;
1215 default:
1216 return -EINVAL;
1217 }
1218}
1219
1220static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
1221 struct v4l2_format *f)
1222{
1223 switch (f->type) {
1224 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1225 {
1226 struct cx8800_fmt *fmt;
1227 enum v4l2_field field;
1228 unsigned int maxw, maxh;
1229
1230 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1231 if (NULL == fmt)
1232 return -EINVAL;
1233
1234 field = f->fmt.pix.field;
1235 maxw = norm_maxw(dev->core->tvnorm);
1236 maxh = norm_maxh(dev->core->tvnorm);
1237
1238 if (V4L2_FIELD_ANY == field) {
1239 field = (f->fmt.pix.height > maxh/2)
1240 ? V4L2_FIELD_INTERLACED
1241 : V4L2_FIELD_BOTTOM;
1242 }
1243
1244 switch (field) {
1245 case V4L2_FIELD_TOP:
1246 case V4L2_FIELD_BOTTOM:
1247 maxh = maxh / 2;
1248 break;
1249 case V4L2_FIELD_INTERLACED:
1250 break;
1251 default:
1252 return -EINVAL;
1253 }
1254
1255 f->fmt.pix.field = field;
1256 if (f->fmt.pix.height < 32)
1257 f->fmt.pix.height = 32;
1258 if (f->fmt.pix.height > maxh)
1259 f->fmt.pix.height = maxh;
1260 if (f->fmt.pix.width < 48)
1261 f->fmt.pix.width = 48;
1262 if (f->fmt.pix.width > maxw)
1263 f->fmt.pix.width = maxw;
1264 f->fmt.pix.width &= ~0x03;
1265 f->fmt.pix.bytesperline =
1266 (f->fmt.pix.width * fmt->depth) >> 3;
1267 f->fmt.pix.sizeimage =
1268 f->fmt.pix.height * f->fmt.pix.bytesperline;
1269
1270 return 0;
1271 }
1272 case V4L2_BUF_TYPE_VBI_CAPTURE:
1273 cx8800_vbi_fmt(dev, f);
1274 return 0;
1275 default:
1276 return -EINVAL;
1277 }
1278}
1279
1280static int cx8800_s_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
1281 struct v4l2_format *f)
1282{
1283 int err;
1284
1285 switch (f->type) {
1286 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1287 err = cx8800_try_fmt(dev,fh,f);
1288 if (0 != err)
1289 return err;
1290
1291 fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
1292 fh->width = f->fmt.pix.width;
1293 fh->height = f->fmt.pix.height;
1294 fh->vidq.field = f->fmt.pix.field;
1295 return 0;
1296 case V4L2_BUF_TYPE_VBI_CAPTURE:
1297 cx8800_vbi_fmt(dev, f);
1298 return 0;
1299 default:
1300 return -EINVAL;
1301 }
1302}
1303
1304/*
1305 * This function is _not_ called directly, but from
1306 * video_generic_ioctl (and maybe others). userspace
1307 * copying is done already, arg is a kernel pointer.
1308 */
1309static int video_do_ioctl(struct inode *inode, struct file *file,
1310 unsigned int cmd, void *arg)
1311{
1312 struct cx8800_fh *fh = file->private_data;
1313 struct cx8800_dev *dev = fh->dev;
1314 struct cx88_core *core = dev->core;
1315#if 0
1316 unsigned long flags;
1317#endif
1318 int err;
1319
1320 if (video_debug > 1)
1321 cx88_print_ioctl(core->name,cmd);
1322 switch (cmd) {
1323 case VIDIOC_QUERYCAP:
1324 {
1325 struct v4l2_capability *cap = arg;
1326
1327 memset(cap,0,sizeof(*cap));
1328 strcpy(cap->driver, "cx8800");
1329 strlcpy(cap->card, cx88_boards[core->board].name,
1330 sizeof(cap->card));
1331 sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
1332 cap->version = CX88_VERSION_CODE;
1333 cap->capabilities =
1334 V4L2_CAP_VIDEO_CAPTURE |
1335 V4L2_CAP_READWRITE |
1336 V4L2_CAP_STREAMING |
1337 V4L2_CAP_VBI_CAPTURE |
1338#if 0
1339 V4L2_CAP_VIDEO_OVERLAY |
1340#endif
1341 0;
1342 if (UNSET != core->tuner_type)
1343 cap->capabilities |= V4L2_CAP_TUNER;
1344 return 0;
1345 }
1346
1347 /* ---------- tv norms ---------- */
1348 case VIDIOC_ENUMSTD:
1349 {
1350 struct v4l2_standard *e = arg;
1351 unsigned int i;
1352
1353 i = e->index;
1354 if (i >= ARRAY_SIZE(tvnorms))
1355 return -EINVAL;
1356 err = v4l2_video_std_construct(e, tvnorms[e->index].id,
1357 tvnorms[e->index].name);
1358 e->index = i;
1359 if (err < 0)
1360 return err;
1361 return 0;
1362 }
1363 case VIDIOC_G_STD:
1364 {
1365 v4l2_std_id *id = arg;
1366
1367 *id = core->tvnorm->id;
1368 return 0;
1369 }
1370 case VIDIOC_S_STD:
1371 {
1372 v4l2_std_id *id = arg;
1373 unsigned int i;
1374
1375 for(i = 0; i < ARRAY_SIZE(tvnorms); i++)
1376 if (*id & tvnorms[i].id)
1377 break;
1378 if (i == ARRAY_SIZE(tvnorms))
1379 return -EINVAL;
1380
1381 down(&dev->lock);
1382 cx88_set_tvnorm(dev->core,&tvnorms[i]);
1383 up(&dev->lock);
1384 return 0;
1385 }
1386
1387 /* ------ input switching ---------- */
1388 case VIDIOC_ENUMINPUT:
1389 {
1390 static const char *iname[] = {
1391 [ CX88_VMUX_COMPOSITE1 ] = "Composite1",
1392 [ CX88_VMUX_COMPOSITE2 ] = "Composite2",
1393 [ CX88_VMUX_COMPOSITE3 ] = "Composite3",
1394 [ CX88_VMUX_COMPOSITE4 ] = "Composite4",
1395 [ CX88_VMUX_SVIDEO ] = "S-Video",
1396 [ CX88_VMUX_TELEVISION ] = "Television",
1397 [ CX88_VMUX_CABLE ] = "Cable TV",
1398 [ CX88_VMUX_DVB ] = "DVB",
1399 [ CX88_VMUX_DEBUG ] = "for debug only",
1400 };
1401 struct v4l2_input *i = arg;
1402 unsigned int n;
1403
1404 n = i->index;
1405 if (n >= 4)
1406 return -EINVAL;
1407 if (0 == INPUT(n)->type)
1408 return -EINVAL;
1409 memset(i,0,sizeof(*i));
1410 i->index = n;
1411 i->type = V4L2_INPUT_TYPE_CAMERA;
1412 strcpy(i->name,iname[INPUT(n)->type]);
1413 if ((CX88_VMUX_TELEVISION == INPUT(n)->type) ||
1414 (CX88_VMUX_CABLE == INPUT(n)->type))
1415 i->type = V4L2_INPUT_TYPE_TUNER;
1416 for (n = 0; n < ARRAY_SIZE(tvnorms); n++)
1417 i->std |= tvnorms[n].id;
1418 return 0;
1419 }
1420 case VIDIOC_G_INPUT:
1421 {
1422 unsigned int *i = arg;
1423
1424 *i = dev->core->input;
1425 return 0;
1426 }
1427 case VIDIOC_S_INPUT:
1428 {
1429 unsigned int *i = arg;
1430
1431 if (*i >= 4)
1432 return -EINVAL;
1433 down(&dev->lock);
1434 cx88_newstation(core);
1435 video_mux(dev,*i);
1436 up(&dev->lock);
1437 return 0;
1438 }
1439
1440
1441#if 0
1442 /* needs review */
1443 case VIDIOC_G_AUDIO:
1444 {
1445 struct v4l2_audio *a = arg;
1446 unsigned int n = a->index;
1447
1448 memset(a,0,sizeof(*a));
1449 a->index = n;
1450 switch (n) {
1451 case 0:
1452 if ((CX88_VMUX_TELEVISION == INPUT(n)->type)
1453 || (CX88_VMUX_CABLE == INPUT(n)->type)) {
1454 strcpy(a->name,"Television");
1455 // FIXME figure out if stereo received and set V4L2_AUDCAP_STEREO.
1456 return 0;
1457 }
1458 break;
1459 case 1:
1460 if (CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD == core->board) {
1461 strcpy(a->name,"Line In");
1462 a->capability = V4L2_AUDCAP_STEREO;
1463 return 0;
1464 }
1465 break;
1466 }
1467 // Audio input not available.
1468 return -EINVAL;
1469 }
1470#endif
1471
1472 /* --- capture ioctls ---------------------------------------- */
1473 case VIDIOC_ENUM_FMT:
1474 {
1475 struct v4l2_fmtdesc *f = arg;
1476 enum v4l2_buf_type type;
1477 unsigned int index;
1478
1479 index = f->index;
1480 type = f->type;
1481 switch (type) {
1482 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1483 if (index >= ARRAY_SIZE(formats))
1484 return -EINVAL;
1485 memset(f,0,sizeof(*f));
1486 f->index = index;
1487 f->type = type;
1488 strlcpy(f->description,formats[index].name,sizeof(f->description));
1489 f->pixelformat = formats[index].fourcc;
1490 break;
1491 default:
1492 return -EINVAL;
1493 }
1494 return 0;
1495 }
1496 case VIDIOC_G_FMT:
1497 {
1498 struct v4l2_format *f = arg;
1499 return cx8800_g_fmt(dev,fh,f);
1500 }
1501 case VIDIOC_S_FMT:
1502 {
1503 struct v4l2_format *f = arg;
1504 return cx8800_s_fmt(dev,fh,f);
1505 }
1506 case VIDIOC_TRY_FMT:
1507 {
1508 struct v4l2_format *f = arg;
1509 return cx8800_try_fmt(dev,fh,f);
1510 }
1511
1512 /* --- controls ---------------------------------------------- */
1513 case VIDIOC_QUERYCTRL:
1514 {
1515 struct v4l2_queryctrl *c = arg;
1516 int i;
1517
1518 if (c->id < V4L2_CID_BASE ||
1519 c->id >= V4L2_CID_LASTP1)
1520 return -EINVAL;
1521 for (i = 0; i < CX8800_CTLS; i++)
1522 if (cx8800_ctls[i].v.id == c->id)
1523 break;
1524 if (i == CX8800_CTLS) {
1525 *c = no_ctl;
1526 return 0;
1527 }
1528 *c = cx8800_ctls[i].v;
1529 return 0;
1530 }
1531 case VIDIOC_G_CTRL:
1532 return get_control(dev,arg);
1533 case VIDIOC_S_CTRL:
1534 return set_control(dev,arg);
1535
1536 /* --- tuner ioctls ------------------------------------------ */
1537 case VIDIOC_G_TUNER:
1538 {
1539 struct v4l2_tuner *t = arg;
1540 u32 reg;
1541
1542 if (UNSET == core->tuner_type)
1543 return -EINVAL;
1544 if (0 != t->index)
1545 return -EINVAL;
1546
1547 memset(t,0,sizeof(*t));
1548 strcpy(t->name, "Television");
1549 t->type = V4L2_TUNER_ANALOG_TV;
1550 t->capability = V4L2_TUNER_CAP_NORM;
1551 t->rangehigh = 0xffffffffUL;
1552
1553 cx88_get_stereo(core ,t);
1554 reg = cx_read(MO_DEVICE_STATUS);
1555 t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
1556 return 0;
1557 }
1558 case VIDIOC_S_TUNER:
1559 {
1560 struct v4l2_tuner *t = arg;
1561
1562 if (UNSET == core->tuner_type)
1563 return -EINVAL;
1564 if (0 != t->index)
1565 return -EINVAL;
1566 cx88_set_stereo(core, t->audmode, 1);
1567 return 0;
1568 }
1569 case VIDIOC_G_FREQUENCY:
1570 {
1571 struct v4l2_frequency *f = arg;
1572
1573 if (UNSET == core->tuner_type)
1574 return -EINVAL;
1575 if (f->tuner != 0)
1576 return -EINVAL;
1577 memset(f,0,sizeof(*f));
1578 f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
1579 f->frequency = dev->freq;
1580 return 0;
1581 }
1582 case VIDIOC_S_FREQUENCY:
1583 {
1584 struct v4l2_frequency *f = arg;
1585
1586 if (UNSET == core->tuner_type)
1587 return -EINVAL;
1588 if (f->tuner != 0)
1589 return -EINVAL;
1590 if (0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)
1591 return -EINVAL;
1592 if (1 == fh->radio && f->type != V4L2_TUNER_RADIO)
1593 return -EINVAL;
1594 down(&dev->lock);
1595 dev->freq = f->frequency;
1596 cx88_newstation(core);
1597#ifdef V4L2_I2C_CLIENTS
1598 cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f);
1599#else
1600 cx88_call_i2c_clients(dev->core,VIDIOCSFREQ,&dev->freq);
1601#endif
1602 up(&dev->lock);
1603 return 0;
1604 }
1605
1606 /* --- streaming capture ------------------------------------- */
1607 case VIDIOCGMBUF:
1608 {
1609 struct video_mbuf *mbuf = arg;
1610 struct videobuf_queue *q;
1611 struct v4l2_requestbuffers req;
1612 unsigned int i;
1613
1614 q = get_queue(fh);
1615 memset(&req,0,sizeof(req));
1616 req.type = q->type;
1617 req.count = 8;
1618 req.memory = V4L2_MEMORY_MMAP;
1619 err = videobuf_reqbufs(q,&req);
1620 if (err < 0)
1621 return err;
1622 memset(mbuf,0,sizeof(*mbuf));
1623 mbuf->frames = req.count;
1624 mbuf->size = 0;
1625 for (i = 0; i < mbuf->frames; i++) {
1626 mbuf->offsets[i] = q->bufs[i]->boff;
1627 mbuf->size += q->bufs[i]->bsize;
1628 }
1629 return 0;
1630 }
1631 case VIDIOC_REQBUFS:
1632 return videobuf_reqbufs(get_queue(fh), arg);
1633
1634 case VIDIOC_QUERYBUF:
1635 return videobuf_querybuf(get_queue(fh), arg);
1636
1637 case VIDIOC_QBUF:
1638 return videobuf_qbuf(get_queue(fh), arg);
1639
1640 case VIDIOC_DQBUF:
1641 return videobuf_dqbuf(get_queue(fh), arg,
1642 file->f_flags & O_NONBLOCK);
1643
1644 case VIDIOC_STREAMON:
1645 {
1646 int res = get_ressource(fh);
1647
1648 if (!res_get(dev,fh,res))
1649 return -EBUSY;
1650 return videobuf_streamon(get_queue(fh));
1651 }
1652 case VIDIOC_STREAMOFF:
1653 {
1654 int res = get_ressource(fh);
1655
1656 err = videobuf_streamoff(get_queue(fh));
1657 if (err < 0)
1658 return err;
1659 res_free(dev,fh,res);
1660 return 0;
1661 }
1662
1663 default:
1664 return v4l_compat_translate_ioctl(inode,file,cmd,arg,
1665 video_do_ioctl);
1666 }
1667 return 0;
1668}
1669
1670static int video_ioctl(struct inode *inode, struct file *file,
1671 unsigned int cmd, unsigned long arg)
1672{
1673 return video_usercopy(inode, file, cmd, arg, video_do_ioctl);
1674}
1675
1676/* ----------------------------------------------------------- */
1677
1678static int radio_do_ioctl(struct inode *inode, struct file *file,
1679 unsigned int cmd, void *arg)
1680{
1681 struct cx8800_fh *fh = file->private_data;
1682 struct cx8800_dev *dev = fh->dev;
1683 struct cx88_core *core = dev->core;
1684
1685 if (video_debug > 1)
1686 cx88_print_ioctl(core->name,cmd);
1687
1688 switch (cmd) {
1689 case VIDIOC_QUERYCAP:
1690 {
1691 struct v4l2_capability *cap = arg;
1692
1693 memset(cap,0,sizeof(*cap));
1694 strcpy(cap->driver, "cx8800");
1695 strlcpy(cap->card, cx88_boards[core->board].name,
1696 sizeof(cap->card));
1697 sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
1698 cap->version = CX88_VERSION_CODE;
1699 cap->capabilities = V4L2_CAP_TUNER;
1700 return 0;
1701 }
1702 case VIDIOC_G_TUNER:
1703 {
1704 struct v4l2_tuner *t = arg;
1705
1706 if (t->index > 0)
1707 return -EINVAL;
1708
1709 memset(t,0,sizeof(*t));
1710 strcpy(t->name, "Radio");
1711 t->rangelow = (int)(65*16);
1712 t->rangehigh = (int)(108*16);
1713
1714#ifdef V4L2_I2C_CLIENTS
1715 cx88_call_i2c_clients(dev->core,VIDIOC_G_TUNER,t);
1716#else
1717 {
1718 struct video_tuner vt;
1719 memset(&vt,0,sizeof(vt));
1720 cx88_call_i2c_clients(dev,VIDIOCGTUNER,&vt);
1721 t->signal = vt.signal;
1722 }
1723#endif
1724 return 0;
1725 }
1726 case VIDIOC_ENUMINPUT:
1727 {
1728 struct v4l2_input *i = arg;
1729
1730 if (i->index != 0)
1731 return -EINVAL;
1732 strcpy(i->name,"Radio");
1733 i->type = V4L2_INPUT_TYPE_TUNER;
1734 return 0;
1735 }
1736 case VIDIOC_G_INPUT:
1737 {
1738 int *i = arg;
1739 *i = 0;
1740 return 0;
1741 }
1742 case VIDIOC_G_AUDIO:
1743 {
1744 struct v4l2_audio *a = arg;
1745
1746 memset(a,0,sizeof(*a));
1747 strcpy(a->name,"Radio");
1748 return 0;
1749 }
1750 case VIDIOC_G_STD:
1751 {
1752 v4l2_std_id *id = arg;
1753 *id = 0;
1754 return 0;
1755 }
1756 case VIDIOC_S_AUDIO:
1757 case VIDIOC_S_TUNER:
1758 case VIDIOC_S_INPUT:
1759 case VIDIOC_S_STD:
1760 return 0;
1761
1762 case VIDIOC_QUERYCTRL:
1763 {
1764 struct v4l2_queryctrl *c = arg;
1765 int i;
1766
1767 if (c->id < V4L2_CID_BASE ||
1768 c->id >= V4L2_CID_LASTP1)
1769 return -EINVAL;
1770 if (c->id == V4L2_CID_AUDIO_MUTE) {
1771 for (i = 0; i < CX8800_CTLS; i++)
1772 if (cx8800_ctls[i].v.id == c->id)
1773 break;
1774 *c = cx8800_ctls[i].v;
1775 } else
1776 *c = no_ctl;
1777 return 0;
1778 }
1779
1780
1781 case VIDIOC_G_CTRL:
1782 case VIDIOC_S_CTRL:
1783 case VIDIOC_G_FREQUENCY:
1784 case VIDIOC_S_FREQUENCY:
1785 return video_do_ioctl(inode,file,cmd,arg);
1786
1787 default:
1788 return v4l_compat_translate_ioctl(inode,file,cmd,arg,
1789 radio_do_ioctl);
1790 }
1791 return 0;
1792};
1793
1794static int radio_ioctl(struct inode *inode, struct file *file,
1795 unsigned int cmd, unsigned long arg)
1796{
1797 return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
1798};
1799
1800/* ----------------------------------------------------------- */
1801
1802static void cx8800_vid_timeout(unsigned long data)
1803{
1804 struct cx8800_dev *dev = (struct cx8800_dev*)data;
1805 struct cx88_core *core = dev->core;
1806 struct cx88_dmaqueue *q = &dev->vidq;
1807 struct cx88_buffer *buf;
1808 unsigned long flags;
1809
1810 cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH21]);
1811
1812 cx_clear(MO_VID_DMACNTRL, 0x11);
1813 cx_clear(VID_CAPTURE_CONTROL, 0x06);
1814
1815 spin_lock_irqsave(&dev->slock,flags);
1816 while (!list_empty(&q->active)) {
1817 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
1818 list_del(&buf->vb.queue);
1819 buf->vb.state = STATE_ERROR;
1820 wake_up(&buf->vb.done);
1821 printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name,
1822 buf, buf->vb.i, (unsigned long)buf->risc.dma);
1823 }
1824 restart_video_queue(dev,q);
1825 spin_unlock_irqrestore(&dev->slock,flags);
1826}
1827
1828static void cx8800_vid_irq(struct cx8800_dev *dev)
1829{
1830 struct cx88_core *core = dev->core;
1831 u32 status, mask, count;
1832
1833 status = cx_read(MO_VID_INTSTAT);
1834 mask = cx_read(MO_VID_INTMSK);
1835 if (0 == (status & mask))
1836 return;
1837 cx_write(MO_VID_INTSTAT, status);
1838 if (irq_debug || (status & mask & ~0xff))
1839 cx88_print_irqbits(core->name, "irq vid",
1840 cx88_vid_irqs, status, mask);
1841
1842 /* risc op code error */
1843 if (status & (1 << 16)) {
1844 printk(KERN_WARNING "%s/0: video risc op code error\n",core->name);
1845 cx_clear(MO_VID_DMACNTRL, 0x11);
1846 cx_clear(VID_CAPTURE_CONTROL, 0x06);
1847 cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH21]);
1848 }
1849
1850 /* risc1 y */
1851 if (status & 0x01) {
1852 spin_lock(&dev->slock);
1853 count = cx_read(MO_VIDY_GPCNT);
1854 cx88_wakeup(dev->core, &dev->vidq, count);
1855 spin_unlock(&dev->slock);
1856 }
1857
1858 /* risc1 vbi */
1859 if (status & 0x08) {
1860 spin_lock(&dev->slock);
1861 count = cx_read(MO_VBI_GPCNT);
1862 cx88_wakeup(dev->core, &dev->vbiq, count);
1863 spin_unlock(&dev->slock);
1864 }
1865
1866 /* risc2 y */
1867 if (status & 0x10) {
1868 dprintk(2,"stopper video\n");
1869 spin_lock(&dev->slock);
1870 restart_video_queue(dev,&dev->vidq);
1871 spin_unlock(&dev->slock);
1872 }
1873
1874 /* risc2 vbi */
1875 if (status & 0x80) {
1876 dprintk(2,"stopper vbi\n");
1877 spin_lock(&dev->slock);
1878 cx8800_restart_vbi_queue(dev,&dev->vbiq);
1879 spin_unlock(&dev->slock);
1880 }
1881}
1882
1883static irqreturn_t cx8800_irq(int irq, void *dev_id, struct pt_regs *regs)
1884{
1885 struct cx8800_dev *dev = dev_id;
1886 struct cx88_core *core = dev->core;
1887 u32 status;
1888 int loop, handled = 0;
1889
1890 for (loop = 0; loop < 10; loop++) {
1891 status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x01);
1892 if (0 == status)
1893 goto out;
1894 cx_write(MO_PCI_INTSTAT, status);
1895 handled = 1;
1896
1897 if (status & core->pci_irqmask)
1898 cx88_core_irq(core,status);
1899 if (status & 0x01)
1900 cx8800_vid_irq(dev);
1901 };
1902 if (10 == loop) {
1903 printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
1904 core->name);
1905 cx_write(MO_PCI_INTMSK,0);
1906 }
1907
1908 out:
1909 return IRQ_RETVAL(handled);
1910}
1911
1912/* ----------------------------------------------------------- */
1913/* exported stuff */
1914
1915static struct file_operations video_fops =
1916{
1917 .owner = THIS_MODULE,
1918 .open = video_open,
1919 .release = video_release,
1920 .read = video_read,
1921 .poll = video_poll,
1922 .mmap = video_mmap,
1923 .ioctl = video_ioctl,
1924 .llseek = no_llseek,
1925};
1926
1927struct video_device cx8800_video_template =
1928{
1929 .name = "cx8800-video",
1930 .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,
1931 .hardware = 0,
1932 .fops = &video_fops,
1933 .minor = -1,
1934};
1935
1936struct video_device cx8800_vbi_template =
1937{
1938 .name = "cx8800-vbi",
1939 .type = VID_TYPE_TELETEXT|VID_TYPE_TUNER,
1940 .hardware = 0,
1941 .fops = &video_fops,
1942 .minor = -1,
1943};
1944
1945static struct file_operations radio_fops =
1946{
1947 .owner = THIS_MODULE,
1948 .open = video_open,
1949 .release = video_release,
1950 .ioctl = radio_ioctl,
1951 .llseek = no_llseek,
1952};
1953
1954struct video_device cx8800_radio_template =
1955{
1956 .name = "cx8800-radio",
1957 .type = VID_TYPE_TUNER,
1958 .hardware = 0,
1959 .fops = &radio_fops,
1960 .minor = -1,
1961};
1962
1963/* ----------------------------------------------------------- */
1964
1965static void cx8800_unregister_video(struct cx8800_dev *dev)
1966{
1967 if (dev->radio_dev) {
1968 if (-1 != dev->radio_dev->minor)
1969 video_unregister_device(dev->radio_dev);
1970 else
1971 video_device_release(dev->radio_dev);
1972 dev->radio_dev = NULL;
1973 }
1974 if (dev->vbi_dev) {
1975 if (-1 != dev->vbi_dev->minor)
1976 video_unregister_device(dev->vbi_dev);
1977 else
1978 video_device_release(dev->vbi_dev);
1979 dev->vbi_dev = NULL;
1980 }
1981 if (dev->video_dev) {
1982 if (-1 != dev->video_dev->minor)
1983 video_unregister_device(dev->video_dev);
1984 else
1985 video_device_release(dev->video_dev);
1986 dev->video_dev = NULL;
1987 }
1988}
1989
1990static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
1991 const struct pci_device_id *pci_id)
1992{
1993 struct cx8800_dev *dev;
1994 struct cx88_core *core;
1995 int err;
1996
1997 dev = kmalloc(sizeof(*dev),GFP_KERNEL);
1998 if (NULL == dev)
1999 return -ENOMEM;
2000 memset(dev,0,sizeof(*dev));
2001
2002 /* pci init */
2003 dev->pci = pci_dev;
2004 if (pci_enable_device(pci_dev)) {
2005 err = -EIO;
2006 goto fail_free;
2007 }
2008 core = cx88_core_get(dev->pci);
2009 if (NULL == core) {
2010 err = -EINVAL;
2011 goto fail_free;
2012 }
2013 dev->core = core;
2014
2015 /* print pci info */
2016 pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
2017 pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
2018 printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
2019 "latency: %d, mmio: 0x%lx\n", core->name,
2020 pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
2021 dev->pci_lat,pci_resource_start(pci_dev,0));
2022
2023 pci_set_master(pci_dev);
2024 if (!pci_dma_supported(pci_dev,0xffffffff)) {
2025 printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name);
2026 err = -EIO;
2027 goto fail_core;
2028 }
2029
2030 /* initialize driver struct */
2031 init_MUTEX(&dev->lock);
2032 spin_lock_init(&dev->slock);
2033 core->tvnorm = tvnorms;
2034
2035 /* init video dma queues */
2036 INIT_LIST_HEAD(&dev->vidq.active);
2037 INIT_LIST_HEAD(&dev->vidq.queued);
2038 dev->vidq.timeout.function = cx8800_vid_timeout;
2039 dev->vidq.timeout.data = (unsigned long)dev;
2040 init_timer(&dev->vidq.timeout);
2041 cx88_risc_stopper(dev->pci,&dev->vidq.stopper,
2042 MO_VID_DMACNTRL,0x11,0x00);
2043
2044 /* init vbi dma queues */
2045 INIT_LIST_HEAD(&dev->vbiq.active);
2046 INIT_LIST_HEAD(&dev->vbiq.queued);
2047 dev->vbiq.timeout.function = cx8800_vbi_timeout;
2048 dev->vbiq.timeout.data = (unsigned long)dev;
2049 init_timer(&dev->vbiq.timeout);
2050 cx88_risc_stopper(dev->pci,&dev->vbiq.stopper,
2051 MO_VID_DMACNTRL,0x88,0x00);
2052
2053 /* get irq */
2054 err = request_irq(pci_dev->irq, cx8800_irq,
2055 SA_SHIRQ | SA_INTERRUPT, core->name, dev);
2056 if (err < 0) {
2057 printk(KERN_ERR "%s: can't get IRQ %d\n",
2058 core->name,pci_dev->irq);
2059 goto fail_core;
2060 }
2061 cx_set(MO_PCI_INTMSK, core->pci_irqmask);
2062
2063 /* load and configure helper modules */
2064 if (TUNER_ABSENT != core->tuner_type)
2065 request_module("tuner");
2066 if (core->tda9887_conf)
2067 request_module("tda9887");
2068 if (core->tuner_type != UNSET)
2069 cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE,&core->tuner_type);
2070 if (core->tda9887_conf)
2071 cx88_call_i2c_clients(dev->core,TDA9887_SET_CONFIG,&core->tda9887_conf);
2072
2073 /* register v4l devices */
2074 dev->video_dev = cx88_vdev_init(core,dev->pci,
2075 &cx8800_video_template,"video");
2076 err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
2077 video_nr[core->nr]);
2078 if (err < 0) {
2079 printk(KERN_INFO "%s: can't register video device\n",
2080 core->name);
2081 goto fail_unreg;
2082 }
2083 printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n",
2084 core->name,dev->video_dev->minor & 0x1f);
2085
2086 dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
2087 err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
2088 vbi_nr[core->nr]);
2089 if (err < 0) {
2090 printk(KERN_INFO "%s/0: can't register vbi device\n",
2091 core->name);
2092 goto fail_unreg;
2093 }
2094 printk(KERN_INFO "%s/0: registered device vbi%d\n",
2095 core->name,dev->vbi_dev->minor & 0x1f);
2096
2097 if (core->has_radio) {
2098 dev->radio_dev = cx88_vdev_init(core,dev->pci,
2099 &cx8800_radio_template,"radio");
2100 err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
2101 radio_nr[core->nr]);
2102 if (err < 0) {
2103 printk(KERN_INFO "%s/0: can't register radio device\n",
2104 core->name);
2105 goto fail_unreg;
2106 }
2107 printk(KERN_INFO "%s/0: registered device radio%d\n",
2108 core->name,dev->radio_dev->minor & 0x1f);
2109 }
2110
2111 /* everything worked */
2112 list_add_tail(&dev->devlist,&cx8800_devlist);
2113 pci_set_drvdata(pci_dev,dev);
2114
2115 /* initial device configuration */
2116 down(&dev->lock);
2117 init_controls(dev);
2118 cx88_set_tvnorm(dev->core,tvnorms);
2119 video_mux(dev,0);
2120 up(&dev->lock);
2121
2122 /* start tvaudio thread */
2123 if (core->tuner_type != TUNER_ABSENT)
2124 core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
2125 return 0;
2126
2127fail_unreg:
2128 cx8800_unregister_video(dev);
2129 free_irq(pci_dev->irq, dev);
2130fail_core:
2131 cx88_core_put(core,dev->pci);
2132fail_free:
2133 kfree(dev);
2134 return err;
2135}
2136
2137static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
2138{
2139 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
2140
2141 /* stop thread */
2142 if (dev->core->kthread) {
2143 kthread_stop(dev->core->kthread);
2144 dev->core->kthread = NULL;
2145 }
2146
2147 cx88_shutdown(dev->core); /* FIXME */
2148 pci_disable_device(pci_dev);
2149
2150 /* unregister stuff */
2151
2152 free_irq(pci_dev->irq, dev);
2153 cx8800_unregister_video(dev);
2154 pci_set_drvdata(pci_dev, NULL);
2155
2156 /* free memory */
2157 btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
2158 list_del(&dev->devlist);
2159 cx88_core_put(dev->core,dev->pci);
2160 kfree(dev);
2161}
2162
2163static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
2164{
2165 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
2166 struct cx88_core *core = dev->core;
2167
2168 /* stop video+vbi capture */
2169 spin_lock(&dev->slock);
2170 if (!list_empty(&dev->vidq.active)) {
2171 printk("%s: suspend video\n", core->name);
2172 stop_video_dma(dev);
2173 del_timer(&dev->vidq.timeout);
2174 }
2175 if (!list_empty(&dev->vbiq.active)) {
2176 printk("%s: suspend vbi\n", core->name);
2177 cx8800_stop_vbi_dma(dev);
2178 del_timer(&dev->vbiq.timeout);
2179 }
2180 spin_unlock(&dev->slock);
2181
2182#if 1
2183 /* FIXME -- shutdown device */
2184 cx88_shutdown(dev->core);
2185#endif
2186
2187 pci_save_state(pci_dev);
2188 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
2189 pci_disable_device(pci_dev);
2190 dev->state.disabled = 1;
2191 }
2192 return 0;
2193}
2194
2195static int cx8800_resume(struct pci_dev *pci_dev)
2196{
2197 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
2198 struct cx88_core *core = dev->core;
2199
2200 if (dev->state.disabled) {
2201 pci_enable_device(pci_dev);
2202 dev->state.disabled = 0;
2203 }
2204 pci_set_power_state(pci_dev, PCI_D0);
2205 pci_restore_state(pci_dev);
2206
2207#if 1
2208 /* FIXME: re-initialize hardware */
2209 cx88_reset(dev->core);
2210#endif
2211
2212 /* restart video+vbi capture */
2213 spin_lock(&dev->slock);
2214 if (!list_empty(&dev->vidq.active)) {
2215 printk("%s: resume video\n", core->name);
2216 restart_video_queue(dev,&dev->vidq);
2217 }
2218 if (!list_empty(&dev->vbiq.active)) {
2219 printk("%s: resume vbi\n", core->name);
2220 cx8800_restart_vbi_queue(dev,&dev->vbiq);
2221 }
2222 spin_unlock(&dev->slock);
2223
2224 return 0;
2225}
2226
2227/* ----------------------------------------------------------- */
2228
2229struct pci_device_id cx8800_pci_tbl[] = {
2230 {
2231 .vendor = 0x14f1,
2232 .device = 0x8800,
2233 .subvendor = PCI_ANY_ID,
2234 .subdevice = PCI_ANY_ID,
2235 },{
2236 /* --- end of list --- */
2237 }
2238};
2239MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl);
2240
2241static struct pci_driver cx8800_pci_driver = {
2242 .name = "cx8800",
2243 .id_table = cx8800_pci_tbl,
2244 .probe = cx8800_initdev,
2245 .remove = __devexit_p(cx8800_finidev),
2246
2247 .suspend = cx8800_suspend,
2248 .resume = cx8800_resume,
2249};
2250
2251static int cx8800_init(void)
2252{
2253 printk(KERN_INFO "cx2388x v4l2 driver version %d.%d.%d loaded\n",
2254 (CX88_VERSION_CODE >> 16) & 0xff,
2255 (CX88_VERSION_CODE >> 8) & 0xff,
2256 CX88_VERSION_CODE & 0xff);
2257#ifdef SNAPSHOT
2258 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
2259 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
2260#endif
2261 return pci_register_driver(&cx8800_pci_driver);
2262}
2263
2264static void cx8800_fini(void)
2265{
2266 pci_unregister_driver(&cx8800_pci_driver);
2267}
2268
2269module_init(cx8800_init);
2270module_exit(cx8800_fini);
2271
2272/* ----------------------------------------------------------- */
2273/*
2274 * Local variables:
2275 * c-basic-offset: 8
2276 * End:
2277 */
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
new file mode 100644
index 000000000000..b351d9eae615
--- /dev/null
+++ b/drivers/media/video/cx88/cx88.h
@@ -0,0 +1,551 @@
1/*
2 * $Id: cx88.h,v 1.56 2005/03/04 09:12:23 kraxel Exp $
3 *
4 * v4l2 device driver for cx2388x based TV cards
5 *
6 * (c) 2003,04 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/pci.h>
24#include <linux/i2c.h>
25#include <linux/i2c-algo-bit.h>
26#include <linux/videodev.h>
27#include <linux/kdev_t.h>
28
29#include <media/tuner.h>
30#include <media/tveeprom.h>
31#include <media/audiochip.h>
32#include <media/video-buf.h>
33#include <media/video-buf-dvb.h>
34
35#include "btcx-risc.h"
36#include "cx88-reg.h"
37
38#include <linux/version.h>
39#define CX88_VERSION_CODE KERNEL_VERSION(0,0,4)
40
41#ifndef TRUE
42# define TRUE (1==1)
43#endif
44#ifndef FALSE
45# define FALSE (1==0)
46#endif
47#define UNSET (-1U)
48
49#define CX88_MAXBOARDS 8
50
51/* ----------------------------------------------------------- */
52/* defines and enums */
53
54#define V4L2_I2C_CLIENTS 1
55
56#define FORMAT_FLAGS_PACKED 0x01
57#define FORMAT_FLAGS_PLANAR 0x02
58
59#define VBI_LINE_COUNT 17
60#define VBI_LINE_LENGTH 2048
61
62/* need "shadow" registers for some write-only ones ... */
63#define SHADOW_AUD_VOL_CTL 1
64#define SHADOW_AUD_BAL_CTL 2
65#define SHADOW_MAX 2
66
67/* ----------------------------------------------------------- */
68/* tv norms */
69
70struct cx88_tvnorm {
71 char *name;
72 v4l2_std_id id;
73 u32 cxiformat;
74 u32 cxoformat;
75};
76
77static unsigned int inline norm_maxw(struct cx88_tvnorm *norm)
78{
79 return (norm->id & V4L2_STD_625_50) ? 768 : 640;
80// return (norm->id & V4L2_STD_625_50) ? 720 : 640;
81}
82
83static unsigned int inline norm_maxh(struct cx88_tvnorm *norm)
84{
85 return (norm->id & V4L2_STD_625_50) ? 576 : 480;
86}
87
88/* ----------------------------------------------------------- */
89/* static data */
90
91struct cx8800_fmt {
92 char *name;
93 u32 fourcc; /* v4l2 format id */
94 int depth;
95 int flags;
96 u32 cxformat;
97};
98
99struct cx88_ctrl {
100 struct v4l2_queryctrl v;
101 u32 off;
102 u32 reg;
103 u32 sreg;
104 u32 mask;
105 u32 shift;
106};
107
108/* ----------------------------------------------------------- */
109/* SRAM memory management data (see cx88-core.c) */
110
111#define SRAM_CH21 0 /* video */
112#define SRAM_CH22 1
113#define SRAM_CH23 2
114#define SRAM_CH24 3 /* vbi */
115#define SRAM_CH25 4 /* audio */
116#define SRAM_CH26 5
117#define SRAM_CH28 6 /* mpeg */
118/* more */
119
120struct sram_channel {
121 char *name;
122 u32 cmds_start;
123 u32 ctrl_start;
124 u32 cdt;
125 u32 fifo_start;
126 u32 fifo_size;
127 u32 ptr1_reg;
128 u32 ptr2_reg;
129 u32 cnt1_reg;
130 u32 cnt2_reg;
131};
132extern struct sram_channel cx88_sram_channels[];
133
134/* ----------------------------------------------------------- */
135/* card configuration */
136
137#define CX88_BOARD_NOAUTO UNSET
138#define CX88_BOARD_UNKNOWN 0
139#define CX88_BOARD_HAUPPAUGE 1
140#define CX88_BOARD_GDI 2
141#define CX88_BOARD_PIXELVIEW 3
142#define CX88_BOARD_ATI_WONDER_PRO 4
143#define CX88_BOARD_WINFAST2000XP_EXPERT 5
144#define CX88_BOARD_AVERTV_303 6
145#define CX88_BOARD_MSI_TVANYWHERE_MASTER 7
146#define CX88_BOARD_WINFAST_DV2000 8
147#define CX88_BOARD_LEADTEK_PVR2000 9
148#define CX88_BOARD_IODATA_GVVCP3PCI 10
149#define CX88_BOARD_PROLINK_PLAYTVPVR 11
150#define CX88_BOARD_ASUS_PVR_416 12
151#define CX88_BOARD_MSI_TVANYWHERE 13
152#define CX88_BOARD_KWORLD_DVB_T 14
153#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1 15
154#define CX88_BOARD_KWORLD_LTV883 16
155#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD 17
156#define CX88_BOARD_HAUPPAUGE_DVB_T1 18
157#define CX88_BOARD_CONEXANT_DVB_T1 19
158#define CX88_BOARD_PROVIDEO_PV259 20
159#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS 21
160#define CX88_BOARD_PCHDTV_HD3000 22
161#define CX88_BOARD_DNTV_LIVE_DVB_T 23
162#define CX88_BOARD_HAUPPAUGE_ROSLYN 24
163#define CX88_BOARD_DIGITALLOGIC_MEC 25
164#define CX88_BOARD_IODATA_GVBCTV7E 26
165
166enum cx88_itype {
167 CX88_VMUX_COMPOSITE1 = 1,
168 CX88_VMUX_COMPOSITE2,
169 CX88_VMUX_COMPOSITE3,
170 CX88_VMUX_COMPOSITE4,
171 CX88_VMUX_SVIDEO,
172 CX88_VMUX_TELEVISION,
173 CX88_VMUX_CABLE,
174 CX88_VMUX_DVB,
175 CX88_VMUX_DEBUG,
176 CX88_RADIO,
177};
178
179struct cx88_input {
180 enum cx88_itype type;
181 unsigned int vmux;
182 u32 gpio0, gpio1, gpio2, gpio3;
183};
184
185struct cx88_board {
186 char *name;
187 unsigned int tuner_type;
188 int tda9887_conf;
189 struct cx88_input input[8];
190 struct cx88_input radio;
191 int blackbird:1;
192 int dvb:1;
193};
194
195struct cx88_subid {
196 u16 subvendor;
197 u16 subdevice;
198 u32 card;
199};
200
201#define INPUT(nr) (&cx88_boards[core->board].input[nr])
202
203/* ----------------------------------------------------------- */
204/* device / file handle status */
205
206#define RESOURCE_OVERLAY 1
207#define RESOURCE_VIDEO 2
208#define RESOURCE_VBI 4
209
210#define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */
211//#define BUFFER_TIMEOUT (HZ*2)
212
213/* buffer for one video frame */
214struct cx88_buffer {
215 /* common v4l buffer stuff -- must be first */
216 struct videobuf_buffer vb;
217
218 /* cx88 specific */
219 unsigned int bpl;
220 struct btcx_riscmem risc;
221 struct cx8800_fmt *fmt;
222 u32 count;
223};
224
225struct cx88_dmaqueue {
226 struct list_head active;
227 struct list_head queued;
228 struct timer_list timeout;
229 struct btcx_riscmem stopper;
230 u32 count;
231};
232
233struct cx88_core {
234 struct list_head devlist;
235 atomic_t refcount;
236
237 /* board name */
238 int nr;
239 char name[32];
240
241 /* pci stuff */
242 int pci_bus;
243 int pci_slot;
244 u32 __iomem *lmmio;
245 u8 __iomem *bmmio;
246 u32 shadow[SHADOW_MAX];
247 int pci_irqmask;
248
249 /* i2c i/o */
250 struct i2c_adapter i2c_adap;
251 struct i2c_algo_bit_data i2c_algo;
252 struct i2c_client i2c_client;
253 u32 i2c_state, i2c_rc;
254
255 /* config info -- analog */
256 unsigned int board;
257 unsigned int tuner_type;
258 unsigned int tda9887_conf;
259 unsigned int has_radio;
260
261 /* config info -- dvb */
262 struct dvb_pll_desc *pll_desc;
263 unsigned int pll_addr;
264
265 /* state info */
266 struct task_struct *kthread;
267 struct cx88_tvnorm *tvnorm;
268 u32 tvaudio;
269 u32 audiomode_manual;
270 u32 audiomode_current;
271 u32 input;
272 u32 astat;
273
274 /* IR remote control state */
275 struct cx88_IR *ir;
276};
277
278struct cx8800_dev;
279struct cx8802_dev;
280
281/* ----------------------------------------------------------- */
282/* function 0: video stuff */
283
284struct cx8800_fh {
285 struct cx8800_dev *dev;
286 enum v4l2_buf_type type;
287 int radio;
288 unsigned int resources;
289
290 /* video overlay */
291 struct v4l2_window win;
292 struct v4l2_clip *clips;
293 unsigned int nclips;
294
295 /* video capture */
296 struct cx8800_fmt *fmt;
297 unsigned int width,height;
298 struct videobuf_queue vidq;
299
300 /* vbi capture */
301 struct videobuf_queue vbiq;
302};
303
304struct cx8800_suspend_state {
305 int disabled;
306};
307
308struct cx8800_dev {
309 struct cx88_core *core;
310 struct list_head devlist;
311 struct semaphore lock;
312 spinlock_t slock;
313
314 /* various device info */
315 unsigned int resources;
316 struct video_device *video_dev;
317 struct video_device *vbi_dev;
318 struct video_device *radio_dev;
319
320 /* pci i/o */
321 struct pci_dev *pci;
322 unsigned char pci_rev,pci_lat;
323
324#if 0
325 /* video overlay */
326 struct v4l2_framebuffer fbuf;
327 struct cx88_buffer *screen;
328#endif
329
330 /* capture queues */
331 struct cx88_dmaqueue vidq;
332 struct cx88_dmaqueue vbiq;
333
334 /* various v4l controls */
335 u32 freq;
336
337 /* other global state info */
338 struct cx8800_suspend_state state;
339};
340
341/* ----------------------------------------------------------- */
342/* function 1: audio/alsa stuff */
343
344struct cx8801_dev {
345 struct cx88_core *core;
346
347 /* pci i/o */
348 struct pci_dev *pci;
349 unsigned char pci_rev,pci_lat;
350};
351
352/* ----------------------------------------------------------- */
353/* function 2: mpeg stuff */
354
355struct cx8802_fh {
356 struct cx8802_dev *dev;
357 struct videobuf_queue mpegq;
358};
359
360struct cx8802_suspend_state {
361 int disabled;
362};
363
364struct cx8802_dev {
365 struct cx88_core *core;
366 struct semaphore lock;
367 spinlock_t slock;
368
369 /* pci i/o */
370 struct pci_dev *pci;
371 unsigned char pci_rev,pci_lat;
372
373 /* dma queues */
374 struct cx88_dmaqueue mpegq;
375 u32 ts_packet_size;
376 u32 ts_packet_count;
377
378 /* other global state info */
379 struct cx8802_suspend_state state;
380
381 /* for blackbird only */
382 struct list_head devlist;
383 struct video_device *mpeg_dev;
384 u32 mailbox;
385 int width;
386 int height;
387
388 /* for dvb only */
389 struct videobuf_dvb dvb;
390 void* fe_handle;
391 int (*fe_release)(void *handle);
392
393 /* for switching modulation types */
394 unsigned char ts_gen_cntrl;
395};
396
397/* ----------------------------------------------------------- */
398
399#define cx_read(reg) readl(core->lmmio + ((reg)>>2))
400#define cx_write(reg,value) writel((value), core->lmmio + ((reg)>>2))
401#define cx_writeb(reg,value) writeb((value), core->bmmio + (reg))
402
403#define cx_andor(reg,mask,value) \
404 writel((readl(core->lmmio+((reg)>>2)) & ~(mask)) |\
405 ((value) & (mask)), core->lmmio+((reg)>>2))
406#define cx_set(reg,bit) cx_andor((reg),(bit),(bit))
407#define cx_clear(reg,bit) cx_andor((reg),(bit),0)
408
409#define cx_wait(d) { if (need_resched()) schedule(); else udelay(d); }
410
411/* shadow registers */
412#define cx_sread(sreg) (core->shadow[sreg])
413#define cx_swrite(sreg,reg,value) \
414 (core->shadow[sreg] = value, \
415 writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
416#define cx_sandor(sreg,reg,mask,value) \
417 (core->shadow[sreg] = (core->shadow[sreg] & ~(mask)) | ((value) & (mask)), \
418 writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
419
420/* ----------------------------------------------------------- */
421/* cx88-core.c */
422
423extern char *cx88_pci_irqs[32];
424extern char *cx88_vid_irqs[32];
425extern char *cx88_mpeg_irqs[32];
426extern void cx88_print_irqbits(char *name, char *tag, char **strings,
427 u32 bits, u32 mask);
428extern void cx88_print_ioctl(char *name, unsigned int cmd);
429
430extern int cx88_core_irq(struct cx88_core *core, u32 status);
431extern void cx88_wakeup(struct cx88_core *core,
432 struct cx88_dmaqueue *q, u32 count);
433extern void cx88_shutdown(struct cx88_core *core);
434extern int cx88_reset(struct cx88_core *core);
435
436extern int
437cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
438 struct scatterlist *sglist,
439 unsigned int top_offset, unsigned int bottom_offset,
440 unsigned int bpl, unsigned int padding, unsigned int lines);
441extern int
442cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
443 struct scatterlist *sglist, unsigned int bpl,
444 unsigned int lines);
445extern int
446cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
447 u32 reg, u32 mask, u32 value);
448extern void
449cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf);
450
451extern void cx88_risc_disasm(struct cx88_core *core,
452 struct btcx_riscmem *risc);
453extern int cx88_sram_channel_setup(struct cx88_core *core,
454 struct sram_channel *ch,
455 unsigned int bpl, u32 risc);
456extern void cx88_sram_channel_dump(struct cx88_core *core,
457 struct sram_channel *ch);
458
459extern int cx88_set_scale(struct cx88_core *core, unsigned int width,
460 unsigned int height, enum v4l2_field field);
461extern int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm);
462
463extern struct video_device *cx88_vdev_init(struct cx88_core *core,
464 struct pci_dev *pci,
465 struct video_device *template,
466 char *type);
467extern struct cx88_core* cx88_core_get(struct pci_dev *pci);
468extern void cx88_core_put(struct cx88_core *core,
469 struct pci_dev *pci);
470
471/* ----------------------------------------------------------- */
472/* cx88-vbi.c */
473
474void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f);
475int cx8800_start_vbi_dma(struct cx8800_dev *dev,
476 struct cx88_dmaqueue *q,
477 struct cx88_buffer *buf);
478int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
479int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
480 struct cx88_dmaqueue *q);
481void cx8800_vbi_timeout(unsigned long data);
482
483extern struct videobuf_queue_ops cx8800_vbi_qops;
484
485/* ----------------------------------------------------------- */
486/* cx88-i2c.c */
487
488extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci);
489extern void cx88_call_i2c_clients(struct cx88_core *core,
490 unsigned int cmd, void *arg);
491
492
493/* ----------------------------------------------------------- */
494/* cx88-cards.c */
495
496extern struct cx88_board cx88_boards[];
497extern const unsigned int cx88_bcount;
498
499extern struct cx88_subid cx88_subids[];
500extern const unsigned int cx88_idcount;
501
502extern void cx88_card_list(struct cx88_core *core, struct pci_dev *pci);
503extern void cx88_card_setup(struct cx88_core *core);
504
505/* ----------------------------------------------------------- */
506/* cx88-tvaudio.c */
507
508#define WW_NONE 1
509#define WW_BTSC 2
510#define WW_NICAM_I 3
511#define WW_NICAM_BGDKL 4
512#define WW_A1 5
513#define WW_A2_BG 6
514#define WW_A2_DK 7
515#define WW_A2_M 8
516#define WW_EIAJ 9
517#define WW_SYSTEM_L_AM 10
518#define WW_I2SPT 11
519#define WW_FM 12
520
521void cx88_set_tvaudio(struct cx88_core *core);
522void cx88_newstation(struct cx88_core *core);
523void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
524void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
525int cx88_audio_thread(void *data);
526
527/* ----------------------------------------------------------- */
528/* cx88-input.c */
529
530int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci);
531int cx88_ir_fini(struct cx88_core *core);
532void cx88_ir_irq(struct cx88_core *core);
533
534/* ----------------------------------------------------------- */
535/* cx88-mpeg.c */
536
537int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf);
538void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
539void cx8802_cancel_buffers(struct cx8802_dev *dev);
540
541int cx8802_init_common(struct cx8802_dev *dev);
542void cx8802_fini_common(struct cx8802_dev *dev);
543
544int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state);
545int cx8802_resume_common(struct pci_dev *pci_dev);
546
547/*
548 * Local variables:
549 * c-basic-offset: 8
550 * End:
551 */