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