blob: 59a43603b5cbdcb8f933e28eac5b3454486f0697 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <linux/signal.h>
41#include <asm/io.h>
42#include <asm/pgtable.h>
43#include <asm/page.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/types.h>
45
46#include <linux/videodev.h>
47#include <asm/uaccess.h>
48
49MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
50MODULE_AUTHOR("Mike Bernson & Dave Perks");
51MODULE_LICENSE("GPL");
52
53#include <linux/i2c.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55#define I2C_NAME(s) (s)->name
56
57#include <linux/video_decoder.h>
58
59static int debug = 0;
60module_param(debug, int, 0);
61MODULE_PARM_DESC(debug, "Debug level (0-1)");
62
63#define dprintk(num, format, args...) \
64 do { \
65 if (debug >= num) \
66 printk(format, ##args); \
67 } while (0)
68
69/* ----------------------------------------------------------------------- */
70
71struct bt819 {
72 unsigned char reg[32];
73
74 int initialized;
75 int norm;
76 int input;
77 int enable;
78 int bright;
79 int contrast;
80 int hue;
81 int sat;
82};
83
84struct timing {
85 int hactive;
86 int hdelay;
87 int vactive;
88 int vdelay;
89 int hscale;
90 int vscale;
91};
92
93/* for values, see the bt819 datasheet */
94static struct timing timing_data[] = {
95 {864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
96 {858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
97};
98
99#define I2C_BT819 0x8a
100
101/* ----------------------------------------------------------------------- */
102
103static inline int
104bt819_write (struct i2c_client *client,
105 u8 reg,
106 u8 value)
107{
108 struct bt819 *decoder = i2c_get_clientdata(client);
109
110 decoder->reg[reg] = value;
111 return i2c_smbus_write_byte_data(client, reg, value);
112}
113
114static inline int
115bt819_setbit (struct i2c_client *client,
116 u8 reg,
117 u8 bit,
118 u8 value)
119{
120 struct bt819 *decoder = i2c_get_clientdata(client);
121
122 return bt819_write(client, reg,
123 (decoder->
124 reg[reg] & ~(1 << bit)) |
125 (value ? (1 << bit) : 0));
126}
127
128static int
129bt819_write_block (struct i2c_client *client,
130 const u8 *data,
131 unsigned int len)
132{
133 int ret = -1;
134 u8 reg;
135
136 /* the bt819 has an autoincrement function, use it if
137 * the adapter understands raw I2C */
138 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
139 /* do raw I2C, not smbus compatible */
140 struct bt819 *decoder = i2c_get_clientdata(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 u8 block_data[32];
Jean Delvare9aa45e32006-03-22 03:48:35 -0300142 int block_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 while (len >= 2) {
Jean Delvare9aa45e32006-03-22 03:48:35 -0300145 block_len = 0;
146 block_data[block_len++] = reg = data[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 do {
Jean Delvare9aa45e32006-03-22 03:48:35 -0300148 block_data[block_len++] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 decoder->reg[reg++] = data[1];
150 len -= 2;
151 data += 2;
152 } while (len >= 2 && data[0] == reg &&
Jean Delvare9aa45e32006-03-22 03:48:35 -0300153 block_len < 32);
154 if ((ret = i2c_master_send(client, block_data,
155 block_len)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 break;
157 }
158 } else {
159 /* do some slow I2C emulation kind of thing */
160 while (len >= 2) {
161 reg = *data++;
162 if ((ret = bt819_write(client, reg, *data++)) < 0)
163 break;
164 len -= 2;
165 }
166 }
167
168 return ret;
169}
170
171static inline int
172bt819_read (struct i2c_client *client,
173 u8 reg)
174{
175 return i2c_smbus_read_byte_data(client, reg);
176}
177
178static int
179bt819_init (struct i2c_client *client)
180{
181 struct bt819 *decoder = i2c_get_clientdata(client);
182
183 static unsigned char init[] = {
184 //0x1f, 0x00, /* Reset */
185 0x01, 0x59, /* 0x01 input format */
186 0x02, 0x00, /* 0x02 temporal decimation */
187 0x03, 0x12, /* 0x03 Cropping msb */
188 0x04, 0x16, /* 0x04 Vertical Delay, lsb */
189 0x05, 0xe0, /* 0x05 Vertical Active lsb */
190 0x06, 0x80, /* 0x06 Horizontal Delay lsb */
191 0x07, 0xd0, /* 0x07 Horizontal Active lsb */
192 0x08, 0x00, /* 0x08 Horizontal Scaling msb */
193 0x09, 0xf8, /* 0x09 Horizontal Scaling lsb */
194 0x0a, 0x00, /* 0x0a Brightness control */
195 0x0b, 0x30, /* 0x0b Miscellaneous control */
196 0x0c, 0xd8, /* 0x0c Luma Gain lsb */
197 0x0d, 0xfe, /* 0x0d Chroma Gain (U) lsb */
198 0x0e, 0xb4, /* 0x0e Chroma Gain (V) msb */
199 0x0f, 0x00, /* 0x0f Hue control */
200 0x12, 0x04, /* 0x12 Output Format */
201 0x13, 0x20, /* 0x13 Vertial Scaling msb 0x00
202 chroma comb OFF, line drop scaling, interlace scaling
203 BUG? Why does turning the chroma comb on fuck up color?
204 Bug in the bt819 stepping on my board?
205 */
206 0x14, 0x00, /* 0x14 Vertial Scaling lsb */
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300207 0x16, 0x07, /* 0x16 Video Timing Polarity
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 ACTIVE=active low
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300209 FIELD: high=odd,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 vreset=active high,
211 hreset=active high */
212 0x18, 0x68, /* 0x18 AGC Delay */
213 0x19, 0x5d, /* 0x19 Burst Gate Delay */
214 0x1a, 0x80, /* 0x1a ADC Interface */
215 };
216
217 struct timing *timing = &timing_data[decoder->norm];
218
219 init[0x03 * 2 - 1] =
220 (((timing->vdelay >> 8) & 0x03) << 6) | (((timing->
221 vactive >> 8) &
222 0x03) << 4) |
223 (((timing->hdelay >> 8) & 0x03) << 2) | ((timing->
224 hactive >> 8) &
225 0x03);
226 init[0x04 * 2 - 1] = timing->vdelay & 0xff;
227 init[0x05 * 2 - 1] = timing->vactive & 0xff;
228 init[0x06 * 2 - 1] = timing->hdelay & 0xff;
229 init[0x07 * 2 - 1] = timing->hactive & 0xff;
230 init[0x08 * 2 - 1] = timing->hscale >> 8;
231 init[0x09 * 2 - 1] = timing->hscale & 0xff;
232 /* 0x15 in array is address 0x19 */
233 init[0x15 * 2 - 1] = (decoder->norm == 0) ? 115 : 93; /* Chroma burst delay */
234 /* reset */
235 bt819_write(client, 0x1f, 0x00);
236 mdelay(1);
237
238 /* init */
239 return bt819_write_block(client, init, sizeof(init));
240
241}
242
243/* ----------------------------------------------------------------------- */
244
245static int
246bt819_command (struct i2c_client *client,
247 unsigned int cmd,
248 void *arg)
249{
250 int temp;
251
252 struct bt819 *decoder = i2c_get_clientdata(client);
253
254 if (!decoder->initialized) { // First call to bt819_init could be
255 bt819_init(client); // without #FRST = 0
256 decoder->initialized = 1;
257 }
258
259 switch (cmd) {
260
261 case 0:
262 /* This is just for testing!!! */
263 bt819_init(client);
264 break;
265
266 case DECODER_GET_CAPABILITIES:
267 {
268 struct video_decoder_capability *cap = arg;
269
270 cap->flags = VIDEO_DECODER_PAL |
271 VIDEO_DECODER_NTSC |
272 VIDEO_DECODER_AUTO |
273 VIDEO_DECODER_CCIR;
274 cap->inputs = 8;
275 cap->outputs = 1;
276 }
277 break;
278
279 case DECODER_GET_STATUS:
280 {
281 int *iarg = arg;
282 int status;
283 int res;
284
285 status = bt819_read(client, 0x00);
286 res = 0;
287 if ((status & 0x80)) {
288 res |= DECODER_STATUS_GOOD;
289 }
290 switch (decoder->norm) {
291 case VIDEO_MODE_NTSC:
292 res |= DECODER_STATUS_NTSC;
293 break;
294 case VIDEO_MODE_PAL:
295 res |= DECODER_STATUS_PAL;
296 break;
297 default:
298 case VIDEO_MODE_AUTO:
299 if ((status & 0x10)) {
300 res |= DECODER_STATUS_PAL;
301 } else {
302 res |= DECODER_STATUS_NTSC;
303 }
304 break;
305 }
306 res |= DECODER_STATUS_COLOR;
307 *iarg = res;
308
309 dprintk(1, KERN_INFO "%s: get status %x\n", I2C_NAME(client),
310 *iarg);
311 }
312 break;
313
314 case DECODER_SET_NORM:
315 {
316 int *iarg = arg;
317 struct timing *timing = NULL;
318
319 dprintk(1, KERN_INFO "%s: set norm %x\n", I2C_NAME(client),
320 *iarg);
321
322 switch (*iarg) {
323 case VIDEO_MODE_NTSC:
324 bt819_setbit(client, 0x01, 0, 1);
325 bt819_setbit(client, 0x01, 1, 0);
326 bt819_setbit(client, 0x01, 5, 0);
327 bt819_write(client, 0x18, 0x68);
328 bt819_write(client, 0x19, 0x5d);
329 //bt819_setbit(client, 0x1a, 5, 1);
330 timing = &timing_data[VIDEO_MODE_NTSC];
331 break;
332 case VIDEO_MODE_PAL:
333 bt819_setbit(client, 0x01, 0, 1);
334 bt819_setbit(client, 0x01, 1, 1);
335 bt819_setbit(client, 0x01, 5, 1);
336 bt819_write(client, 0x18, 0x7f);
337 bt819_write(client, 0x19, 0x72);
338 //bt819_setbit(client, 0x1a, 5, 0);
339 timing = &timing_data[VIDEO_MODE_PAL];
340 break;
341 case VIDEO_MODE_AUTO:
342 bt819_setbit(client, 0x01, 0, 0);
343 bt819_setbit(client, 0x01, 1, 0);
344 break;
345 default:
346 dprintk(1,
347 KERN_ERR
348 "%s: unsupported norm %d\n",
349 I2C_NAME(client), *iarg);
350 return -EINVAL;
351 }
352
353 if (timing) {
354 bt819_write(client, 0x03,
355 (((timing->vdelay >> 8) & 0x03) << 6) |
356 (((timing->vactive >> 8) & 0x03) << 4) |
357 (((timing->hdelay >> 8) & 0x03) << 2) |
358 ((timing->hactive >> 8) & 0x03) );
359 bt819_write(client, 0x04, timing->vdelay & 0xff);
360 bt819_write(client, 0x05, timing->vactive & 0xff);
361 bt819_write(client, 0x06, timing->hdelay & 0xff);
362 bt819_write(client, 0x07, timing->hactive & 0xff);
363 bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff);
364 bt819_write(client, 0x09, timing->hscale & 0xff);
365 }
366
367 decoder->norm = *iarg;
368 }
369 break;
370
371 case DECODER_SET_INPUT:
372 {
373 int *iarg = arg;
374
375 dprintk(1, KERN_INFO "%s: set input %x\n", I2C_NAME(client),
376 *iarg);
377
378 if (*iarg < 0 || *iarg > 7) {
379 return -EINVAL;
380 }
381
382 if (decoder->input != *iarg) {
383 decoder->input = *iarg;
384 /* select mode */
385 if (decoder->input == 0) {
386 bt819_setbit(client, 0x0b, 6, 0);
387 bt819_setbit(client, 0x1a, 1, 1);
388 } else {
389 bt819_setbit(client, 0x0b, 6, 1);
390 bt819_setbit(client, 0x1a, 1, 0);
391 }
392 }
393 }
394 break;
395
396 case DECODER_SET_OUTPUT:
397 {
398 int *iarg = arg;
399
400 dprintk(1, KERN_INFO "%s: set output %x\n", I2C_NAME(client),
401 *iarg);
402
403 /* not much choice of outputs */
404 if (*iarg != 0) {
405 return -EINVAL;
406 }
407 }
408 break;
409
410 case DECODER_ENABLE_OUTPUT:
411 {
412 int *iarg = arg;
413 int enable = (*iarg != 0);
414
415 dprintk(1, KERN_INFO "%s: enable output %x\n",
416 I2C_NAME(client), *iarg);
417
418 if (decoder->enable != enable) {
419 decoder->enable = enable;
420
421 if (decoder->enable) {
422 bt819_setbit(client, 0x16, 7, 0);
423 } else {
424 bt819_setbit(client, 0x16, 7, 1);
425 }
426 }
427 }
428 break;
429
430 case DECODER_SET_PICTURE:
431 {
432 struct video_picture *pic = arg;
433
434 dprintk(1,
435 KERN_INFO
436 "%s: set picture brightness %d contrast %d colour %d\n",
437 I2C_NAME(client), pic->brightness, pic->contrast,
438 pic->colour);
439
440
441 if (decoder->bright != pic->brightness) {
442 /* We want -128 to 127 we get 0-65535 */
443 decoder->bright = pic->brightness;
444 bt819_write(client, 0x0a,
445 (decoder->bright >> 8) - 128);
446 }
447
448 if (decoder->contrast != pic->contrast) {
449 /* We want 0 to 511 we get 0-65535 */
450 decoder->contrast = pic->contrast;
451 bt819_write(client, 0x0c,
452 (decoder->contrast >> 7) & 0xff);
453 bt819_setbit(client, 0x0b, 2,
454 ((decoder->contrast >> 15) & 0x01));
455 }
456
457 if (decoder->sat != pic->colour) {
458 /* We want 0 to 511 we get 0-65535 */
459 decoder->sat = pic->colour;
460 bt819_write(client, 0x0d,
461 (decoder->sat >> 7) & 0xff);
462 bt819_setbit(client, 0x0b, 1,
463 ((decoder->sat >> 15) & 0x01));
464
465 temp = (decoder->sat * 201) / 237;
466 bt819_write(client, 0x0e, (temp >> 7) & 0xff);
467 bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01);
468 }
469
470 if (decoder->hue != pic->hue) {
471 /* We want -128 to 127 we get 0-65535 */
472 decoder->hue = pic->hue;
473 bt819_write(client, 0x0f,
474 128 - (decoder->hue >> 8));
475 }
476 }
477 break;
478
479 default:
480 return -EINVAL;
481 }
482
483 return 0;
484}
485
486/* ----------------------------------------------------------------------- */
487
488/*
489 * Generic i2c probe
490 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
491 */
492static unsigned short normal_i2c[] = {
493 I2C_BT819 >> 1,
494 I2C_CLIENT_END,
495};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
Jean Delvare68cc9d02005-04-02 20:04:41 +0200497static unsigned short ignore = I2C_CLIENT_END;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300498
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499static struct i2c_client_address_data addr_data = {
500 .normal_i2c = normal_i2c,
Jean Delvare68cc9d02005-04-02 20:04:41 +0200501 .probe = &ignore,
502 .ignore = &ignore,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503};
504
505static struct i2c_driver i2c_driver_bt819;
506
507static int
508bt819_detect_client (struct i2c_adapter *adapter,
509 int address,
510 int kind)
511{
512 int i, id;
513 struct bt819 *decoder;
514 struct i2c_client *client;
515
516 dprintk(1,
517 KERN_INFO
518 "saa7111.c: detecting bt819 client on address 0x%x\n",
519 address << 1);
520
521 /* Check if the adapter supports the needed features */
522 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
523 return 0;
524
Panagiotis Issaris74081872006-01-11 19:40:56 -0200525 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 if (client == 0)
527 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 client->addr = address;
529 client->adapter = adapter;
530 client->driver = &i2c_driver_bt819;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531
Panagiotis Issaris74081872006-01-11 19:40:56 -0200532 decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 if (decoder == NULL) {
534 kfree(client);
535 return -ENOMEM;
536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 decoder->norm = VIDEO_MODE_NTSC;
538 decoder->input = 0;
539 decoder->enable = 1;
540 decoder->bright = 32768;
541 decoder->contrast = 32768;
542 decoder->hue = 32768;
543 decoder->sat = 32768;
544 decoder->initialized = 0;
545 i2c_set_clientdata(client, decoder);
546
547 id = bt819_read(client, 0x17);
548 switch (id & 0xf0) {
549 case 0x70:
550 strlcpy(I2C_NAME(client), "bt819a", sizeof(I2C_NAME(client)));
551 break;
552 case 0x60:
553 strlcpy(I2C_NAME(client), "bt817a", sizeof(I2C_NAME(client)));
554 break;
555 case 0x20:
556 strlcpy(I2C_NAME(client), "bt815a", sizeof(I2C_NAME(client)));
557 break;
558 default:
559 dprintk(1,
560 KERN_ERR
561 "bt819: unknown chip version 0x%x (ver 0x%x)\n",
562 id & 0xf0, id & 0x0f);
563 kfree(decoder);
564 kfree(client);
565 return 0;
566 }
567
568 i = i2c_attach_client(client);
569 if (i) {
570 kfree(client);
571 kfree(decoder);
572 return i;
573 }
574
575 i = bt819_init(client);
576 if (i < 0) {
577 dprintk(1, KERN_ERR "%s_attach: init status %d\n",
578 I2C_NAME(client), i);
579 } else {
580 dprintk(1,
581 KERN_INFO
582 "%s_attach: chip version 0x%x at address 0x%x\n",
583 I2C_NAME(client), id & 0x0f,
584 client->addr << 1);
585 }
586
587 return 0;
588}
589
590static int
591bt819_attach_adapter (struct i2c_adapter *adapter)
592{
593 return i2c_probe(adapter, &addr_data, &bt819_detect_client);
594}
595
596static int
597bt819_detach_client (struct i2c_client *client)
598{
599 struct bt819 *decoder = i2c_get_clientdata(client);
600 int err;
601
602 err = i2c_detach_client(client);
603 if (err) {
604 return err;
605 }
606
607 kfree(decoder);
608 kfree(client);
609
610 return 0;
611}
612
613/* ----------------------------------------------------------------------- */
614
615static struct i2c_driver i2c_driver_bt819 = {
Laurent Riffard604f28e2005-11-26 20:43:39 +0100616 .driver = {
Laurent Riffard604f28e2005-11-26 20:43:39 +0100617 .name = "bt819",
618 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
620 .id = I2C_DRIVERID_BT819,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622 .attach_adapter = bt819_attach_adapter,
623 .detach_client = bt819_detach_client,
624 .command = bt819_command,
625};
626
627static int __init
628bt819_init_module (void)
629{
630 return i2c_add_driver(&i2c_driver_bt819);
631}
632
633static void __exit
634bt819_exit (void)
635{
636 i2c_del_driver(&i2c_driver_bt819);
637}
638
639module_init(bt819_init_module);
640module_exit(bt819_exit);