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