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