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