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