blob: e7b38fdd5e3c9389e2032ca1c8c5103a19a120a1 [file] [log] [blame]
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * bt819 - BT819A VideoStream Decoder (Rockwell Part)
3 *
4 * Copyright (C) 1999 Mike Bernson <mike@mlb.org>
5 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
6 *
7 * Modifications for LML33/DC10plus unified driver
8 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03009 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
11 * - moved over to linux>=2.4.x i2c protocol (9/9/2002)
12 *
13 * This code was modify/ported from the saa7111 driver written
14 * by Dave Perks.
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#include <linux/slab.h>
39#include <linux/mm.h>
40#include <linux/pci.h>
41#include <linux/signal.h>
42#include <asm/io.h>
43#include <asm/pgtable.h>
44#include <asm/page.h>
45#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <linux/types.h>
47
48#include <linux/videodev.h>
49#include <asm/uaccess.h>
50
51MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
52MODULE_AUTHOR("Mike Bernson & Dave Perks");
53MODULE_LICENSE("GPL");
54
55#include <linux/i2c.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57#define I2C_NAME(s) (s)->name
58
59#include <linux/video_decoder.h>
60
61static int debug = 0;
62module_param(debug, int, 0);
63MODULE_PARM_DESC(debug, "Debug level (0-1)");
64
65#define dprintk(num, format, args...) \
66 do { \
67 if (debug >= num) \
68 printk(format, ##args); \
69 } while (0)
70
71/* ----------------------------------------------------------------------- */
72
73struct bt819 {
74 unsigned char reg[32];
75
76 int initialized;
77 int norm;
78 int input;
79 int enable;
80 int bright;
81 int contrast;
82 int hue;
83 int sat;
84};
85
86struct timing {
87 int hactive;
88 int hdelay;
89 int vactive;
90 int vdelay;
91 int hscale;
92 int vscale;
93};
94
95/* for values, see the bt819 datasheet */
96static struct timing timing_data[] = {
97 {864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
98 {858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
99};
100
101#define I2C_BT819 0x8a
102
103/* ----------------------------------------------------------------------- */
104
105static inline int
106bt819_write (struct i2c_client *client,
107 u8 reg,
108 u8 value)
109{
110 struct bt819 *decoder = i2c_get_clientdata(client);
111
112 decoder->reg[reg] = value;
113 return i2c_smbus_write_byte_data(client, reg, value);
114}
115
116static inline int
117bt819_setbit (struct i2c_client *client,
118 u8 reg,
119 u8 bit,
120 u8 value)
121{
122 struct bt819 *decoder = i2c_get_clientdata(client);
123
124 return bt819_write(client, reg,
125 (decoder->
126 reg[reg] & ~(1 << bit)) |
127 (value ? (1 << bit) : 0));
128}
129
130static int
131bt819_write_block (struct i2c_client *client,
132 const u8 *data,
133 unsigned int len)
134{
135 int ret = -1;
136 u8 reg;
137
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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 u8 block_data[32];
Jean Delvare9aa45e32006-03-22 03:48:35 -0300144 int block_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 while (len >= 2) {
Jean Delvare9aa45e32006-03-22 03:48:35 -0300147 block_len = 0;
148 block_data[block_len++] = reg = data[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 do {
Jean Delvare9aa45e32006-03-22 03:48:35 -0300150 block_data[block_len++] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 decoder->reg[reg++] = data[1];
152 len -= 2;
153 data += 2;
154 } while (len >= 2 && data[0] == reg &&
Jean Delvare9aa45e32006-03-22 03:48:35 -0300155 block_len < 32);
156 if ((ret = i2c_master_send(client, block_data,
157 block_len)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 break;
159 }
160 } else {
161 /* do some slow I2C emulation kind of thing */
162 while (len >= 2) {
163 reg = *data++;
164 if ((ret = bt819_write(client, reg, *data++)) < 0)
165 break;
166 len -= 2;
167 }
168 }
169
170 return ret;
171}
172
173static inline int
174bt819_read (struct i2c_client *client,
175 u8 reg)
176{
177 return i2c_smbus_read_byte_data(client, reg);
178}
179
180static int
181bt819_init (struct i2c_client *client)
182{
183 struct bt819 *decoder = i2c_get_clientdata(client);
184
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?
207 */
208 0x14, 0x00, /* 0x14 Vertial Scaling lsb */
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300209 0x16, 0x07, /* 0x16 Video Timing Polarity
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 ACTIVE=active low
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300211 FIELD: high=odd,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 vreset=active high,
213 hreset=active high */
214 0x18, 0x68, /* 0x18 AGC Delay */
215 0x19, 0x5d, /* 0x19 Burst Gate Delay */
216 0x1a, 0x80, /* 0x1a ADC Interface */
217 };
218
219 struct timing *timing = &timing_data[decoder->norm];
220
221 init[0x03 * 2 - 1] =
222 (((timing->vdelay >> 8) & 0x03) << 6) | (((timing->
223 vactive >> 8) &
224 0x03) << 4) |
225 (((timing->hdelay >> 8) & 0x03) << 2) | ((timing->
226 hactive >> 8) &
227 0x03);
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 */
236 /* reset */
237 bt819_write(client, 0x1f, 0x00);
238 mdelay(1);
239
240 /* init */
241 return bt819_write_block(client, init, sizeof(init));
242
243}
244
245/* ----------------------------------------------------------------------- */
246
247static int
248bt819_command (struct i2c_client *client,
249 unsigned int cmd,
250 void *arg)
251{
252 int temp;
253
254 struct bt819 *decoder = i2c_get_clientdata(client);
255
256 if (!decoder->initialized) { // First call to bt819_init could be
257 bt819_init(client); // without #FRST = 0
258 decoder->initialized = 1;
259 }
260
261 switch (cmd) {
262
263 case 0:
264 /* This is just for testing!!! */
265 bt819_init(client);
266 break;
267
268 case DECODER_GET_CAPABILITIES:
269 {
270 struct video_decoder_capability *cap = arg;
271
272 cap->flags = VIDEO_DECODER_PAL |
273 VIDEO_DECODER_NTSC |
274 VIDEO_DECODER_AUTO |
275 VIDEO_DECODER_CCIR;
276 cap->inputs = 8;
277 cap->outputs = 1;
278 }
279 break;
280
281 case DECODER_GET_STATUS:
282 {
283 int *iarg = arg;
284 int status;
285 int res;
286
287 status = bt819_read(client, 0x00);
288 res = 0;
289 if ((status & 0x80)) {
290 res |= DECODER_STATUS_GOOD;
291 }
292 switch (decoder->norm) {
293 case VIDEO_MODE_NTSC:
294 res |= DECODER_STATUS_NTSC;
295 break;
296 case VIDEO_MODE_PAL:
297 res |= DECODER_STATUS_PAL;
298 break;
299 default:
300 case VIDEO_MODE_AUTO:
301 if ((status & 0x10)) {
302 res |= DECODER_STATUS_PAL;
303 } else {
304 res |= DECODER_STATUS_NTSC;
305 }
306 break;
307 }
308 res |= DECODER_STATUS_COLOR;
309 *iarg = res;
310
311 dprintk(1, KERN_INFO "%s: get status %x\n", I2C_NAME(client),
312 *iarg);
313 }
314 break;
315
316 case DECODER_SET_NORM:
317 {
318 int *iarg = arg;
319 struct timing *timing = NULL;
320
321 dprintk(1, KERN_INFO "%s: set norm %x\n", I2C_NAME(client),
322 *iarg);
323
324 switch (*iarg) {
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];
333 break;
334 case VIDEO_MODE_PAL:
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];
342 break;
343 case VIDEO_MODE_AUTO:
344 bt819_setbit(client, 0x01, 0, 0);
345 bt819_setbit(client, 0x01, 1, 0);
346 break;
347 default:
348 dprintk(1,
349 KERN_ERR
350 "%s: unsupported norm %d\n",
351 I2C_NAME(client), *iarg);
352 return -EINVAL;
353 }
354
355 if (timing) {
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);
367 }
368
369 decoder->norm = *iarg;
370 }
371 break;
372
373 case DECODER_SET_INPUT:
374 {
375 int *iarg = arg;
376
377 dprintk(1, KERN_INFO "%s: set input %x\n", I2C_NAME(client),
378 *iarg);
379
380 if (*iarg < 0 || *iarg > 7) {
381 return -EINVAL;
382 }
383
384 if (decoder->input != *iarg) {
385 decoder->input = *iarg;
386 /* select mode */
387 if (decoder->input == 0) {
388 bt819_setbit(client, 0x0b, 6, 0);
389 bt819_setbit(client, 0x1a, 1, 1);
390 } else {
391 bt819_setbit(client, 0x0b, 6, 1);
392 bt819_setbit(client, 0x1a, 1, 0);
393 }
394 }
395 }
396 break;
397
398 case DECODER_SET_OUTPUT:
399 {
400 int *iarg = arg;
401
402 dprintk(1, KERN_INFO "%s: set output %x\n", I2C_NAME(client),
403 *iarg);
404
405 /* not much choice of outputs */
406 if (*iarg != 0) {
407 return -EINVAL;
408 }
409 }
410 break;
411
412 case DECODER_ENABLE_OUTPUT:
413 {
414 int *iarg = arg;
415 int enable = (*iarg != 0);
416
417 dprintk(1, KERN_INFO "%s: enable output %x\n",
418 I2C_NAME(client), *iarg);
419
420 if (decoder->enable != enable) {
421 decoder->enable = enable;
422
423 if (decoder->enable) {
424 bt819_setbit(client, 0x16, 7, 0);
425 } else {
426 bt819_setbit(client, 0x16, 7, 1);
427 }
428 }
429 }
430 break;
431
432 case DECODER_SET_PICTURE:
433 {
434 struct video_picture *pic = arg;
435
436 dprintk(1,
437 KERN_INFO
438 "%s: set picture brightness %d contrast %d colour %d\n",
439 I2C_NAME(client), pic->brightness, pic->contrast,
440 pic->colour);
441
442
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);
448 }
449
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));
457 }
458
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));
466
467 temp = (decoder->sat * 201) / 237;
468 bt819_write(client, 0x0e, (temp >> 7) & 0xff);
469 bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01);
470 }
471
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));
477 }
478 }
479 break;
480
481 default:
482 return -EINVAL;
483 }
484
485 return 0;
486}
487
488/* ----------------------------------------------------------------------- */
489
490/*
491 * Generic i2c probe
492 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
493 */
494static unsigned short normal_i2c[] = {
495 I2C_BT819 >> 1,
496 I2C_CLIENT_END,
497};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
Jean Delvare68cc9d02005-04-02 20:04:41 +0200499static unsigned short ignore = I2C_CLIENT_END;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300500
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501static struct i2c_client_address_data addr_data = {
502 .normal_i2c = normal_i2c,
Jean Delvare68cc9d02005-04-02 20:04:41 +0200503 .probe = &ignore,
504 .ignore = &ignore,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505};
506
507static struct i2c_driver i2c_driver_bt819;
508
509static int
510bt819_detect_client (struct i2c_adapter *adapter,
511 int address,
512 int kind)
513{
514 int i, id;
515 struct bt819 *decoder;
516 struct i2c_client *client;
517
518 dprintk(1,
519 KERN_INFO
520 "saa7111.c: detecting bt819 client on address 0x%x\n",
521 address << 1);
522
523 /* Check if the adapter supports the needed features */
524 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
525 return 0;
526
Panagiotis Issaris74081872006-01-11 19:40:56 -0200527 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 if (client == 0)
529 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 client->addr = address;
531 client->adapter = adapter;
532 client->driver = &i2c_driver_bt819;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533
Panagiotis Issaris74081872006-01-11 19:40:56 -0200534 decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 if (decoder == NULL) {
536 kfree(client);
537 return -ENOMEM;
538 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 decoder->norm = VIDEO_MODE_NTSC;
540 decoder->input = 0;
541 decoder->enable = 1;
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);
548
549 id = bt819_read(client, 0x17);
550 switch (id & 0xf0) {
551 case 0x70:
552 strlcpy(I2C_NAME(client), "bt819a", sizeof(I2C_NAME(client)));
553 break;
554 case 0x60:
555 strlcpy(I2C_NAME(client), "bt817a", sizeof(I2C_NAME(client)));
556 break;
557 case 0x20:
558 strlcpy(I2C_NAME(client), "bt815a", sizeof(I2C_NAME(client)));
559 break;
560 default:
561 dprintk(1,
562 KERN_ERR
563 "bt819: unknown chip version 0x%x (ver 0x%x)\n",
564 id & 0xf0, id & 0x0f);
565 kfree(decoder);
566 kfree(client);
567 return 0;
568 }
569
570 i = i2c_attach_client(client);
571 if (i) {
572 kfree(client);
573 kfree(decoder);
574 return i;
575 }
576
577 i = bt819_init(client);
578 if (i < 0) {
579 dprintk(1, KERN_ERR "%s_attach: init status %d\n",
580 I2C_NAME(client), i);
581 } else {
582 dprintk(1,
583 KERN_INFO
584 "%s_attach: chip version 0x%x at address 0x%x\n",
585 I2C_NAME(client), id & 0x0f,
586 client->addr << 1);
587 }
588
589 return 0;
590}
591
592static int
593bt819_attach_adapter (struct i2c_adapter *adapter)
594{
595 return i2c_probe(adapter, &addr_data, &bt819_detect_client);
596}
597
598static int
599bt819_detach_client (struct i2c_client *client)
600{
601 struct bt819 *decoder = i2c_get_clientdata(client);
602 int err;
603
604 err = i2c_detach_client(client);
605 if (err) {
606 return err;
607 }
608
609 kfree(decoder);
610 kfree(client);
611
612 return 0;
613}
614
615/* ----------------------------------------------------------------------- */
616
617static struct i2c_driver i2c_driver_bt819 = {
Laurent Riffard604f28e2005-11-26 20:43:39 +0100618 .driver = {
Laurent Riffard604f28e2005-11-26 20:43:39 +0100619 .name = "bt819",
620 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622 .id = I2C_DRIVERID_BT819,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
624 .attach_adapter = bt819_attach_adapter,
625 .detach_client = bt819_detach_client,
626 .command = bt819_command,
627};
628
629static int __init
630bt819_init_module (void)
631{
632 return i2c_add_driver(&i2c_driver_bt819);
633}
634
635static void __exit
636bt819_exit (void)
637{
638 i2c_del_driver(&i2c_driver_bt819);
639}
640
641module_init(bt819_init_module);
642module_exit(bt819_exit);