V4L/DVB (4228a): pvrusb2 to kernel 2.6.18
[deliverable/linux.git] / drivers / media / video / saa7114.c
CommitLineData
d56410e0 1/*
1da177e4
LT
2 * saa7114 - Philips SAA7114H video decoder driver version 0.0.1
3 *
4 * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
5 *
6 * Based on saa7111 driver by Dave Perks
7 *
8 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
9 *
10 * Slight changes for video timing and attachment output by
11 * Wolfgang Scherr <scherr@net4you.net>
12 *
13 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
14 * - moved over to linux>=2.4.x i2c protocol (1/1/2003)
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30
31#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/delay.h>
34#include <linux/errno.h>
35#include <linux/fs.h>
36#include <linux/kernel.h>
37#include <linux/major.h>
38
39#include <linux/slab.h>
40
41#include <linux/mm.h>
42#include <linux/pci.h>
43#include <linux/signal.h>
44#include <asm/io.h>
45#include <asm/pgtable.h>
46#include <asm/page.h>
47#include <linux/sched.h>
1da177e4
LT
48#include <linux/types.h>
49
50#include <linux/videodev.h>
51#include <asm/uaccess.h>
52
53MODULE_DESCRIPTION("Philips SAA7114H video decoder driver");
54MODULE_AUTHOR("Maxim Yevtyushkin");
55MODULE_LICENSE("GPL");
56
57#include <linux/i2c.h>
1da177e4
LT
58
59#define I2C_NAME(x) (x)->name
60
61#include <linux/video_decoder.h>
62
63static int debug = 0;
64module_param(debug, int, 0);
65MODULE_PARM_DESC(debug, "Debug level (0-1)");
66
67#define dprintk(num, format, args...) \
68 do { \
69 if (debug >= num) \
70 printk(format, ##args); \
71 } while (0)
72
73/* ----------------------------------------------------------------------- */
74
75struct saa7114 {
76 unsigned char reg[0xf0 * 2];
77
78 int norm;
79 int input;
80 int enable;
81 int bright;
82 int contrast;
83 int hue;
84 int sat;
85 int playback;
86};
87
88#define I2C_SAA7114 0x42
89#define I2C_SAA7114A 0x40
90
91#define I2C_DELAY 10
92
93
94//#define SAA_7114_NTSC_HSYNC_START (-3)
95//#define SAA_7114_NTSC_HSYNC_STOP (-18)
96
97#define SAA_7114_NTSC_HSYNC_START (-17)
98#define SAA_7114_NTSC_HSYNC_STOP (-32)
99
100//#define SAA_7114_NTSC_HOFFSET (5)
101#define SAA_7114_NTSC_HOFFSET (6)
102#define SAA_7114_NTSC_VOFFSET (10)
103#define SAA_7114_NTSC_WIDTH (720)
104#define SAA_7114_NTSC_HEIGHT (250)
105
106#define SAA_7114_SECAM_HSYNC_START (-17)
107#define SAA_7114_SECAM_HSYNC_STOP (-32)
108
109#define SAA_7114_SECAM_HOFFSET (2)
110#define SAA_7114_SECAM_VOFFSET (10)
111#define SAA_7114_SECAM_WIDTH (720)
112#define SAA_7114_SECAM_HEIGHT (300)
113
114#define SAA_7114_PAL_HSYNC_START (-17)
115#define SAA_7114_PAL_HSYNC_STOP (-32)
116
117#define SAA_7114_PAL_HOFFSET (2)
118#define SAA_7114_PAL_VOFFSET (10)
119#define SAA_7114_PAL_WIDTH (720)
120#define SAA_7114_PAL_HEIGHT (300)
121
122
123
124#define SAA_7114_VERTICAL_CHROMA_OFFSET 0 //0x50504040
125#define SAA_7114_VERTICAL_LUMA_OFFSET 0
126
127#define REG_ADDR(x) (((x) << 1) + 1)
128#define LOBYTE(x) ((unsigned char)((x) & 0xff))
129#define HIBYTE(x) ((unsigned char)(((x) >> 8) & 0xff))
130#define LOWORD(x) ((unsigned short int)((x) & 0xffff))
131#define HIWORD(x) ((unsigned short int)(((x) >> 16) & 0xffff))
132
133
134/* ----------------------------------------------------------------------- */
135
136static inline int
137saa7114_write (struct i2c_client *client,
138 u8 reg,
139 u8 value)
140{
1da177e4
LT
141 return i2c_smbus_write_byte_data(client, reg, value);
142}
143
144static int
145saa7114_write_block (struct i2c_client *client,
146 const u8 *data,
147 unsigned int len)
148{
149 int ret = -1;
150 u8 reg;
151
152 /* the saa7114 has an autoincrement function, use it if
153 * the adapter understands raw I2C */
154 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
155 /* do raw I2C, not smbus compatible */
1da177e4 156 u8 block_data[32];
9aa45e34 157 int block_len;
1da177e4 158
1da177e4 159 while (len >= 2) {
9aa45e34
JD
160 block_len = 0;
161 block_data[block_len++] = reg = data[0];
1da177e4 162 do {
9aa45e34 163 block_data[block_len++] = data[1];
62543123 164 reg++;
1da177e4
LT
165 len -= 2;
166 data += 2;
167 } while (len >= 2 && data[0] == reg &&
9aa45e34
JD
168 block_len < 32);
169 if ((ret = i2c_master_send(client, block_data,
170 block_len)) < 0)
1da177e4
LT
171 break;
172 }
173 } else {
174 /* do some slow I2C emulation kind of thing */
175 while (len >= 2) {
176 reg = *data++;
177 if ((ret = saa7114_write(client, reg,
178 *data++)) < 0)
179 break;
180 len -= 2;
181 }
182 }
183
184 return ret;
185}
186
187static inline int
188saa7114_read (struct i2c_client *client,
189 u8 reg)
190{
191 return i2c_smbus_read_byte_data(client, reg);
192}
193
194/* ----------------------------------------------------------------------- */
195
196// initially set NTSC, composite
197
198
199static const unsigned char init[] = {
200 0x00, 0x00, /* 00 - ID byte , chip version,
201 * read only */
202 0x01, 0x08, /* 01 - X,X,X,X, IDEL3 to IDEL0 -
203 * horizontal increment delay,
204 * recommended position */
205 0x02, 0x00, /* 02 - FUSE=3, GUDL=2, MODE=0 ;
206 * input control */
207 0x03, 0x10, /* 03 - HLNRS=0, VBSL=1, WPOFF=0,
208 * HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
209 0x04, 0x90, /* 04 - GAI1=256 */
210 0x05, 0x90, /* 05 - GAI2=256 */
211 0x06, SAA_7114_NTSC_HSYNC_START, /* 06 - HSB: hsync start,
212 * depends on the video standard */
213 0x07, SAA_7114_NTSC_HSYNC_STOP, /* 07 - HSS: hsync stop, depends
214 *on the video standard */
215 0x08, 0xb8, /* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1,
216 * HPLL: free running in playback, locked
217 * in capture, VNOI=0 */
218 0x09, 0x80, /* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0,
219 * UPTCV=0, APER=1; depends from input */
220 0x0a, 0x80, /* 0a - BRIG=128 */
221 0x0b, 0x44, /* 0b - CONT=1.109 */
222 0x0c, 0x40, /* 0c - SATN=1.0 */
223 0x0d, 0x00, /* 0d - HUE=0 */
224 0x0e, 0x84, /* 0e - CDTO, CSTD2 to 0, DCVF, FCTC,
225 * CCOMB; depends from video standard */
226 0x0f, 0x24, /* 0f - ACGC,CGAIN6 to CGAIN0; depends
227 * from video standard */
228 0x10, 0x03, /* 10 - OFFU1 to 0, OFFV1 to 0, CHBW,
229 * LCBW2 to 0 */
230 0x11, 0x59, /* 11 - COLO, RTP1, HEDL1 to 0, RTP0,
231 * YDEL2 to 0 */
232 0x12, 0xc9, /* 12 - RT signal control RTSE13 to 10
233 * and 03 to 00 */
234 0x13, 0x80, /* 13 - RT/X port output control */
235 0x14, 0x00, /* 14 - analog, ADC, compatibility control */
236 0x15, 0x00, /* 15 - VGATE start FID change */
237 0x16, 0xfe, /* 16 - VGATE stop */
238 0x17, 0x00, /* 17 - Misc., VGATE MSBs */
239 0x18, 0x40, /* RAWG */
240 0x19, 0x80, /* RAWO */
241 0x1a, 0x00,
242 0x1b, 0x00,
243 0x1c, 0x00,
244 0x1d, 0x00,
245 0x1e, 0x00,
246 0x1f, 0x00, /* status byte, read only */
247 0x20, 0x00, /* video decoder reserved part */
248 0x21, 0x00,
249 0x22, 0x00,
250 0x23, 0x00,
251 0x24, 0x00,
252 0x25, 0x00,
253 0x26, 0x00,
254 0x27, 0x00,
255 0x28, 0x00,
256 0x29, 0x00,
257 0x2a, 0x00,
258 0x2b, 0x00,
259 0x2c, 0x00,
260 0x2d, 0x00,
261 0x2e, 0x00,
262 0x2f, 0x00,
263 0x30, 0xbc, /* audio clock generator */
264 0x31, 0xdf,
265 0x32, 0x02,
266 0x33, 0x00,
267 0x34, 0xcd,
268 0x35, 0xcc,
269 0x36, 0x3a,
270 0x37, 0x00,
271 0x38, 0x03,
272 0x39, 0x10,
273 0x3a, 0x00,
274 0x3b, 0x00,
275 0x3c, 0x00,
276 0x3d, 0x00,
277 0x3e, 0x00,
278 0x3f, 0x00,
279 0x40, 0x00, /* VBI data slicer */
280 0x41, 0xff,
281 0x42, 0xff,
282 0x43, 0xff,
283 0x44, 0xff,
284 0x45, 0xff,
285 0x46, 0xff,
286 0x47, 0xff,
287 0x48, 0xff,
288 0x49, 0xff,
289 0x4a, 0xff,
290 0x4b, 0xff,
291 0x4c, 0xff,
292 0x4d, 0xff,
293 0x4e, 0xff,
294 0x4f, 0xff,
295 0x50, 0xff,
296 0x51, 0xff,
297 0x52, 0xff,
298 0x53, 0xff,
299 0x54, 0xff,
300 0x55, 0xff,
301 0x56, 0xff,
302 0x57, 0xff,
d56410e0 303 0x58, 0x40, // framing code
1da177e4
LT
304 0x59, 0x47, // horizontal offset
305 0x5a, 0x06, // vertical offset
306 0x5b, 0x83, // field offset
307 0x5c, 0x00, // reserved
308 0x5d, 0x3e, // header and data
309 0x5e, 0x00, // sliced data
310 0x5f, 0x00, // reserved
311 0x60, 0x00, /* video decoder reserved part */
312 0x61, 0x00,
313 0x62, 0x00,
314 0x63, 0x00,
315 0x64, 0x00,
316 0x65, 0x00,
317 0x66, 0x00,
318 0x67, 0x00,
319 0x68, 0x00,
320 0x69, 0x00,
321 0x6a, 0x00,
322 0x6b, 0x00,
323 0x6c, 0x00,
324 0x6d, 0x00,
325 0x6e, 0x00,
326 0x6f, 0x00,
327 0x70, 0x00, /* video decoder reserved part */
328 0x71, 0x00,
329 0x72, 0x00,
330 0x73, 0x00,
331 0x74, 0x00,
332 0x75, 0x00,
333 0x76, 0x00,
334 0x77, 0x00,
335 0x78, 0x00,
336 0x79, 0x00,
337 0x7a, 0x00,
338 0x7b, 0x00,
339 0x7c, 0x00,
340 0x7d, 0x00,
341 0x7e, 0x00,
342 0x7f, 0x00,
343 0x80, 0x00, /* X-port, I-port and scaler */
344 0x81, 0x00,
345 0x82, 0x00,
346 0x83, 0x00,
347 0x84, 0xc5,
d56410e0 348 0x85, 0x0d, // hsync and vsync ?
1da177e4
LT
349 0x86, 0x40,
350 0x87, 0x01,
351 0x88, 0x00,
352 0x89, 0x00,
353 0x8a, 0x00,
354 0x8b, 0x00,
355 0x8c, 0x00,
356 0x8d, 0x00,
357 0x8e, 0x00,
358 0x8f, 0x00,
359 0x90, 0x03, /* Task A definition */
360 0x91, 0x08,
361 0x92, 0x00,
362 0x93, 0x40,
363 0x94, 0x00, // window settings
364 0x95, 0x00,
365 0x96, 0x00,
366 0x97, 0x00,
367 0x98, 0x00,
368 0x99, 0x00,
369 0x9a, 0x00,
370 0x9b, 0x00,
371 0x9c, 0x00,
372 0x9d, 0x00,
373 0x9e, 0x00,
374 0x9f, 0x00,
375 0xa0, 0x01, /* horizontal integer prescaling ratio */
376 0xa1, 0x00, /* horizontal prescaler accumulation
377 * sequence length */
378 0xa2, 0x00, /* UV FIR filter, Y FIR filter, prescaler
379 * DC gain */
380 0xa3, 0x00,
381 0xa4, 0x80, // luminance brightness
382 0xa5, 0x40, // luminance gain
383 0xa6, 0x40, // chrominance saturation
384 0xa7, 0x00,
385 0xa8, 0x00, // horizontal luminance scaling increment
386 0xa9, 0x04,
387 0xaa, 0x00, // horizontal luminance phase offset
388 0xab, 0x00,
389 0xac, 0x00, // horizontal chrominance scaling increment
390 0xad, 0x02,
391 0xae, 0x00, // horizontal chrominance phase offset
392 0xaf, 0x00,
393 0xb0, 0x00, // vertical luminance scaling increment
394 0xb1, 0x04,
395 0xb2, 0x00, // vertical chrominance scaling increment
396 0xb3, 0x04,
397 0xb4, 0x00,
398 0xb5, 0x00,
399 0xb6, 0x00,
400 0xb7, 0x00,
401 0xb8, 0x00,
402 0xb9, 0x00,
403 0xba, 0x00,
404 0xbb, 0x00,
405 0xbc, 0x00,
406 0xbd, 0x00,
407 0xbe, 0x00,
408 0xbf, 0x00,
409 0xc0, 0x02, // Task B definition
410 0xc1, 0x08,
411 0xc2, 0x00,
412 0xc3, 0x40,
413 0xc4, 0x00, // window settings
414 0xc5, 0x00,
415 0xc6, 0x00,
416 0xc7, 0x00,
417 0xc8, 0x00,
418 0xc9, 0x00,
419 0xca, 0x00,
420 0xcb, 0x00,
421 0xcc, 0x00,
422 0xcd, 0x00,
423 0xce, 0x00,
424 0xcf, 0x00,
425 0xd0, 0x01, // horizontal integer prescaling ratio
426 0xd1, 0x00, // horizontal prescaler accumulation sequence length
427 0xd2, 0x00, // UV FIR filter, Y FIR filter, prescaler DC gain
428 0xd3, 0x00,
429 0xd4, 0x80, // luminance brightness
430 0xd5, 0x40, // luminance gain
431 0xd6, 0x40, // chrominance saturation
432 0xd7, 0x00,
433 0xd8, 0x00, // horizontal luminance scaling increment
434 0xd9, 0x04,
435 0xda, 0x00, // horizontal luminance phase offset
436 0xdb, 0x00,
d56410e0 437 0xdc, 0x00, // horizontal chrominance scaling increment
1da177e4
LT
438 0xdd, 0x02,
439 0xde, 0x00, // horizontal chrominance phase offset
440 0xdf, 0x00,
441 0xe0, 0x00, // vertical luminance scaling increment
442 0xe1, 0x04,
443 0xe2, 0x00, // vertical chrominance scaling increment
444 0xe3, 0x04,
445 0xe4, 0x00,
446 0xe5, 0x00,
447 0xe6, 0x00,
448 0xe7, 0x00,
449 0xe8, 0x00,
450 0xe9, 0x00,
451 0xea, 0x00,
452 0xeb, 0x00,
453 0xec, 0x00,
454 0xed, 0x00,
455 0xee, 0x00,
456 0xef, 0x00
457};
458
459static int
460saa7114_command (struct i2c_client *client,
461 unsigned int cmd,
462 void *arg)
463{
464 struct saa7114 *decoder = i2c_get_clientdata(client);
465
466 switch (cmd) {
467
468 case 0:
469 //dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client));
470 //saa7114_write_block(client, init, sizeof(init));
471 break;
472
473 case DECODER_DUMP:
474 {
475 int i;
476
477 dprintk(1, KERN_INFO "%s: decoder dump\n", I2C_NAME(client));
478
479 for (i = 0; i < 32; i += 16) {
480 int j;
481
482 printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i);
483 for (j = 0; j < 16; ++j) {
484 printk(" %02x",
485 saa7114_read(client, i + j));
486 }
487 printk("\n");
488 }
489 }
490 break;
491
492 case DECODER_GET_CAPABILITIES:
493 {
494 struct video_decoder_capability *cap = arg;
495
496 dprintk(1, KERN_DEBUG "%s: decoder get capabilities\n",
497 I2C_NAME(client));
498
499 cap->flags = VIDEO_DECODER_PAL |
500 VIDEO_DECODER_NTSC |
501 VIDEO_DECODER_AUTO |
502 VIDEO_DECODER_CCIR;
503 cap->inputs = 8;
504 cap->outputs = 1;
505 }
506 break;
507
508 case DECODER_GET_STATUS:
509 {
510 int *iarg = arg;
511 int status;
512 int res;
513
514 status = saa7114_read(client, 0x1f);
515
516 dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client),
517 status);
518 res = 0;
519 if ((status & (1 << 6)) == 0) {
520 res |= DECODER_STATUS_GOOD;
521 }
522 switch (decoder->norm) {
523 case VIDEO_MODE_NTSC:
524 res |= DECODER_STATUS_NTSC;
525 break;
526 case VIDEO_MODE_PAL:
527 res |= DECODER_STATUS_PAL;
528 break;
529 case VIDEO_MODE_SECAM:
530 res |= DECODER_STATUS_SECAM;
531 break;
532 default:
533 case VIDEO_MODE_AUTO:
534 if ((status & (1 << 5)) != 0) {
535 res |= DECODER_STATUS_NTSC;
536 } else {
537 res |= DECODER_STATUS_PAL;
538 }
539 break;
540 }
541 if ((status & (1 << 0)) != 0) {
542 res |= DECODER_STATUS_COLOR;
543 }
544 *iarg = res;
545 }
546 break;
547
548 case DECODER_SET_NORM:
549 {
550 int *iarg = arg;
551
552 short int hoff = 0, voff = 0, w = 0, h = 0;
553
554 dprintk(1, KERN_DEBUG "%s: decoder set norm ",
555 I2C_NAME(client));
556 switch (*iarg) {
557
558 case VIDEO_MODE_NTSC:
559 dprintk(1, "NTSC\n");
560 decoder->reg[REG_ADDR(0x06)] =
561 SAA_7114_NTSC_HSYNC_START;
562 decoder->reg[REG_ADDR(0x07)] =
563 SAA_7114_NTSC_HSYNC_STOP;
564
565 decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture
566
567 decoder->reg[REG_ADDR(0x0e)] = 0x85;
568 decoder->reg[REG_ADDR(0x0f)] = 0x24;
569
570 hoff = SAA_7114_NTSC_HOFFSET;
571 voff = SAA_7114_NTSC_VOFFSET;
572 w = SAA_7114_NTSC_WIDTH;
573 h = SAA_7114_NTSC_HEIGHT;
574
575 break;
576
577 case VIDEO_MODE_PAL:
578 dprintk(1, "PAL\n");
579 decoder->reg[REG_ADDR(0x06)] =
580 SAA_7114_PAL_HSYNC_START;
581 decoder->reg[REG_ADDR(0x07)] =
582 SAA_7114_PAL_HSYNC_STOP;
583
584 decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture
585
586 decoder->reg[REG_ADDR(0x0e)] = 0x81;
587 decoder->reg[REG_ADDR(0x0f)] = 0x24;
588
589 hoff = SAA_7114_PAL_HOFFSET;
590 voff = SAA_7114_PAL_VOFFSET;
591 w = SAA_7114_PAL_WIDTH;
592 h = SAA_7114_PAL_HEIGHT;
593
594 break;
595
596 default:
597 dprintk(1, " Unknown video mode!!!\n");
598 return -EINVAL;
599
600 }
601
602
603 decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff); // hoffset low
604 decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f; // hoffset high
605 decoder->reg[REG_ADDR(0x96)] = LOBYTE(w); // width low
606 decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f; // width high
607 decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff); // voffset low
608 decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f; // voffset high
609 decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2); // height low
610 decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f; // height high
611 decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w); // out width low
612 decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f; // out width high
613 decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h); // out height low
614 decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f; // out height high
615
616 decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff); // hoffset low
617 decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f; // hoffset high
618 decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w); // width low
619 decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f; // width high
620 decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff); // voffset low
621 decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f; // voffset high
622 decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2); // height low
623 decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f; // height high
624 decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w); // out width low
625 decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f; // out width high
626 decoder->reg[REG_ADDR(0xce)] = LOBYTE(h); // out height low
627 decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f; // out height high
628
629
630 saa7114_write(client, 0x80, 0x06); // i-port and scaler back end clock selection, task A&B off
631 saa7114_write(client, 0x88, 0xd8); // sw reset scaler
632 saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
633
634 saa7114_write_block(client, decoder->reg + (0x06 << 1),
635 3 << 1);
636 saa7114_write_block(client, decoder->reg + (0x0e << 1),
637 2 << 1);
638 saa7114_write_block(client, decoder->reg + (0x5a << 1),
639 2 << 1);
640
641 saa7114_write_block(client, decoder->reg + (0x94 << 1),
642 (0x9f + 1 - 0x94) << 1);
643 saa7114_write_block(client, decoder->reg + (0xc4 << 1),
644 (0xcf + 1 - 0xc4) << 1);
645
646 saa7114_write(client, 0x88, 0xd8); // sw reset scaler
647 saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
648 saa7114_write(client, 0x80, 0x36); // i-port and scaler back end clock selection
649
650 decoder->norm = *iarg;
651 }
652 break;
653
654 case DECODER_SET_INPUT:
655 {
656 int *iarg = arg;
657
658 dprintk(1, KERN_DEBUG "%s: decoder set input (%d)\n",
659 I2C_NAME(client), *iarg);
660 if (*iarg < 0 || *iarg > 7) {
661 return -EINVAL;
662 }
663
664 if (decoder->input != *iarg) {
665 dprintk(1, KERN_DEBUG "%s: now setting %s input\n",
666 I2C_NAME(client),
667 *iarg >= 6 ? "S-Video" : "Composite");
668 decoder->input = *iarg;
669
670 /* select mode */
671 decoder->reg[REG_ADDR(0x02)] =
672 (decoder->
673 reg[REG_ADDR(0x02)] & 0xf0) | (decoder->
674 input <
675 6 ? 0x0 : 0x9);
676 saa7114_write(client, 0x02,
677 decoder->reg[REG_ADDR(0x02)]);
678
679 /* bypass chrominance trap for modes 6..9 */
680 decoder->reg[REG_ADDR(0x09)] =
681 (decoder->
682 reg[REG_ADDR(0x09)] & 0x7f) | (decoder->
683 input <
684 6 ? 0x0 :
685 0x80);
686 saa7114_write(client, 0x09,
687 decoder->reg[REG_ADDR(0x09)]);
688
689 decoder->reg[REG_ADDR(0x0e)] =
690 decoder->input <
691 6 ? decoder->
692 reg[REG_ADDR(0x0e)] | 1 : decoder->
693 reg[REG_ADDR(0x0e)] & ~1;
694 saa7114_write(client, 0x0e,
695 decoder->reg[REG_ADDR(0x0e)]);
696 }
697 }
698 break;
699
700 case DECODER_SET_OUTPUT:
701 {
702 int *iarg = arg;
703
704 dprintk(1, KERN_DEBUG "%s: decoder set output\n",
705 I2C_NAME(client));
706
707 /* not much choice of outputs */
708 if (*iarg != 0) {
709 return -EINVAL;
710 }
711 }
712 break;
713
714 case DECODER_ENABLE_OUTPUT:
715 {
716 int *iarg = arg;
717 int enable = (*iarg != 0);
718
719 dprintk(1, KERN_DEBUG "%s: decoder %s output\n",
720 I2C_NAME(client), enable ? "enable" : "disable");
721
722 decoder->playback = !enable;
723
724 if (decoder->enable != enable) {
725 decoder->enable = enable;
726
727 /* RJ: If output should be disabled (for
728 * playing videos), we also need a open PLL.
729 * The input is set to 0 (where no input
730 * source is connected), although this
731 * is not necessary.
732 *
733 * If output should be enabled, we have to
734 * reverse the above.
735 */
736
737 if (decoder->enable) {
738 decoder->reg[REG_ADDR(0x08)] = 0xb8;
739 decoder->reg[REG_ADDR(0x12)] = 0xc9;
740 decoder->reg[REG_ADDR(0x13)] = 0x80;
741 decoder->reg[REG_ADDR(0x87)] = 0x01;
742 } else {
743 decoder->reg[REG_ADDR(0x08)] = 0x7c;
744 decoder->reg[REG_ADDR(0x12)] = 0x00;
745 decoder->reg[REG_ADDR(0x13)] = 0x00;
746 decoder->reg[REG_ADDR(0x87)] = 0x00;
747 }
748
749 saa7114_write_block(client,
750 decoder->reg + (0x12 << 1),
751 2 << 1);
752 saa7114_write(client, 0x08,
753 decoder->reg[REG_ADDR(0x08)]);
754 saa7114_write(client, 0x87,
755 decoder->reg[REG_ADDR(0x87)]);
756 saa7114_write(client, 0x88, 0xd8); // sw reset scaler
d56410e0 757 saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
1da177e4
LT
758 saa7114_write(client, 0x80, 0x36);
759
760 }
761 }
762 break;
763
764 case DECODER_SET_PICTURE:
765 {
766 struct video_picture *pic = arg;
767
768 dprintk(1,
769 KERN_DEBUG
770 "%s: decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n",
771 I2C_NAME(client), pic->brightness, pic->contrast,
772 pic->colour, pic->hue);
773
774 if (decoder->bright != pic->brightness) {
775 /* We want 0 to 255 we get 0-65535 */
776 decoder->bright = pic->brightness;
777 saa7114_write(client, 0x0a, decoder->bright >> 8);
778 }
779 if (decoder->contrast != pic->contrast) {
780 /* We want 0 to 127 we get 0-65535 */
781 decoder->contrast = pic->contrast;
782 saa7114_write(client, 0x0b,
783 decoder->contrast >> 9);
784 }
785 if (decoder->sat != pic->colour) {
786 /* We want 0 to 127 we get 0-65535 */
787 decoder->sat = pic->colour;
788 saa7114_write(client, 0x0c, decoder->sat >> 9);
789 }
790 if (decoder->hue != pic->hue) {
791 /* We want -128 to 127 we get 0-65535 */
792 decoder->hue = pic->hue;
793 saa7114_write(client, 0x0d,
794 (decoder->hue - 32768) >> 8);
795 }
796 }
797 break;
798
799 default:
800 return -EINVAL;
801 }
802
803 return 0;
804}
805
806/* ----------------------------------------------------------------------- */
807
808/*
809 * Generic i2c probe
810 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
811 */
812static unsigned short normal_i2c[] =
813 { I2C_SAA7114 >> 1, I2C_SAA7114A >> 1, I2C_CLIENT_END };
1da177e4 814
68cc9d0b 815static unsigned short ignore = I2C_CLIENT_END;
d56410e0 816
1da177e4
LT
817static struct i2c_client_address_data addr_data = {
818 .normal_i2c = normal_i2c,
68cc9d0b
JD
819 .probe = &ignore,
820 .ignore = &ignore,
1da177e4
LT
821};
822
823static struct i2c_driver i2c_driver_saa7114;
824
825static int
826saa7114_detect_client (struct i2c_adapter *adapter,
827 int address,
828 int kind)
829{
830 int i, err[30];
831 short int hoff = SAA_7114_NTSC_HOFFSET;
832 short int voff = SAA_7114_NTSC_VOFFSET;
833 short int w = SAA_7114_NTSC_WIDTH;
834 short int h = SAA_7114_NTSC_HEIGHT;
835 struct i2c_client *client;
836 struct saa7114 *decoder;
837
838 dprintk(1,
839 KERN_INFO
840 "saa7114.c: detecting saa7114 client on address 0x%x\n",
841 address << 1);
842
843 /* Check if the adapter supports the needed features */
844 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
845 return 0;
846
7408187d 847 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
1da177e4
LT
848 if (client == 0)
849 return -ENOMEM;
1da177e4
LT
850 client->addr = address;
851 client->adapter = adapter;
852 client->driver = &i2c_driver_saa7114;
1da177e4
LT
853 strlcpy(I2C_NAME(client), "saa7114", sizeof(I2C_NAME(client)));
854
7408187d 855 decoder = kzalloc(sizeof(struct saa7114), GFP_KERNEL);
1da177e4
LT
856 if (decoder == NULL) {
857 kfree(client);
858 return -ENOMEM;
859 }
1da177e4
LT
860 decoder->norm = VIDEO_MODE_NTSC;
861 decoder->input = -1;
862 decoder->enable = 1;
863 decoder->bright = 32768;
864 decoder->contrast = 32768;
865 decoder->hue = 32768;
866 decoder->sat = 32768;
867 decoder->playback = 0; // initially capture mode useda
868 i2c_set_clientdata(client, decoder);
869
870 memcpy(decoder->reg, init, sizeof(init));
871
872 decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff); // hoffset low
873 decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f; // hoffset high
874 decoder->reg[REG_ADDR(0x96)] = LOBYTE(w); // width low
875 decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f; // width high
876 decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff); // voffset low
877 decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f; // voffset high
878 decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2); // height low
879 decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f; // height high
880 decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w); // out width low
881 decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f; // out width high
882 decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h); // out height low
883 decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f; // out height high
884
885 decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff); // hoffset low
886 decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f; // hoffset high
887 decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w); // width low
888 decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f; // width high
889 decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff); // voffset low
890 decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f; // voffset high
891 decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2); // height low
892 decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f; // height high
893 decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w); // out width low
894 decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f; // out width high
895 decoder->reg[REG_ADDR(0xce)] = LOBYTE(h); // out height low
896 decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f; // out height high
897
898 decoder->reg[REG_ADDR(0xb8)] =
899 LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
900 decoder->reg[REG_ADDR(0xb9)] =
901 HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
902 decoder->reg[REG_ADDR(0xba)] =
903 LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
904 decoder->reg[REG_ADDR(0xbb)] =
905 HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
906
907 decoder->reg[REG_ADDR(0xbc)] =
908 LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
909 decoder->reg[REG_ADDR(0xbd)] =
910 HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
911 decoder->reg[REG_ADDR(0xbe)] =
912 LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
913 decoder->reg[REG_ADDR(0xbf)] =
914 HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
915
916 decoder->reg[REG_ADDR(0xe8)] =
917 LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
918 decoder->reg[REG_ADDR(0xe9)] =
919 HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
920 decoder->reg[REG_ADDR(0xea)] =
921 LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
922 decoder->reg[REG_ADDR(0xeb)] =
923 HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
924
925 decoder->reg[REG_ADDR(0xec)] =
926 LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
927 decoder->reg[REG_ADDR(0xed)] =
928 HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
929 decoder->reg[REG_ADDR(0xee)] =
930 LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
931 decoder->reg[REG_ADDR(0xef)] =
932 HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
933
934
935 decoder->reg[REG_ADDR(0x13)] = 0x80; // RTC0 on
936 decoder->reg[REG_ADDR(0x87)] = 0x01; // I-Port
937 decoder->reg[REG_ADDR(0x12)] = 0xc9; // RTS0
938
939 decoder->reg[REG_ADDR(0x02)] = 0xc0; // set composite1 input, aveasy
940 decoder->reg[REG_ADDR(0x09)] = 0x00; // chrominance trap
941 decoder->reg[REG_ADDR(0x0e)] |= 1; // combfilter on
942
943
944 dprintk(1, KERN_DEBUG "%s_attach: starting decoder init\n",
945 I2C_NAME(client));
946
947 err[0] =
948 saa7114_write_block(client, decoder->reg + (0x20 << 1),
949 0x10 << 1);
950 err[1] =
951 saa7114_write_block(client, decoder->reg + (0x30 << 1),
952 0x10 << 1);
953 err[2] =
954 saa7114_write_block(client, decoder->reg + (0x63 << 1),
955 (0x7f + 1 - 0x63) << 1);
956 err[3] =
957 saa7114_write_block(client, decoder->reg + (0x89 << 1),
958 6 << 1);
959 err[4] =
960 saa7114_write_block(client, decoder->reg + (0xb8 << 1),
961 8 << 1);
962 err[5] =
963 saa7114_write_block(client, decoder->reg + (0xe8 << 1),
964 8 << 1);
965
966
967 for (i = 0; i <= 5; i++) {
968 if (err[i] < 0) {
969 dprintk(1,
970 KERN_ERR
971 "%s_attach: init error %d at stage %d, leaving attach.\n",
972 I2C_NAME(client), i, err[i]);
973 kfree(decoder);
974 kfree(client);
975 return 0;
976 }
977 }
978
979 for (i = 6; i < 8; i++) {
980 dprintk(1,
981 KERN_DEBUG
982 "%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n",
983 I2C_NAME(client), i, saa7114_read(client, i),
984 decoder->reg[REG_ADDR(i)]);
985 }
986
987 dprintk(1,
988 KERN_DEBUG
989 "%s_attach: performing decoder reset sequence\n",
990 I2C_NAME(client));
991
992 err[6] = saa7114_write(client, 0x80, 0x06); // i-port and scaler backend clock selection, task A&B off
993 err[7] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler
994 err[8] = saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
995
996 for (i = 6; i <= 8; i++) {
997 if (err[i] < 0) {
998 dprintk(1,
999 KERN_ERR
1000 "%s_attach: init error %d at stage %d, leaving attach.\n",
1001 I2C_NAME(client), i, err[i]);
1002 kfree(decoder);
1003 kfree(client);
1004 return 0;
1005 }
1006 }
1007
1008 dprintk(1, KERN_INFO "%s_attach: performing the rest of init\n",
1009 I2C_NAME(client));
1010
1011
1012 err[9] = saa7114_write(client, 0x01, decoder->reg[REG_ADDR(0x01)]);
1013 err[10] = saa7114_write_block(client, decoder->reg + (0x03 << 1), (0x1e + 1 - 0x03) << 1); // big seq
1014 err[11] = saa7114_write_block(client, decoder->reg + (0x40 << 1), (0x5f + 1 - 0x40) << 1); // slicer
1015 err[12] = saa7114_write_block(client, decoder->reg + (0x81 << 1), 2 << 1); // ?
1016 err[13] = saa7114_write_block(client, decoder->reg + (0x83 << 1), 5 << 1); // ?
1017 err[14] = saa7114_write_block(client, decoder->reg + (0x90 << 1), 4 << 1); // Task A
1018 err[15] =
1019 saa7114_write_block(client, decoder->reg + (0x94 << 1),
1020 12 << 1);
1021 err[16] =
1022 saa7114_write_block(client, decoder->reg + (0xa0 << 1),
1023 8 << 1);
1024 err[17] =
1025 saa7114_write_block(client, decoder->reg + (0xa8 << 1),
1026 8 << 1);
1027 err[18] =
1028 saa7114_write_block(client, decoder->reg + (0xb0 << 1),
1029 8 << 1);
1030 err[19] = saa7114_write_block(client, decoder->reg + (0xc0 << 1), 4 << 1); // Task B
1031 err[15] =
1032 saa7114_write_block(client, decoder->reg + (0xc4 << 1),
1033 12 << 1);
1034 err[16] =
1035 saa7114_write_block(client, decoder->reg + (0xd0 << 1),
1036 8 << 1);
1037 err[17] =
1038 saa7114_write_block(client, decoder->reg + (0xd8 << 1),
1039 8 << 1);
1040 err[18] =
1041 saa7114_write_block(client, decoder->reg + (0xe0 << 1),
1042 8 << 1);
1043
1044 for (i = 9; i <= 18; i++) {
1045 if (err[i] < 0) {
1046 dprintk(1,
1047 KERN_ERR
1048 "%s_attach: init error %d at stage %d, leaving attach.\n",
1049 I2C_NAME(client), i, err[i]);
1050 kfree(decoder);
1051 kfree(client);
1052 return 0;
1053 }
1054 }
1055
1056
1057 for (i = 6; i < 8; i++) {
1058 dprintk(1,
1059 KERN_DEBUG
1060 "%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n",
1061 I2C_NAME(client), i, saa7114_read(client, i),
1062 decoder->reg[REG_ADDR(i)]);
1063 }
1064
1065
1066 for (i = 0x11; i <= 0x13; i++) {
1067 dprintk(1,
1068 KERN_DEBUG
1069 "%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n",
1070 I2C_NAME(client), i, saa7114_read(client, i),
1071 decoder->reg[REG_ADDR(i)]);
1072 }
1073
1074
1075 dprintk(1, KERN_DEBUG "%s_attach: setting video input\n",
1076 I2C_NAME(client));
1077
1078 err[19] =
1079 saa7114_write(client, 0x02, decoder->reg[REG_ADDR(0x02)]);
1080 err[20] =
1081 saa7114_write(client, 0x09, decoder->reg[REG_ADDR(0x09)]);
1082 err[21] =
1083 saa7114_write(client, 0x0e, decoder->reg[REG_ADDR(0x0e)]);
1084
1085 for (i = 19; i <= 21; i++) {
1086 if (err[i] < 0) {
1087 dprintk(1,
1088 KERN_ERR
1089 "%s_attach: init error %d at stage %d, leaving attach.\n",
1090 I2C_NAME(client), i, err[i]);
1091 kfree(decoder);
1092 kfree(client);
1093 return 0;
1094 }
1095 }
1096
1097 dprintk(1,
1098 KERN_DEBUG
1099 "%s_attach: performing decoder reset sequence\n",
1100 I2C_NAME(client));
1101
1102 err[22] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler
1103 err[23] = saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
1104 err[24] = saa7114_write(client, 0x80, 0x36); // i-port and scaler backend clock selection, task A&B off
1105
1106
1107 for (i = 22; i <= 24; i++) {
1108 if (err[i] < 0) {
1109 dprintk(1,
1110 KERN_ERR
1111 "%s_attach: init error %d at stage %d, leaving attach.\n",
1112 I2C_NAME(client), i, err[i]);
1113 kfree(decoder);
1114 kfree(client);
1115 return 0;
1116 }
1117 }
1118
1119 err[25] = saa7114_write(client, 0x06, init[REG_ADDR(0x06)]);
1120 err[26] = saa7114_write(client, 0x07, init[REG_ADDR(0x07)]);
1121 err[27] = saa7114_write(client, 0x10, init[REG_ADDR(0x10)]);
1122
1123 dprintk(1,
1124 KERN_INFO
1125 "%s_attach: chip version %x, decoder status 0x%02x\n",
1126 I2C_NAME(client), saa7114_read(client, 0x00) >> 4,
1127 saa7114_read(client, 0x1f));
1128 dprintk(1,
1129 KERN_DEBUG
1130 "%s_attach: power save control: 0x%02x, scaler status: 0x%02x\n",
1131 I2C_NAME(client), saa7114_read(client, 0x88),
1132 saa7114_read(client, 0x8f));
1133
1134
1135 for (i = 0x94; i < 0x96; i++) {
1136 dprintk(1,
1137 KERN_DEBUG
1138 "%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n",
1139 I2C_NAME(client), i, saa7114_read(client, i),
1140 decoder->reg[REG_ADDR(i)]);
1141 }
1142
1143 i = i2c_attach_client(client);
1144 if (i) {
1145 kfree(client);
1146 kfree(decoder);
1147 return i;
1148 }
1149
1150 //i = saa7114_write_block(client, init, sizeof(init));
1151 i = 0;
1152 if (i < 0) {
1153 dprintk(1, KERN_ERR "%s_attach error: init status %d\n",
1154 I2C_NAME(client), i);
1155 } else {
1156 dprintk(1,
1157 KERN_INFO
1158 "%s_attach: chip version %x at address 0x%x\n",
1159 I2C_NAME(client), saa7114_read(client, 0x00) >> 4,
1160 client->addr << 1);
1161 }
1162
1163 return 0;
1164}
1165
1166static int
1167saa7114_attach_adapter (struct i2c_adapter *adapter)
1168{
1169 dprintk(1,
1170 KERN_INFO
1171 "saa7114.c: starting probe for adapter %s (0x%x)\n",
1172 I2C_NAME(adapter), adapter->id);
1173 return i2c_probe(adapter, &addr_data, &saa7114_detect_client);
1174}
1175
1176static int
1177saa7114_detach_client (struct i2c_client *client)
1178{
1179 struct saa7114 *decoder = i2c_get_clientdata(client);
1180 int err;
1181
1182 err = i2c_detach_client(client);
1183 if (err) {
1184 return err;
1185 }
1186
1187 kfree(decoder);
1188 kfree(client);
1189
1190 return 0;
1191}
1192
1193/* ----------------------------------------------------------------------- */
1194
1195static struct i2c_driver i2c_driver_saa7114 = {
604f28e2 1196 .driver = {
604f28e2
LR
1197 .name = "saa7114",
1198 },
1da177e4
LT
1199
1200 .id = I2C_DRIVERID_SAA7114,
1da177e4
LT
1201
1202 .attach_adapter = saa7114_attach_adapter,
1203 .detach_client = saa7114_detach_client,
1204 .command = saa7114_command,
1205};
1206
1207static int __init
1208saa7114_init (void)
1209{
1210 return i2c_add_driver(&i2c_driver_saa7114);
1211}
1212
1213static void __exit
1214saa7114_exit (void)
1215{
1216 i2c_del_driver(&i2c_driver_saa7114);
1217}
1218
1219module_init(saa7114_init);
1220module_exit(saa7114_exit);
This page took 0.193815 seconds and 5 git commands to generate.