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);
146 msg.addr = client->addr;
149 msg.buf = (char *) block_data;
151 block_data[msg.len++] = reg = data[0];
153 block_data[msg.len++] =
154 decoder->reg[reg++] = data[1];
157 } while (len >= 2 && data[0] == reg &&
159 if ((ret = i2c_transfer(client->adapter,
164 /* do some slow I2C emulation kind of thing */
167 if ((ret = bt819_write(client, reg, *data++)) < 0)
177 bt819_read (struct i2c_client *client,
180 return i2c_smbus_read_byte_data(client, reg);
184 bt819_init (struct i2c_client *client)
186 struct bt819 *decoder = i2c_get_clientdata(client);
188 static unsigned char init[] = {
189 //0x1f, 0x00, /* Reset */
190 0x01, 0x59, /* 0x01 input format */
191 0x02, 0x00, /* 0x02 temporal decimation */
192 0x03, 0x12, /* 0x03 Cropping msb */
193 0x04, 0x16, /* 0x04 Vertical Delay, lsb */
194 0x05, 0xe0, /* 0x05 Vertical Active lsb */
195 0x06, 0x80, /* 0x06 Horizontal Delay lsb */
196 0x07, 0xd0, /* 0x07 Horizontal Active lsb */
197 0x08, 0x00, /* 0x08 Horizontal Scaling msb */
198 0x09, 0xf8, /* 0x09 Horizontal Scaling lsb */
199 0x0a, 0x00, /* 0x0a Brightness control */
200 0x0b, 0x30, /* 0x0b Miscellaneous control */
201 0x0c, 0xd8, /* 0x0c Luma Gain lsb */
202 0x0d, 0xfe, /* 0x0d Chroma Gain (U) lsb */
203 0x0e, 0xb4, /* 0x0e Chroma Gain (V) msb */
204 0x0f, 0x00, /* 0x0f Hue control */
205 0x12, 0x04, /* 0x12 Output Format */
206 0x13, 0x20, /* 0x13 Vertial Scaling msb 0x00
207 chroma comb OFF, line drop scaling, interlace scaling
208 BUG? Why does turning the chroma comb on fuck up color?
209 Bug in the bt819 stepping on my board?
211 0x14, 0x00, /* 0x14 Vertial Scaling lsb */
212 0x16, 0x07, /* 0x16 Video Timing Polarity
216 hreset=active high */
217 0x18, 0x68, /* 0x18 AGC Delay */
218 0x19, 0x5d, /* 0x19 Burst Gate Delay */
219 0x1a, 0x80, /* 0x1a ADC Interface */
222 struct timing *timing = &timing_data[decoder->norm];
225 (((timing->vdelay >> 8) & 0x03) << 6) | (((timing->
228 (((timing->hdelay >> 8) & 0x03) << 2) | ((timing->
231 init[0x04 * 2 - 1] = timing->vdelay & 0xff;
232 init[0x05 * 2 - 1] = timing->vactive & 0xff;
233 init[0x06 * 2 - 1] = timing->hdelay & 0xff;
234 init[0x07 * 2 - 1] = timing->hactive & 0xff;
235 init[0x08 * 2 - 1] = timing->hscale >> 8;
236 init[0x09 * 2 - 1] = timing->hscale & 0xff;
237 /* 0x15 in array is address 0x19 */
238 init[0x15 * 2 - 1] = (decoder->norm == 0) ? 115 : 93; /* Chroma burst delay */
240 bt819_write(client, 0x1f, 0x00);
244 return bt819_write_block(client, init, sizeof(init));
248 /* ----------------------------------------------------------------------- */
251 bt819_command (struct i2c_client *client,
257 struct bt819 *decoder = i2c_get_clientdata(client);
259 if (!decoder->initialized) { // First call to bt819_init could be
260 bt819_init(client); // without #FRST = 0
261 decoder->initialized = 1;
267 /* This is just for testing!!! */
271 case DECODER_GET_CAPABILITIES:
273 struct video_decoder_capability *cap = arg;
275 cap->flags = VIDEO_DECODER_PAL |
284 case DECODER_GET_STATUS:
290 status = bt819_read(client, 0x00);
292 if ((status & 0x80)) {
293 res |= DECODER_STATUS_GOOD;
295 switch (decoder->norm) {
296 case VIDEO_MODE_NTSC:
297 res |= DECODER_STATUS_NTSC;
300 res |= DECODER_STATUS_PAL;
303 case VIDEO_MODE_AUTO:
304 if ((status & 0x10)) {
305 res |= DECODER_STATUS_PAL;
307 res |= DECODER_STATUS_NTSC;
311 res |= DECODER_STATUS_COLOR;
314 dprintk(1, KERN_INFO "%s: get status %x\n", I2C_NAME(client),
319 case DECODER_SET_NORM:
322 struct timing *timing = NULL;
324 dprintk(1, KERN_INFO "%s: set norm %x\n", I2C_NAME(client),
328 case VIDEO_MODE_NTSC:
329 bt819_setbit(client, 0x01, 0, 1);
330 bt819_setbit(client, 0x01, 1, 0);
331 bt819_setbit(client, 0x01, 5, 0);
332 bt819_write(client, 0x18, 0x68);
333 bt819_write(client, 0x19, 0x5d);
334 //bt819_setbit(client, 0x1a, 5, 1);
335 timing = &timing_data[VIDEO_MODE_NTSC];
338 bt819_setbit(client, 0x01, 0, 1);
339 bt819_setbit(client, 0x01, 1, 1);
340 bt819_setbit(client, 0x01, 5, 1);
341 bt819_write(client, 0x18, 0x7f);
342 bt819_write(client, 0x19, 0x72);
343 //bt819_setbit(client, 0x1a, 5, 0);
344 timing = &timing_data[VIDEO_MODE_PAL];
346 case VIDEO_MODE_AUTO:
347 bt819_setbit(client, 0x01, 0, 0);
348 bt819_setbit(client, 0x01, 1, 0);
353 "%s: unsupported norm %d\n",
354 I2C_NAME(client), *iarg);
359 bt819_write(client, 0x03,
360 (((timing->vdelay >> 8) & 0x03) << 6) |
361 (((timing->vactive >> 8) & 0x03) << 4) |
362 (((timing->hdelay >> 8) & 0x03) << 2) |
363 ((timing->hactive >> 8) & 0x03) );
364 bt819_write(client, 0x04, timing->vdelay & 0xff);
365 bt819_write(client, 0x05, timing->vactive & 0xff);
366 bt819_write(client, 0x06, timing->hdelay & 0xff);
367 bt819_write(client, 0x07, timing->hactive & 0xff);
368 bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff);
369 bt819_write(client, 0x09, timing->hscale & 0xff);
372 decoder->norm = *iarg;
376 case DECODER_SET_INPUT:
380 dprintk(1, KERN_INFO "%s: set input %x\n", I2C_NAME(client),
383 if (*iarg < 0 || *iarg > 7) {
387 if (decoder->input != *iarg) {
388 decoder->input = *iarg;
390 if (decoder->input == 0) {
391 bt819_setbit(client, 0x0b, 6, 0);
392 bt819_setbit(client, 0x1a, 1, 1);
394 bt819_setbit(client, 0x0b, 6, 1);
395 bt819_setbit(client, 0x1a, 1, 0);
401 case DECODER_SET_OUTPUT:
405 dprintk(1, KERN_INFO "%s: set output %x\n", I2C_NAME(client),
408 /* not much choice of outputs */
415 case DECODER_ENABLE_OUTPUT:
418 int enable = (*iarg != 0);
420 dprintk(1, KERN_INFO "%s: enable output %x\n",
421 I2C_NAME(client), *iarg);
423 if (decoder->enable != enable) {
424 decoder->enable = enable;
426 if (decoder->enable) {
427 bt819_setbit(client, 0x16, 7, 0);
429 bt819_setbit(client, 0x16, 7, 1);
435 case DECODER_SET_PICTURE:
437 struct video_picture *pic = arg;
441 "%s: set picture brightness %d contrast %d colour %d\n",
442 I2C_NAME(client), pic->brightness, pic->contrast,
446 if (decoder->bright != pic->brightness) {
447 /* We want -128 to 127 we get 0-65535 */
448 decoder->bright = pic->brightness;
449 bt819_write(client, 0x0a,
450 (decoder->bright >> 8) - 128);
453 if (decoder->contrast != pic->contrast) {
454 /* We want 0 to 511 we get 0-65535 */
455 decoder->contrast = pic->contrast;
456 bt819_write(client, 0x0c,
457 (decoder->contrast >> 7) & 0xff);
458 bt819_setbit(client, 0x0b, 2,
459 ((decoder->contrast >> 15) & 0x01));
462 if (decoder->sat != pic->colour) {
463 /* We want 0 to 511 we get 0-65535 */
464 decoder->sat = pic->colour;
465 bt819_write(client, 0x0d,
466 (decoder->sat >> 7) & 0xff);
467 bt819_setbit(client, 0x0b, 1,
468 ((decoder->sat >> 15) & 0x01));
470 temp = (decoder->sat * 201) / 237;
471 bt819_write(client, 0x0e, (temp >> 7) & 0xff);
472 bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01);
475 if (decoder->hue != pic->hue) {
476 /* We want -128 to 127 we get 0-65535 */
477 decoder->hue = pic->hue;
478 bt819_write(client, 0x0f,
479 128 - (decoder->hue >> 8));
491 /* ----------------------------------------------------------------------- */
495 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
497 static unsigned short normal_i2c[] = {
502 static unsigned short ignore = I2C_CLIENT_END;
504 static struct i2c_client_address_data addr_data = {
505 .normal_i2c = normal_i2c,
510 static struct i2c_driver i2c_driver_bt819;
513 bt819_detect_client (struct i2c_adapter *adapter,
518 struct bt819 *decoder;
519 struct i2c_client *client;
523 "saa7111.c: detecting bt819 client on address 0x%x\n",
526 /* Check if the adapter supports the needed features */
527 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
530 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
533 client->addr = address;
534 client->adapter = adapter;
535 client->driver = &i2c_driver_bt819;
537 decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
538 if (decoder == NULL) {
542 decoder->norm = VIDEO_MODE_NTSC;
545 decoder->bright = 32768;
546 decoder->contrast = 32768;
547 decoder->hue = 32768;
548 decoder->sat = 32768;
549 decoder->initialized = 0;
550 i2c_set_clientdata(client, decoder);
552 id = bt819_read(client, 0x17);
555 strlcpy(I2C_NAME(client), "bt819a", sizeof(I2C_NAME(client)));
558 strlcpy(I2C_NAME(client), "bt817a", sizeof(I2C_NAME(client)));
561 strlcpy(I2C_NAME(client), "bt815a", sizeof(I2C_NAME(client)));
566 "bt819: unknown chip version 0x%x (ver 0x%x)\n",
567 id & 0xf0, id & 0x0f);
573 i = i2c_attach_client(client);
580 i = bt819_init(client);
582 dprintk(1, KERN_ERR "%s_attach: init status %d\n",
583 I2C_NAME(client), i);
587 "%s_attach: chip version 0x%x at address 0x%x\n",
588 I2C_NAME(client), id & 0x0f,
596 bt819_attach_adapter (struct i2c_adapter *adapter)
598 return i2c_probe(adapter, &addr_data, &bt819_detect_client);
602 bt819_detach_client (struct i2c_client *client)
604 struct bt819 *decoder = i2c_get_clientdata(client);
607 err = i2c_detach_client(client);
618 /* ----------------------------------------------------------------------- */
620 static struct i2c_driver i2c_driver_bt819 = {
625 .id = I2C_DRIVERID_BT819,
627 .attach_adapter = bt819_attach_adapter,
628 .detach_client = bt819_detach_client,
629 .command = bt819_command,
633 bt819_init_module (void)
635 return i2c_add_driver(&i2c_driver_bt819);
641 i2c_del_driver(&i2c_driver_bt819);
644 module_init(bt819_init_module);
645 module_exit(bt819_exit);