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 <asm/segment.h>
47 #include <linux/types.h>
49 #include <linux/videodev.h>
50 #include <asm/uaccess.h>
52 MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
53 MODULE_AUTHOR("Mike Bernson & Dave Perks");
54 MODULE_LICENSE("GPL");
56 #include <linux/i2c.h>
57 #include <linux/i2c-dev.h>
59 #define I2C_NAME(s) (s)->name
61 #include <linux/video_decoder.h>
64 module_param(debug, int, 0);
65 MODULE_PARM_DESC(debug, "Debug level (0-1)");
67 #define dprintk(num, format, args...) \
70 printk(format, ##args); \
73 /* ----------------------------------------------------------------------- */
76 unsigned char reg[32];
97 /* for values, see the bt819 datasheet */
98 static struct timing timing_data[] = {
99 {864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
100 {858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
103 #define I2C_BT819 0x8a
105 /* ----------------------------------------------------------------------- */
108 bt819_write (struct i2c_client *client,
112 struct bt819 *decoder = i2c_get_clientdata(client);
114 decoder->reg[reg] = value;
115 return i2c_smbus_write_byte_data(client, reg, value);
119 bt819_setbit (struct i2c_client *client,
124 struct bt819 *decoder = i2c_get_clientdata(client);
126 return bt819_write(client, reg,
128 reg[reg] & ~(1 << bit)) |
129 (value ? (1 << bit) : 0));
133 bt819_write_block (struct i2c_client *client,
140 /* the bt819 has an autoincrement function, use it if
141 * the adapter understands raw I2C */
142 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
143 /* do raw I2C, not smbus compatible */
144 struct bt819 *decoder = i2c_get_clientdata(client);
148 msg.addr = client->addr;
151 msg.buf = (char *) block_data;
153 block_data[msg.len++] = reg = data[0];
155 block_data[msg.len++] =
156 decoder->reg[reg++] = data[1];
159 } while (len >= 2 && data[0] == reg &&
161 if ((ret = i2c_transfer(client->adapter,
166 /* do some slow I2C emulation kind of thing */
169 if ((ret = bt819_write(client, reg, *data++)) < 0)
179 bt819_read (struct i2c_client *client,
182 return i2c_smbus_read_byte_data(client, reg);
186 bt819_init (struct i2c_client *client)
188 struct bt819 *decoder = i2c_get_clientdata(client);
190 static unsigned char init[] = {
191 //0x1f, 0x00, /* Reset */
192 0x01, 0x59, /* 0x01 input format */
193 0x02, 0x00, /* 0x02 temporal decimation */
194 0x03, 0x12, /* 0x03 Cropping msb */
195 0x04, 0x16, /* 0x04 Vertical Delay, lsb */
196 0x05, 0xe0, /* 0x05 Vertical Active lsb */
197 0x06, 0x80, /* 0x06 Horizontal Delay lsb */
198 0x07, 0xd0, /* 0x07 Horizontal Active lsb */
199 0x08, 0x00, /* 0x08 Horizontal Scaling msb */
200 0x09, 0xf8, /* 0x09 Horizontal Scaling lsb */
201 0x0a, 0x00, /* 0x0a Brightness control */
202 0x0b, 0x30, /* 0x0b Miscellaneous control */
203 0x0c, 0xd8, /* 0x0c Luma Gain lsb */
204 0x0d, 0xfe, /* 0x0d Chroma Gain (U) lsb */
205 0x0e, 0xb4, /* 0x0e Chroma Gain (V) msb */
206 0x0f, 0x00, /* 0x0f Hue control */
207 0x12, 0x04, /* 0x12 Output Format */
208 0x13, 0x20, /* 0x13 Vertial Scaling msb 0x00
209 chroma comb OFF, line drop scaling, interlace scaling
210 BUG? Why does turning the chroma comb on fuck up color?
211 Bug in the bt819 stepping on my board?
213 0x14, 0x00, /* 0x14 Vertial Scaling lsb */
214 0x16, 0x07, /* 0x16 Video Timing Polarity
218 hreset=active high */
219 0x18, 0x68, /* 0x18 AGC Delay */
220 0x19, 0x5d, /* 0x19 Burst Gate Delay */
221 0x1a, 0x80, /* 0x1a ADC Interface */
224 struct timing *timing = &timing_data[decoder->norm];
227 (((timing->vdelay >> 8) & 0x03) << 6) | (((timing->
230 (((timing->hdelay >> 8) & 0x03) << 2) | ((timing->
233 init[0x04 * 2 - 1] = timing->vdelay & 0xff;
234 init[0x05 * 2 - 1] = timing->vactive & 0xff;
235 init[0x06 * 2 - 1] = timing->hdelay & 0xff;
236 init[0x07 * 2 - 1] = timing->hactive & 0xff;
237 init[0x08 * 2 - 1] = timing->hscale >> 8;
238 init[0x09 * 2 - 1] = timing->hscale & 0xff;
239 /* 0x15 in array is address 0x19 */
240 init[0x15 * 2 - 1] = (decoder->norm == 0) ? 115 : 93; /* Chroma burst delay */
242 bt819_write(client, 0x1f, 0x00);
246 return bt819_write_block(client, init, sizeof(init));
250 /* ----------------------------------------------------------------------- */
253 bt819_command (struct i2c_client *client,
259 struct bt819 *decoder = i2c_get_clientdata(client);
261 if (!decoder->initialized) { // First call to bt819_init could be
262 bt819_init(client); // without #FRST = 0
263 decoder->initialized = 1;
269 /* This is just for testing!!! */
273 case DECODER_GET_CAPABILITIES:
275 struct video_decoder_capability *cap = arg;
277 cap->flags = VIDEO_DECODER_PAL |
286 case DECODER_GET_STATUS:
292 status = bt819_read(client, 0x00);
294 if ((status & 0x80)) {
295 res |= DECODER_STATUS_GOOD;
297 switch (decoder->norm) {
298 case VIDEO_MODE_NTSC:
299 res |= DECODER_STATUS_NTSC;
302 res |= DECODER_STATUS_PAL;
305 case VIDEO_MODE_AUTO:
306 if ((status & 0x10)) {
307 res |= DECODER_STATUS_PAL;
309 res |= DECODER_STATUS_NTSC;
313 res |= DECODER_STATUS_COLOR;
316 dprintk(1, KERN_INFO "%s: get status %x\n", I2C_NAME(client),
321 case DECODER_SET_NORM:
324 struct timing *timing = NULL;
326 dprintk(1, KERN_INFO "%s: set norm %x\n", I2C_NAME(client),
330 case VIDEO_MODE_NTSC:
331 bt819_setbit(client, 0x01, 0, 1);
332 bt819_setbit(client, 0x01, 1, 0);
333 bt819_setbit(client, 0x01, 5, 0);
334 bt819_write(client, 0x18, 0x68);
335 bt819_write(client, 0x19, 0x5d);
336 //bt819_setbit(client, 0x1a, 5, 1);
337 timing = &timing_data[VIDEO_MODE_NTSC];
340 bt819_setbit(client, 0x01, 0, 1);
341 bt819_setbit(client, 0x01, 1, 1);
342 bt819_setbit(client, 0x01, 5, 1);
343 bt819_write(client, 0x18, 0x7f);
344 bt819_write(client, 0x19, 0x72);
345 //bt819_setbit(client, 0x1a, 5, 0);
346 timing = &timing_data[VIDEO_MODE_PAL];
348 case VIDEO_MODE_AUTO:
349 bt819_setbit(client, 0x01, 0, 0);
350 bt819_setbit(client, 0x01, 1, 0);
355 "%s: unsupported norm %d\n",
356 I2C_NAME(client), *iarg);
361 bt819_write(client, 0x03,
362 (((timing->vdelay >> 8) & 0x03) << 6) |
363 (((timing->vactive >> 8) & 0x03) << 4) |
364 (((timing->hdelay >> 8) & 0x03) << 2) |
365 ((timing->hactive >> 8) & 0x03) );
366 bt819_write(client, 0x04, timing->vdelay & 0xff);
367 bt819_write(client, 0x05, timing->vactive & 0xff);
368 bt819_write(client, 0x06, timing->hdelay & 0xff);
369 bt819_write(client, 0x07, timing->hactive & 0xff);
370 bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff);
371 bt819_write(client, 0x09, timing->hscale & 0xff);
374 decoder->norm = *iarg;
378 case DECODER_SET_INPUT:
382 dprintk(1, KERN_INFO "%s: set input %x\n", I2C_NAME(client),
385 if (*iarg < 0 || *iarg > 7) {
389 if (decoder->input != *iarg) {
390 decoder->input = *iarg;
392 if (decoder->input == 0) {
393 bt819_setbit(client, 0x0b, 6, 0);
394 bt819_setbit(client, 0x1a, 1, 1);
396 bt819_setbit(client, 0x0b, 6, 1);
397 bt819_setbit(client, 0x1a, 1, 0);
403 case DECODER_SET_OUTPUT:
407 dprintk(1, KERN_INFO "%s: set output %x\n", I2C_NAME(client),
410 /* not much choice of outputs */
417 case DECODER_ENABLE_OUTPUT:
420 int enable = (*iarg != 0);
422 dprintk(1, KERN_INFO "%s: enable output %x\n",
423 I2C_NAME(client), *iarg);
425 if (decoder->enable != enable) {
426 decoder->enable = enable;
428 if (decoder->enable) {
429 bt819_setbit(client, 0x16, 7, 0);
431 bt819_setbit(client, 0x16, 7, 1);
437 case DECODER_SET_PICTURE:
439 struct video_picture *pic = arg;
443 "%s: set picture brightness %d contrast %d colour %d\n",
444 I2C_NAME(client), pic->brightness, pic->contrast,
448 if (decoder->bright != pic->brightness) {
449 /* We want -128 to 127 we get 0-65535 */
450 decoder->bright = pic->brightness;
451 bt819_write(client, 0x0a,
452 (decoder->bright >> 8) - 128);
455 if (decoder->contrast != pic->contrast) {
456 /* We want 0 to 511 we get 0-65535 */
457 decoder->contrast = pic->contrast;
458 bt819_write(client, 0x0c,
459 (decoder->contrast >> 7) & 0xff);
460 bt819_setbit(client, 0x0b, 2,
461 ((decoder->contrast >> 15) & 0x01));
464 if (decoder->sat != pic->colour) {
465 /* We want 0 to 511 we get 0-65535 */
466 decoder->sat = pic->colour;
467 bt819_write(client, 0x0d,
468 (decoder->sat >> 7) & 0xff);
469 bt819_setbit(client, 0x0b, 1,
470 ((decoder->sat >> 15) & 0x01));
472 temp = (decoder->sat * 201) / 237;
473 bt819_write(client, 0x0e, (temp >> 7) & 0xff);
474 bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01);
477 if (decoder->hue != pic->hue) {
478 /* We want -128 to 127 we get 0-65535 */
479 decoder->hue = pic->hue;
480 bt819_write(client, 0x0f,
481 128 - (decoder->hue >> 8));
493 /* ----------------------------------------------------------------------- */
497 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
499 static unsigned short normal_i2c[] = {
504 static unsigned short ignore = I2C_CLIENT_END;
506 static struct i2c_client_address_data addr_data = {
507 .normal_i2c = normal_i2c,
513 static struct i2c_driver i2c_driver_bt819;
516 bt819_detect_client (struct i2c_adapter *adapter,
521 struct bt819 *decoder;
522 struct i2c_client *client;
526 "saa7111.c: detecting bt819 client on address 0x%x\n",
529 /* Check if the adapter supports the needed features */
530 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
533 client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
536 memset(client, 0, sizeof(struct i2c_client));
537 client->addr = address;
538 client->adapter = adapter;
539 client->driver = &i2c_driver_bt819;
540 client->flags = I2C_CLIENT_ALLOW_USE;
542 decoder = kmalloc(sizeof(struct bt819), GFP_KERNEL);
543 if (decoder == NULL) {
548 memset(decoder, 0, sizeof(struct bt819));
549 decoder->norm = VIDEO_MODE_NTSC;
552 decoder->bright = 32768;
553 decoder->contrast = 32768;
554 decoder->hue = 32768;
555 decoder->sat = 32768;
556 decoder->initialized = 0;
557 i2c_set_clientdata(client, decoder);
559 id = bt819_read(client, 0x17);
562 strlcpy(I2C_NAME(client), "bt819a", sizeof(I2C_NAME(client)));
565 strlcpy(I2C_NAME(client), "bt817a", sizeof(I2C_NAME(client)));
568 strlcpy(I2C_NAME(client), "bt815a", sizeof(I2C_NAME(client)));
573 "bt819: unknown chip version 0x%x (ver 0x%x)\n",
574 id & 0xf0, id & 0x0f);
580 i = i2c_attach_client(client);
587 i = bt819_init(client);
589 dprintk(1, KERN_ERR "%s_attach: init status %d\n",
590 I2C_NAME(client), i);
594 "%s_attach: chip version 0x%x at address 0x%x\n",
595 I2C_NAME(client), id & 0x0f,
603 bt819_attach_adapter (struct i2c_adapter *adapter)
605 return i2c_probe(adapter, &addr_data, &bt819_detect_client);
609 bt819_detach_client (struct i2c_client *client)
611 struct bt819 *decoder = i2c_get_clientdata(client);
614 err = i2c_detach_client(client);
625 /* ----------------------------------------------------------------------- */
627 static struct i2c_driver i2c_driver_bt819 = {
628 .owner = THIS_MODULE,
631 .id = I2C_DRIVERID_BT819,
632 .flags = I2C_DF_NOTIFY,
634 .attach_adapter = bt819_attach_adapter,
635 .detach_client = bt819_detach_client,
636 .command = bt819_command,
640 bt819_init_module (void)
642 return i2c_add_driver(&i2c_driver_bt819);
648 i2c_del_driver(&i2c_driver_bt819);
651 module_init(bt819_init_module);
652 module_exit(bt819_exit);