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