2 * bt819 - BT819A VideoStream Decoder (Rockwell Part)
4 * Copyright (C) 1999 Mike Bernson <mike@mlb.org>
5 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
7 * Modifications for LML33/DC10plus unified driver
8 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
10 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
11 * - moved over to linux>=2.4.x i2c protocol (9/9/2002)
13 * This code was modify/ported from the saa7111 driver written
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.
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.
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.
31 #include <linux/module.h>
32 #include <linux/init.h>
33 #include <linux/delay.h>
34 #include <linux/errno.h>
36 #include <linux/kernel.h>
37 #include <linux/major.h>
38 #include <linux/slab.h>
40 #include <linux/pci.h>
41 #include <linux/signal.h>
43 #include <asm/pgtable.h>
45 #include <linux/sched.h>
46 #include <linux/types.h>
48 #include <linux/videodev.h>
49 #include <asm/uaccess.h>
51 MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
52 MODULE_AUTHOR("Mike Bernson & Dave Perks");
53 MODULE_LICENSE("GPL");
55 #include <linux/i2c.h>
57 #define I2C_NAME(s) (s)->name
59 #include <linux/video_decoder.h>
62 module_param(debug
, int, 0);
63 MODULE_PARM_DESC(debug
, "Debug level (0-1)");
65 #define dprintk(num, format, args...) \
68 printk(format, ##args); \
71 /* ----------------------------------------------------------------------- */
74 unsigned char reg
[32];
95 /* for values, see the bt819 datasheet */
96 static struct timing timing_data
[] = {
97 {864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
98 {858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
101 #define I2C_BT819 0x8a
103 /* ----------------------------------------------------------------------- */
106 bt819_write (struct i2c_client
*client
,
110 struct bt819
*decoder
= i2c_get_clientdata(client
);
112 decoder
->reg
[reg
] = value
;
113 return i2c_smbus_write_byte_data(client
, reg
, value
);
117 bt819_setbit (struct i2c_client
*client
,
122 struct bt819
*decoder
= i2c_get_clientdata(client
);
124 return bt819_write(client
, reg
,
126 reg
[reg
] & ~(1 << bit
)) |
127 (value
? (1 << bit
) : 0));
131 bt819_write_block (struct i2c_client
*client
,
138 /* the bt819 has an autoincrement function, use it if
139 * the adapter understands raw I2C */
140 if (i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
)) {
141 /* do raw I2C, not smbus compatible */
142 struct bt819
*decoder
= i2c_get_clientdata(client
);
148 block_data
[block_len
++] = reg
= data
[0];
150 block_data
[block_len
++] =
151 decoder
->reg
[reg
++] = data
[1];
154 } while (len
>= 2 && data
[0] == reg
&&
156 if ((ret
= i2c_master_send(client
, block_data
,
161 /* do some slow I2C emulation kind of thing */
164 if ((ret
= bt819_write(client
, reg
, *data
++)) < 0)
174 bt819_read (struct i2c_client
*client
,
177 return i2c_smbus_read_byte_data(client
, reg
);
181 bt819_init (struct i2c_client
*client
)
183 struct bt819
*decoder
= i2c_get_clientdata(client
);
185 static unsigned char init
[] = {
186 //0x1f, 0x00, /* Reset */
187 0x01, 0x59, /* 0x01 input format */
188 0x02, 0x00, /* 0x02 temporal decimation */
189 0x03, 0x12, /* 0x03 Cropping msb */
190 0x04, 0x16, /* 0x04 Vertical Delay, lsb */
191 0x05, 0xe0, /* 0x05 Vertical Active lsb */
192 0x06, 0x80, /* 0x06 Horizontal Delay lsb */
193 0x07, 0xd0, /* 0x07 Horizontal Active lsb */
194 0x08, 0x00, /* 0x08 Horizontal Scaling msb */
195 0x09, 0xf8, /* 0x09 Horizontal Scaling lsb */
196 0x0a, 0x00, /* 0x0a Brightness control */
197 0x0b, 0x30, /* 0x0b Miscellaneous control */
198 0x0c, 0xd8, /* 0x0c Luma Gain lsb */
199 0x0d, 0xfe, /* 0x0d Chroma Gain (U) lsb */
200 0x0e, 0xb4, /* 0x0e Chroma Gain (V) msb */
201 0x0f, 0x00, /* 0x0f Hue control */
202 0x12, 0x04, /* 0x12 Output Format */
203 0x13, 0x20, /* 0x13 Vertial Scaling msb 0x00
204 chroma comb OFF, line drop scaling, interlace scaling
205 BUG? Why does turning the chroma comb on fuck up color?
206 Bug in the bt819 stepping on my board?
208 0x14, 0x00, /* 0x14 Vertial Scaling lsb */
209 0x16, 0x07, /* 0x16 Video Timing Polarity
213 hreset=active high */
214 0x18, 0x68, /* 0x18 AGC Delay */
215 0x19, 0x5d, /* 0x19 Burst Gate Delay */
216 0x1a, 0x80, /* 0x1a ADC Interface */
219 struct timing
*timing
= &timing_data
[decoder
->norm
];
222 (((timing
->vdelay
>> 8) & 0x03) << 6) | (((timing
->
225 (((timing
->hdelay
>> 8) & 0x03) << 2) | ((timing
->
228 init
[0x04 * 2 - 1] = timing
->vdelay
& 0xff;
229 init
[0x05 * 2 - 1] = timing
->vactive
& 0xff;
230 init
[0x06 * 2 - 1] = timing
->hdelay
& 0xff;
231 init
[0x07 * 2 - 1] = timing
->hactive
& 0xff;
232 init
[0x08 * 2 - 1] = timing
->hscale
>> 8;
233 init
[0x09 * 2 - 1] = timing
->hscale
& 0xff;
234 /* 0x15 in array is address 0x19 */
235 init
[0x15 * 2 - 1] = (decoder
->norm
== 0) ? 115 : 93; /* Chroma burst delay */
237 bt819_write(client
, 0x1f, 0x00);
241 return bt819_write_block(client
, init
, sizeof(init
));
245 /* ----------------------------------------------------------------------- */
248 bt819_command (struct i2c_client
*client
,
254 struct bt819
*decoder
= i2c_get_clientdata(client
);
256 if (!decoder
->initialized
) { // First call to bt819_init could be
257 bt819_init(client
); // without #FRST = 0
258 decoder
->initialized
= 1;
264 /* This is just for testing!!! */
268 case DECODER_GET_CAPABILITIES
:
270 struct video_decoder_capability
*cap
= arg
;
272 cap
->flags
= VIDEO_DECODER_PAL
|
281 case DECODER_GET_STATUS
:
287 status
= bt819_read(client
, 0x00);
289 if ((status
& 0x80)) {
290 res
|= DECODER_STATUS_GOOD
;
292 switch (decoder
->norm
) {
293 case VIDEO_MODE_NTSC
:
294 res
|= DECODER_STATUS_NTSC
;
297 res
|= DECODER_STATUS_PAL
;
300 case VIDEO_MODE_AUTO
:
301 if ((status
& 0x10)) {
302 res
|= DECODER_STATUS_PAL
;
304 res
|= DECODER_STATUS_NTSC
;
308 res
|= DECODER_STATUS_COLOR
;
311 dprintk(1, KERN_INFO
"%s: get status %x\n", I2C_NAME(client
),
316 case DECODER_SET_NORM
:
319 struct timing
*timing
= NULL
;
321 dprintk(1, KERN_INFO
"%s: set norm %x\n", I2C_NAME(client
),
325 case VIDEO_MODE_NTSC
:
326 bt819_setbit(client
, 0x01, 0, 1);
327 bt819_setbit(client
, 0x01, 1, 0);
328 bt819_setbit(client
, 0x01, 5, 0);
329 bt819_write(client
, 0x18, 0x68);
330 bt819_write(client
, 0x19, 0x5d);
331 //bt819_setbit(client, 0x1a, 5, 1);
332 timing
= &timing_data
[VIDEO_MODE_NTSC
];
335 bt819_setbit(client
, 0x01, 0, 1);
336 bt819_setbit(client
, 0x01, 1, 1);
337 bt819_setbit(client
, 0x01, 5, 1);
338 bt819_write(client
, 0x18, 0x7f);
339 bt819_write(client
, 0x19, 0x72);
340 //bt819_setbit(client, 0x1a, 5, 0);
341 timing
= &timing_data
[VIDEO_MODE_PAL
];
343 case VIDEO_MODE_AUTO
:
344 bt819_setbit(client
, 0x01, 0, 0);
345 bt819_setbit(client
, 0x01, 1, 0);
350 "%s: unsupported norm %d\n",
351 I2C_NAME(client
), *iarg
);
356 bt819_write(client
, 0x03,
357 (((timing
->vdelay
>> 8) & 0x03) << 6) |
358 (((timing
->vactive
>> 8) & 0x03) << 4) |
359 (((timing
->hdelay
>> 8) & 0x03) << 2) |
360 ((timing
->hactive
>> 8) & 0x03) );
361 bt819_write(client
, 0x04, timing
->vdelay
& 0xff);
362 bt819_write(client
, 0x05, timing
->vactive
& 0xff);
363 bt819_write(client
, 0x06, timing
->hdelay
& 0xff);
364 bt819_write(client
, 0x07, timing
->hactive
& 0xff);
365 bt819_write(client
, 0x08, (timing
->hscale
>> 8) & 0xff);
366 bt819_write(client
, 0x09, timing
->hscale
& 0xff);
369 decoder
->norm
= *iarg
;
373 case DECODER_SET_INPUT
:
377 dprintk(1, KERN_INFO
"%s: set input %x\n", I2C_NAME(client
),
380 if (*iarg
< 0 || *iarg
> 7) {
384 if (decoder
->input
!= *iarg
) {
385 decoder
->input
= *iarg
;
387 if (decoder
->input
== 0) {
388 bt819_setbit(client
, 0x0b, 6, 0);
389 bt819_setbit(client
, 0x1a, 1, 1);
391 bt819_setbit(client
, 0x0b, 6, 1);
392 bt819_setbit(client
, 0x1a, 1, 0);
398 case DECODER_SET_OUTPUT
:
402 dprintk(1, KERN_INFO
"%s: set output %x\n", I2C_NAME(client
),
405 /* not much choice of outputs */
412 case DECODER_ENABLE_OUTPUT
:
415 int enable
= (*iarg
!= 0);
417 dprintk(1, KERN_INFO
"%s: enable output %x\n",
418 I2C_NAME(client
), *iarg
);
420 if (decoder
->enable
!= enable
) {
421 decoder
->enable
= enable
;
423 if (decoder
->enable
) {
424 bt819_setbit(client
, 0x16, 7, 0);
426 bt819_setbit(client
, 0x16, 7, 1);
432 case DECODER_SET_PICTURE
:
434 struct video_picture
*pic
= arg
;
438 "%s: set picture brightness %d contrast %d colour %d\n",
439 I2C_NAME(client
), pic
->brightness
, pic
->contrast
,
443 if (decoder
->bright
!= pic
->brightness
) {
444 /* We want -128 to 127 we get 0-65535 */
445 decoder
->bright
= pic
->brightness
;
446 bt819_write(client
, 0x0a,
447 (decoder
->bright
>> 8) - 128);
450 if (decoder
->contrast
!= pic
->contrast
) {
451 /* We want 0 to 511 we get 0-65535 */
452 decoder
->contrast
= pic
->contrast
;
453 bt819_write(client
, 0x0c,
454 (decoder
->contrast
>> 7) & 0xff);
455 bt819_setbit(client
, 0x0b, 2,
456 ((decoder
->contrast
>> 15) & 0x01));
459 if (decoder
->sat
!= pic
->colour
) {
460 /* We want 0 to 511 we get 0-65535 */
461 decoder
->sat
= pic
->colour
;
462 bt819_write(client
, 0x0d,
463 (decoder
->sat
>> 7) & 0xff);
464 bt819_setbit(client
, 0x0b, 1,
465 ((decoder
->sat
>> 15) & 0x01));
467 temp
= (decoder
->sat
* 201) / 237;
468 bt819_write(client
, 0x0e, (temp
>> 7) & 0xff);
469 bt819_setbit(client
, 0x0b, 0, (temp
>> 15) & 0x01);
472 if (decoder
->hue
!= pic
->hue
) {
473 /* We want -128 to 127 we get 0-65535 */
474 decoder
->hue
= pic
->hue
;
475 bt819_write(client
, 0x0f,
476 128 - (decoder
->hue
>> 8));
488 /* ----------------------------------------------------------------------- */
492 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
494 static unsigned short normal_i2c
[] = {
499 static unsigned short ignore
= I2C_CLIENT_END
;
501 static struct i2c_client_address_data addr_data
= {
502 .normal_i2c
= normal_i2c
,
507 static struct i2c_driver i2c_driver_bt819
;
510 bt819_detect_client (struct i2c_adapter
*adapter
,
515 struct bt819
*decoder
;
516 struct i2c_client
*client
;
520 "saa7111.c: detecting bt819 client on address 0x%x\n",
523 /* Check if the adapter supports the needed features */
524 if (!i2c_check_functionality(adapter
, I2C_FUNC_SMBUS_BYTE_DATA
))
527 client
= kzalloc(sizeof(struct i2c_client
), GFP_KERNEL
);
530 client
->addr
= address
;
531 client
->adapter
= adapter
;
532 client
->driver
= &i2c_driver_bt819
;
534 decoder
= kzalloc(sizeof(struct bt819
), GFP_KERNEL
);
535 if (decoder
== NULL
) {
539 decoder
->norm
= VIDEO_MODE_NTSC
;
542 decoder
->bright
= 32768;
543 decoder
->contrast
= 32768;
544 decoder
->hue
= 32768;
545 decoder
->sat
= 32768;
546 decoder
->initialized
= 0;
547 i2c_set_clientdata(client
, decoder
);
549 id
= bt819_read(client
, 0x17);
552 strlcpy(I2C_NAME(client
), "bt819a", sizeof(I2C_NAME(client
)));
555 strlcpy(I2C_NAME(client
), "bt817a", sizeof(I2C_NAME(client
)));
558 strlcpy(I2C_NAME(client
), "bt815a", sizeof(I2C_NAME(client
)));
563 "bt819: unknown chip version 0x%x (ver 0x%x)\n",
564 id
& 0xf0, id
& 0x0f);
570 i
= i2c_attach_client(client
);
577 i
= bt819_init(client
);
579 dprintk(1, KERN_ERR
"%s_attach: init status %d\n",
580 I2C_NAME(client
), i
);
584 "%s_attach: chip version 0x%x at address 0x%x\n",
585 I2C_NAME(client
), id
& 0x0f,
593 bt819_attach_adapter (struct i2c_adapter
*adapter
)
595 return i2c_probe(adapter
, &addr_data
, &bt819_detect_client
);
599 bt819_detach_client (struct i2c_client
*client
)
601 struct bt819
*decoder
= i2c_get_clientdata(client
);
604 err
= i2c_detach_client(client
);
615 /* ----------------------------------------------------------------------- */
617 static struct i2c_driver i2c_driver_bt819
= {
622 .id
= I2C_DRIVERID_BT819
,
624 .attach_adapter
= bt819_attach_adapter
,
625 .detach_client
= bt819_detach_client
,
626 .command
= bt819_command
,
630 bt819_init_module (void)
632 return i2c_add_driver(&i2c_driver_bt819
);
638 i2c_del_driver(&i2c_driver_bt819
);
641 module_init(bt819_init_module
);
642 module_exit(bt819_exit
);