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>
56 #include <linux/i2c-dev.h>
58 #define I2C_NAME(s) (s)->name
60 #include <linux/video_decoder.h>
63 module_param(debug, int, 0);
64 MODULE_PARM_DESC(debug, "Debug level (0-1)");
66 #define dprintk(num, format, args...) \
69 printk(format, ##args); \
72 /* ----------------------------------------------------------------------- */
75 unsigned char reg[32];
96 /* for values, see the bt819 datasheet */
97 static struct timing timing_data[] = {
98 {864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
99 {858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
102 #define I2C_BT819 0x8a
104 /* ----------------------------------------------------------------------- */
107 bt819_write (struct i2c_client *client,
111 struct bt819 *decoder = i2c_get_clientdata(client);
113 decoder->reg[reg] = value;
114 return i2c_smbus_write_byte_data(client, reg, value);
118 bt819_setbit (struct i2c_client *client,
123 struct bt819 *decoder = i2c_get_clientdata(client);
125 return bt819_write(client, reg,
127 reg[reg] & ~(1 << bit)) |
128 (value ? (1 << bit) : 0));
132 bt819_write_block (struct i2c_client *client,
139 /* the bt819 has an autoincrement function, use it if
140 * the adapter understands raw I2C */
141 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
142 /* do raw I2C, not smbus compatible */
143 struct bt819 *decoder = i2c_get_clientdata(client);
147 msg.addr = client->addr;
150 msg.buf = (char *) block_data;
152 block_data[msg.len++] = reg = data[0];
154 block_data[msg.len++] =
155 decoder->reg[reg++] = data[1];
158 } while (len >= 2 && data[0] == reg &&
160 if ((ret = i2c_transfer(client->adapter,
165 /* do some slow I2C emulation kind of thing */
168 if ((ret = bt819_write(client, reg, *data++)) < 0)
178 bt819_read (struct i2c_client *client,
181 return i2c_smbus_read_byte_data(client, reg);
185 bt819_init (struct i2c_client *client)
187 struct bt819 *decoder = i2c_get_clientdata(client);
189 static unsigned char init[] = {
190 //0x1f, 0x00, /* Reset */
191 0x01, 0x59, /* 0x01 input format */
192 0x02, 0x00, /* 0x02 temporal decimation */
193 0x03, 0x12, /* 0x03 Cropping msb */
194 0x04, 0x16, /* 0x04 Vertical Delay, lsb */
195 0x05, 0xe0, /* 0x05 Vertical Active lsb */
196 0x06, 0x80, /* 0x06 Horizontal Delay lsb */
197 0x07, 0xd0, /* 0x07 Horizontal Active lsb */
198 0x08, 0x00, /* 0x08 Horizontal Scaling msb */
199 0x09, 0xf8, /* 0x09 Horizontal Scaling lsb */
200 0x0a, 0x00, /* 0x0a Brightness control */
201 0x0b, 0x30, /* 0x0b Miscellaneous control */
202 0x0c, 0xd8, /* 0x0c Luma Gain lsb */
203 0x0d, 0xfe, /* 0x0d Chroma Gain (U) lsb */
204 0x0e, 0xb4, /* 0x0e Chroma Gain (V) msb */
205 0x0f, 0x00, /* 0x0f Hue control */
206 0x12, 0x04, /* 0x12 Output Format */
207 0x13, 0x20, /* 0x13 Vertial Scaling msb 0x00
208 chroma comb OFF, line drop scaling, interlace scaling
209 BUG? Why does turning the chroma comb on fuck up color?
210 Bug in the bt819 stepping on my board?
212 0x14, 0x00, /* 0x14 Vertial Scaling lsb */
213 0x16, 0x07, /* 0x16 Video Timing Polarity
217 hreset=active high */
218 0x18, 0x68, /* 0x18 AGC Delay */
219 0x19, 0x5d, /* 0x19 Burst Gate Delay */
220 0x1a, 0x80, /* 0x1a ADC Interface */
223 struct timing *timing = &timing_data[decoder->norm];
226 (((timing->vdelay >> 8) & 0x03) << 6) | (((timing->
229 (((timing->hdelay >> 8) & 0x03) << 2) | ((timing->
232 init[0x04 * 2 - 1] = timing->vdelay & 0xff;
233 init[0x05 * 2 - 1] = timing->vactive & 0xff;
234 init[0x06 * 2 - 1] = timing->hdelay & 0xff;
235 init[0x07 * 2 - 1] = timing->hactive & 0xff;
236 init[0x08 * 2 - 1] = timing->hscale >> 8;
237 init[0x09 * 2 - 1] = timing->hscale & 0xff;
238 /* 0x15 in array is address 0x19 */
239 init[0x15 * 2 - 1] = (decoder->norm == 0) ? 115 : 93; /* Chroma burst delay */
241 bt819_write(client, 0x1f, 0x00);
245 return bt819_write_block(client, init, sizeof(init));
249 /* ----------------------------------------------------------------------- */
252 bt819_command (struct i2c_client *client,
258 struct bt819 *decoder = i2c_get_clientdata(client);
260 if (!decoder->initialized) { // First call to bt819_init could be
261 bt819_init(client); // without #FRST = 0
262 decoder->initialized = 1;
268 /* This is just for testing!!! */
272 case DECODER_GET_CAPABILITIES:
274 struct video_decoder_capability *cap = arg;
276 cap->flags = VIDEO_DECODER_PAL |
285 case DECODER_GET_STATUS:
291 status = bt819_read(client, 0x00);
293 if ((status & 0x80)) {
294 res |= DECODER_STATUS_GOOD;
296 switch (decoder->norm) {
297 case VIDEO_MODE_NTSC:
298 res |= DECODER_STATUS_NTSC;
301 res |= DECODER_STATUS_PAL;
304 case VIDEO_MODE_AUTO:
305 if ((status & 0x10)) {
306 res |= DECODER_STATUS_PAL;
308 res |= DECODER_STATUS_NTSC;
312 res |= DECODER_STATUS_COLOR;
315 dprintk(1, KERN_INFO "%s: get status %x\n", I2C_NAME(client),
320 case DECODER_SET_NORM:
323 struct timing *timing = NULL;
325 dprintk(1, KERN_INFO "%s: set norm %x\n", I2C_NAME(client),
329 case VIDEO_MODE_NTSC:
330 bt819_setbit(client, 0x01, 0, 1);
331 bt819_setbit(client, 0x01, 1, 0);
332 bt819_setbit(client, 0x01, 5, 0);
333 bt819_write(client, 0x18, 0x68);
334 bt819_write(client, 0x19, 0x5d);
335 //bt819_setbit(client, 0x1a, 5, 1);
336 timing = &timing_data[VIDEO_MODE_NTSC];
339 bt819_setbit(client, 0x01, 0, 1);
340 bt819_setbit(client, 0x01, 1, 1);
341 bt819_setbit(client, 0x01, 5, 1);
342 bt819_write(client, 0x18, 0x7f);
343 bt819_write(client, 0x19, 0x72);
344 //bt819_setbit(client, 0x1a, 5, 0);
345 timing = &timing_data[VIDEO_MODE_PAL];
347 case VIDEO_MODE_AUTO:
348 bt819_setbit(client, 0x01, 0, 0);
349 bt819_setbit(client, 0x01, 1, 0);
354 "%s: unsupported norm %d\n",
355 I2C_NAME(client), *iarg);
360 bt819_write(client, 0x03,
361 (((timing->vdelay >> 8) & 0x03) << 6) |
362 (((timing->vactive >> 8) & 0x03) << 4) |
363 (((timing->hdelay >> 8) & 0x03) << 2) |
364 ((timing->hactive >> 8) & 0x03) );
365 bt819_write(client, 0x04, timing->vdelay & 0xff);
366 bt819_write(client, 0x05, timing->vactive & 0xff);
367 bt819_write(client, 0x06, timing->hdelay & 0xff);
368 bt819_write(client, 0x07, timing->hactive & 0xff);
369 bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff);
370 bt819_write(client, 0x09, timing->hscale & 0xff);
373 decoder->norm = *iarg;
377 case DECODER_SET_INPUT:
381 dprintk(1, KERN_INFO "%s: set input %x\n", I2C_NAME(client),
384 if (*iarg < 0 || *iarg > 7) {
388 if (decoder->input != *iarg) {
389 decoder->input = *iarg;
391 if (decoder->input == 0) {
392 bt819_setbit(client, 0x0b, 6, 0);
393 bt819_setbit(client, 0x1a, 1, 1);
395 bt819_setbit(client, 0x0b, 6, 1);
396 bt819_setbit(client, 0x1a, 1, 0);
402 case DECODER_SET_OUTPUT:
406 dprintk(1, KERN_INFO "%s: set output %x\n", I2C_NAME(client),
409 /* not much choice of outputs */
416 case DECODER_ENABLE_OUTPUT:
419 int enable = (*iarg != 0);
421 dprintk(1, KERN_INFO "%s: enable output %x\n",
422 I2C_NAME(client), *iarg);
424 if (decoder->enable != enable) {
425 decoder->enable = enable;
427 if (decoder->enable) {
428 bt819_setbit(client, 0x16, 7, 0);
430 bt819_setbit(client, 0x16, 7, 1);
436 case DECODER_SET_PICTURE:
438 struct video_picture *pic = arg;
442 "%s: set picture brightness %d contrast %d colour %d\n",
443 I2C_NAME(client), pic->brightness, pic->contrast,
447 if (decoder->bright != pic->brightness) {
448 /* We want -128 to 127 we get 0-65535 */
449 decoder->bright = pic->brightness;
450 bt819_write(client, 0x0a,
451 (decoder->bright >> 8) - 128);
454 if (decoder->contrast != pic->contrast) {
455 /* We want 0 to 511 we get 0-65535 */
456 decoder->contrast = pic->contrast;
457 bt819_write(client, 0x0c,
458 (decoder->contrast >> 7) & 0xff);
459 bt819_setbit(client, 0x0b, 2,
460 ((decoder->contrast >> 15) & 0x01));
463 if (decoder->sat != pic->colour) {
464 /* We want 0 to 511 we get 0-65535 */
465 decoder->sat = pic->colour;
466 bt819_write(client, 0x0d,
467 (decoder->sat >> 7) & 0xff);
468 bt819_setbit(client, 0x0b, 1,
469 ((decoder->sat >> 15) & 0x01));
471 temp = (decoder->sat * 201) / 237;
472 bt819_write(client, 0x0e, (temp >> 7) & 0xff);
473 bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01);
476 if (decoder->hue != pic->hue) {
477 /* We want -128 to 127 we get 0-65535 */
478 decoder->hue = pic->hue;
479 bt819_write(client, 0x0f,
480 128 - (decoder->hue >> 8));
492 /* ----------------------------------------------------------------------- */
496 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
498 static unsigned short normal_i2c[] = {
503 static unsigned short ignore = I2C_CLIENT_END;
505 static struct i2c_client_address_data addr_data = {
506 .normal_i2c = normal_i2c,
511 static struct i2c_driver i2c_driver_bt819;
514 bt819_detect_client (struct i2c_adapter *adapter,
519 struct bt819 *decoder;
520 struct i2c_client *client;
524 "saa7111.c: detecting bt819 client on address 0x%x\n",
527 /* Check if the adapter supports the needed features */
528 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
531 client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
534 memset(client, 0, sizeof(struct i2c_client));
535 client->addr = address;
536 client->adapter = adapter;
537 client->driver = &i2c_driver_bt819;
538 client->flags = I2C_CLIENT_ALLOW_USE;
540 decoder = kmalloc(sizeof(struct bt819), GFP_KERNEL);
541 if (decoder == NULL) {
546 memset(decoder, 0, sizeof(struct bt819));
547 decoder->norm = VIDEO_MODE_NTSC;
550 decoder->bright = 32768;
551 decoder->contrast = 32768;
552 decoder->hue = 32768;
553 decoder->sat = 32768;
554 decoder->initialized = 0;
555 i2c_set_clientdata(client, decoder);
557 id = bt819_read(client, 0x17);
560 strlcpy(I2C_NAME(client), "bt819a", sizeof(I2C_NAME(client)));
563 strlcpy(I2C_NAME(client), "bt817a", sizeof(I2C_NAME(client)));
566 strlcpy(I2C_NAME(client), "bt815a", sizeof(I2C_NAME(client)));
571 "bt819: unknown chip version 0x%x (ver 0x%x)\n",
572 id & 0xf0, id & 0x0f);
578 i = i2c_attach_client(client);
585 i = bt819_init(client);
587 dprintk(1, KERN_ERR "%s_attach: init status %d\n",
588 I2C_NAME(client), i);
592 "%s_attach: chip version 0x%x at address 0x%x\n",
593 I2C_NAME(client), id & 0x0f,
601 bt819_attach_adapter (struct i2c_adapter *adapter)
603 return i2c_probe(adapter, &addr_data, &bt819_detect_client);
607 bt819_detach_client (struct i2c_client *client)
609 struct bt819 *decoder = i2c_get_clientdata(client);
612 err = i2c_detach_client(client);
623 /* ----------------------------------------------------------------------- */
625 static struct i2c_driver i2c_driver_bt819 = {
626 .owner = THIS_MODULE,
629 .id = I2C_DRIVERID_BT819,
630 .flags = I2C_DF_NOTIFY,
632 .attach_adapter = bt819_attach_adapter,
633 .detach_client = bt819_detach_client,
634 .command = bt819_command,
638 bt819_init_module (void)
640 return i2c_add_driver(&i2c_driver_bt819);
646 i2c_del_driver(&i2c_driver_bt819);
649 module_init(bt819_init_module);
650 module_exit(bt819_exit);