Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.16-rc2 646 lines 15 kB view raw
1/* 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> 46#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); 144 struct i2c_msg msg; 145 u8 block_data[32]; 146 147 msg.addr = client->addr; 148 msg.flags = 0; 149 while (len >= 2) { 150 msg.buf = (char *) block_data; 151 msg.len = 0; 152 block_data[msg.len++] = reg = data[0]; 153 do { 154 block_data[msg.len++] = 155 decoder->reg[reg++] = data[1]; 156 len -= 2; 157 data += 2; 158 } while (len >= 2 && data[0] == reg && 159 msg.len < 32); 160 if ((ret = i2c_transfer(client->adapter, 161 &msg, 1)) < 0) 162 break; 163 } 164 } else { 165 /* do some slow I2C emulation kind of thing */ 166 while (len >= 2) { 167 reg = *data++; 168 if ((ret = bt819_write(client, reg, *data++)) < 0) 169 break; 170 len -= 2; 171 } 172 } 173 174 return ret; 175} 176 177static inline int 178bt819_read (struct i2c_client *client, 179 u8 reg) 180{ 181 return i2c_smbus_read_byte_data(client, reg); 182} 183 184static int 185bt819_init (struct i2c_client *client) 186{ 187 struct bt819 *decoder = i2c_get_clientdata(client); 188 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? 211 */ 212 0x14, 0x00, /* 0x14 Vertial Scaling lsb */ 213 0x16, 0x07, /* 0x16 Video Timing Polarity 214 ACTIVE=active low 215 FIELD: high=odd, 216 vreset=active high, 217 hreset=active high */ 218 0x18, 0x68, /* 0x18 AGC Delay */ 219 0x19, 0x5d, /* 0x19 Burst Gate Delay */ 220 0x1a, 0x80, /* 0x1a ADC Interface */ 221 }; 222 223 struct timing *timing = &timing_data[decoder->norm]; 224 225 init[0x03 * 2 - 1] = 226 (((timing->vdelay >> 8) & 0x03) << 6) | (((timing-> 227 vactive >> 8) & 228 0x03) << 4) | 229 (((timing->hdelay >> 8) & 0x03) << 2) | ((timing-> 230 hactive >> 8) & 231 0x03); 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 */ 240 /* reset */ 241 bt819_write(client, 0x1f, 0x00); 242 mdelay(1); 243 244 /* init */ 245 return bt819_write_block(client, init, sizeof(init)); 246 247} 248 249/* ----------------------------------------------------------------------- */ 250 251static int 252bt819_command (struct i2c_client *client, 253 unsigned int cmd, 254 void *arg) 255{ 256 int temp; 257 258 struct bt819 *decoder = i2c_get_clientdata(client); 259 260 if (!decoder->initialized) { // First call to bt819_init could be 261 bt819_init(client); // without #FRST = 0 262 decoder->initialized = 1; 263 } 264 265 switch (cmd) { 266 267 case 0: 268 /* This is just for testing!!! */ 269 bt819_init(client); 270 break; 271 272 case DECODER_GET_CAPABILITIES: 273 { 274 struct video_decoder_capability *cap = arg; 275 276 cap->flags = VIDEO_DECODER_PAL | 277 VIDEO_DECODER_NTSC | 278 VIDEO_DECODER_AUTO | 279 VIDEO_DECODER_CCIR; 280 cap->inputs = 8; 281 cap->outputs = 1; 282 } 283 break; 284 285 case DECODER_GET_STATUS: 286 { 287 int *iarg = arg; 288 int status; 289 int res; 290 291 status = bt819_read(client, 0x00); 292 res = 0; 293 if ((status & 0x80)) { 294 res |= DECODER_STATUS_GOOD; 295 } 296 switch (decoder->norm) { 297 case VIDEO_MODE_NTSC: 298 res |= DECODER_STATUS_NTSC; 299 break; 300 case VIDEO_MODE_PAL: 301 res |= DECODER_STATUS_PAL; 302 break; 303 default: 304 case VIDEO_MODE_AUTO: 305 if ((status & 0x10)) { 306 res |= DECODER_STATUS_PAL; 307 } else { 308 res |= DECODER_STATUS_NTSC; 309 } 310 break; 311 } 312 res |= DECODER_STATUS_COLOR; 313 *iarg = res; 314 315 dprintk(1, KERN_INFO "%s: get status %x\n", I2C_NAME(client), 316 *iarg); 317 } 318 break; 319 320 case DECODER_SET_NORM: 321 { 322 int *iarg = arg; 323 struct timing *timing = NULL; 324 325 dprintk(1, KERN_INFO "%s: set norm %x\n", I2C_NAME(client), 326 *iarg); 327 328 switch (*iarg) { 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]; 337 break; 338 case VIDEO_MODE_PAL: 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]; 346 break; 347 case VIDEO_MODE_AUTO: 348 bt819_setbit(client, 0x01, 0, 0); 349 bt819_setbit(client, 0x01, 1, 0); 350 break; 351 default: 352 dprintk(1, 353 KERN_ERR 354 "%s: unsupported norm %d\n", 355 I2C_NAME(client), *iarg); 356 return -EINVAL; 357 } 358 359 if (timing) { 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); 371 } 372 373 decoder->norm = *iarg; 374 } 375 break; 376 377 case DECODER_SET_INPUT: 378 { 379 int *iarg = arg; 380 381 dprintk(1, KERN_INFO "%s: set input %x\n", I2C_NAME(client), 382 *iarg); 383 384 if (*iarg < 0 || *iarg > 7) { 385 return -EINVAL; 386 } 387 388 if (decoder->input != *iarg) { 389 decoder->input = *iarg; 390 /* select mode */ 391 if (decoder->input == 0) { 392 bt819_setbit(client, 0x0b, 6, 0); 393 bt819_setbit(client, 0x1a, 1, 1); 394 } else { 395 bt819_setbit(client, 0x0b, 6, 1); 396 bt819_setbit(client, 0x1a, 1, 0); 397 } 398 } 399 } 400 break; 401 402 case DECODER_SET_OUTPUT: 403 { 404 int *iarg = arg; 405 406 dprintk(1, KERN_INFO "%s: set output %x\n", I2C_NAME(client), 407 *iarg); 408 409 /* not much choice of outputs */ 410 if (*iarg != 0) { 411 return -EINVAL; 412 } 413 } 414 break; 415 416 case DECODER_ENABLE_OUTPUT: 417 { 418 int *iarg = arg; 419 int enable = (*iarg != 0); 420 421 dprintk(1, KERN_INFO "%s: enable output %x\n", 422 I2C_NAME(client), *iarg); 423 424 if (decoder->enable != enable) { 425 decoder->enable = enable; 426 427 if (decoder->enable) { 428 bt819_setbit(client, 0x16, 7, 0); 429 } else { 430 bt819_setbit(client, 0x16, 7, 1); 431 } 432 } 433 } 434 break; 435 436 case DECODER_SET_PICTURE: 437 { 438 struct video_picture *pic = arg; 439 440 dprintk(1, 441 KERN_INFO 442 "%s: set picture brightness %d contrast %d colour %d\n", 443 I2C_NAME(client), pic->brightness, pic->contrast, 444 pic->colour); 445 446 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); 452 } 453 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)); 461 } 462 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)); 470 471 temp = (decoder->sat * 201) / 237; 472 bt819_write(client, 0x0e, (temp >> 7) & 0xff); 473 bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01); 474 } 475 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)); 481 } 482 } 483 break; 484 485 default: 486 return -EINVAL; 487 } 488 489 return 0; 490} 491 492/* ----------------------------------------------------------------------- */ 493 494/* 495 * Generic i2c probe 496 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' 497 */ 498static unsigned short normal_i2c[] = { 499 I2C_BT819 >> 1, 500 I2C_CLIENT_END, 501}; 502 503static unsigned short ignore = I2C_CLIENT_END; 504 505static struct i2c_client_address_data addr_data = { 506 .normal_i2c = normal_i2c, 507 .probe = &ignore, 508 .ignore = &ignore, 509}; 510 511static struct i2c_driver i2c_driver_bt819; 512 513static int 514bt819_detect_client (struct i2c_adapter *adapter, 515 int address, 516 int kind) 517{ 518 int i, id; 519 struct bt819 *decoder; 520 struct i2c_client *client; 521 522 dprintk(1, 523 KERN_INFO 524 "saa7111.c: detecting bt819 client on address 0x%x\n", 525 address << 1); 526 527 /* Check if the adapter supports the needed features */ 528 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 529 return 0; 530 531 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); 532 if (client == 0) 533 return -ENOMEM; 534 client->addr = address; 535 client->adapter = adapter; 536 client->driver = &i2c_driver_bt819; 537 538 decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL); 539 if (decoder == NULL) { 540 kfree(client); 541 return -ENOMEM; 542 } 543 decoder->norm = VIDEO_MODE_NTSC; 544 decoder->input = 0; 545 decoder->enable = 1; 546 decoder->bright = 32768; 547 decoder->contrast = 32768; 548 decoder->hue = 32768; 549 decoder->sat = 32768; 550 decoder->initialized = 0; 551 i2c_set_clientdata(client, decoder); 552 553 id = bt819_read(client, 0x17); 554 switch (id & 0xf0) { 555 case 0x70: 556 strlcpy(I2C_NAME(client), "bt819a", sizeof(I2C_NAME(client))); 557 break; 558 case 0x60: 559 strlcpy(I2C_NAME(client), "bt817a", sizeof(I2C_NAME(client))); 560 break; 561 case 0x20: 562 strlcpy(I2C_NAME(client), "bt815a", sizeof(I2C_NAME(client))); 563 break; 564 default: 565 dprintk(1, 566 KERN_ERR 567 "bt819: unknown chip version 0x%x (ver 0x%x)\n", 568 id & 0xf0, id & 0x0f); 569 kfree(decoder); 570 kfree(client); 571 return 0; 572 } 573 574 i = i2c_attach_client(client); 575 if (i) { 576 kfree(client); 577 kfree(decoder); 578 return i; 579 } 580 581 i = bt819_init(client); 582 if (i < 0) { 583 dprintk(1, KERN_ERR "%s_attach: init status %d\n", 584 I2C_NAME(client), i); 585 } else { 586 dprintk(1, 587 KERN_INFO 588 "%s_attach: chip version 0x%x at address 0x%x\n", 589 I2C_NAME(client), id & 0x0f, 590 client->addr << 1); 591 } 592 593 return 0; 594} 595 596static int 597bt819_attach_adapter (struct i2c_adapter *adapter) 598{ 599 return i2c_probe(adapter, &addr_data, &bt819_detect_client); 600} 601 602static int 603bt819_detach_client (struct i2c_client *client) 604{ 605 struct bt819 *decoder = i2c_get_clientdata(client); 606 int err; 607 608 err = i2c_detach_client(client); 609 if (err) { 610 return err; 611 } 612 613 kfree(decoder); 614 kfree(client); 615 616 return 0; 617} 618 619/* ----------------------------------------------------------------------- */ 620 621static struct i2c_driver i2c_driver_bt819 = { 622 .driver = { 623 .name = "bt819", 624 }, 625 626 .id = I2C_DRIVERID_BT819, 627 628 .attach_adapter = bt819_attach_adapter, 629 .detach_client = bt819_detach_client, 630 .command = bt819_command, 631}; 632 633static int __init 634bt819_init_module (void) 635{ 636 return i2c_add_driver(&i2c_driver_bt819); 637} 638 639static void __exit 640bt819_exit (void) 641{ 642 i2c_del_driver(&i2c_driver_bt819); 643} 644 645module_init(bt819_init_module); 646module_exit(bt819_exit);