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