linux-bk/drivers/media/video/bt819.c
<<
>>
Prefs
   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 <asm/segment.h>
  47#include <linux/types.h>
  48
  49#include <linux/videodev.h>
  50#include <asm/uaccess.h>
  51
  52MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
  53MODULE_AUTHOR("Mike Bernson & Dave Perks");
  54MODULE_LICENSE("GPL");
  55
  56#include <linux/i2c.h>
  57#include <linux/i2c-dev.h>
  58
  59#define I2C_NAME(s) (s)->name
  60
  61#include <linux/video_decoder.h>
  62
  63static int debug = 0;
  64module_param(debug, int, 0);
  65MODULE_PARM_DESC(debug, "Debug level (0-1)");
  66
  67#define dprintk(num, format, args...) \
  68        do { \
  69                if (debug >= num) \
  70                        printk(format, ##args); \
  71        } while (0)
  72
  73/* ----------------------------------------------------------------------- */
  74
  75struct bt819 {
  76        unsigned char reg[32];
  77
  78        int initialized;
  79        int norm;
  80        int input;
  81        int enable;
  82        int bright;
  83        int contrast;
  84        int hue;
  85        int sat;
  86};
  87
  88struct timing {
  89        int hactive;
  90        int hdelay;
  91        int vactive;
  92        int vdelay;
  93        int hscale;
  94        int vscale;
  95};
  96
  97/* for values, see the bt819 datasheet */
  98static struct timing timing_data[] = {
  99        {864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
 100        {858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
 101};
 102
 103#define   I2C_BT819        0x8a
 104
 105/* ----------------------------------------------------------------------- */
 106
 107static inline int
 108bt819_write (struct i2c_client *client,
 109             u8                 reg,
 110             u8                 value)
 111{
 112        struct bt819 *decoder = i2c_get_clientdata(client);
 113
 114        decoder->reg[reg] = value;
 115        return i2c_smbus_write_byte_data(client, reg, value);
 116}
 117
 118static inline int
 119bt819_setbit (struct i2c_client *client,
 120              u8                 reg,
 121              u8                 bit,
 122              u8                 value)
 123{
 124        struct bt819 *decoder = i2c_get_clientdata(client);
 125
 126        return bt819_write(client, reg,
 127                           (decoder->
 128                            reg[reg] & ~(1 << bit)) |
 129                            (value ? (1 << bit) : 0));
 130}
 131
 132static int
 133bt819_write_block (struct i2c_client *client,
 134                   const u8          *data,
 135                   unsigned int       len)
 136{
 137        int ret = -1;
 138        u8 reg;
 139
 140        /* the bt819 has an autoincrement function, use it if
 141         * the adapter understands raw I2C */
 142        if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 143                /* do raw I2C, not smbus compatible */
 144                struct bt819 *decoder = i2c_get_clientdata(client);
 145                struct i2c_msg msg;
 146                u8 block_data[32];
 147
 148                msg.addr = client->addr;
 149                msg.flags = 0;
 150                while (len >= 2) {
 151                        msg.buf = (char *) block_data;
 152                        msg.len = 0;
 153                        block_data[msg.len++] = reg = data[0];
 154                        do {
 155                                block_data[msg.len++] =
 156                                    decoder->reg[reg++] = data[1];
 157                                len -= 2;
 158                                data += 2;
 159                        } while (len >= 2 && data[0] == reg &&
 160                                 msg.len < 32);
 161                        if ((ret = i2c_transfer(client->adapter,
 162                                                &msg, 1)) < 0)
 163                                break;
 164                }
 165        } else {
 166                /* do some slow I2C emulation kind of thing */
 167                while (len >= 2) {
 168                        reg = *data++;
 169                        if ((ret = bt819_write(client, reg, *data++)) < 0)
 170                                break;
 171                        len -= 2;
 172                }
 173        }
 174
 175        return ret;
 176}
 177
 178static inline int
 179bt819_read (struct i2c_client *client,
 180            u8                 reg)
 181{
 182        return i2c_smbus_read_byte_data(client, reg);
 183}
 184
 185static int
 186bt819_init (struct i2c_client *client)
 187{
 188        struct bt819 *decoder = i2c_get_clientdata(client);
 189
 190        static unsigned char init[] = {
 191                //0x1f, 0x00,     /* Reset */
 192                0x01, 0x59,     /* 0x01 input format */
 193                0x02, 0x00,     /* 0x02 temporal decimation */
 194                0x03, 0x12,     /* 0x03 Cropping msb */
 195                0x04, 0x16,     /* 0x04 Vertical Delay, lsb */
 196                0x05, 0xe0,     /* 0x05 Vertical Active lsb */
 197                0x06, 0x80,     /* 0x06 Horizontal Delay lsb */
 198                0x07, 0xd0,     /* 0x07 Horizontal Active lsb */
 199                0x08, 0x00,     /* 0x08 Horizontal Scaling msb */
 200                0x09, 0xf8,     /* 0x09 Horizontal Scaling lsb */
 201                0x0a, 0x00,     /* 0x0a Brightness control */
 202                0x0b, 0x30,     /* 0x0b Miscellaneous control */
 203                0x0c, 0xd8,     /* 0x0c Luma Gain lsb */
 204                0x0d, 0xfe,     /* 0x0d Chroma Gain (U) lsb */
 205                0x0e, 0xb4,     /* 0x0e Chroma Gain (V) msb */
 206                0x0f, 0x00,     /* 0x0f Hue control */
 207                0x12, 0x04,     /* 0x12 Output Format */
 208                0x13, 0x20,     /* 0x13 Vertial Scaling msb 0x00
 209                                           chroma comb OFF, line drop scaling, interlace scaling
 210                                           BUG? Why does turning the chroma comb on fuck up color?
 211                                           Bug in the bt819 stepping on my board?
 212                                        */
 213                0x14, 0x00,     /* 0x14 Vertial Scaling lsb */
 214                0x16, 0x07,     /* 0x16 Video Timing Polarity 
 215                                           ACTIVE=active low
 216                                           FIELD: high=odd, 
 217                                           vreset=active high,
 218                                           hreset=active high */
 219                0x18, 0x68,     /* 0x18 AGC Delay */
 220                0x19, 0x5d,     /* 0x19 Burst Gate Delay */
 221                0x1a, 0x80,     /* 0x1a ADC Interface */
 222        };
 223
 224        struct timing *timing = &timing_data[decoder->norm];
 225
 226        init[0x03 * 2 - 1] =
 227            (((timing->vdelay >> 8) & 0x03) << 6) | (((timing->
 228                                                       vactive >> 8) &
 229                                                      0x03) << 4) |
 230            (((timing->hdelay >> 8) & 0x03) << 2) | ((timing->
 231                                                      hactive >> 8) &
 232                                                     0x03);
 233        init[0x04 * 2 - 1] = timing->vdelay & 0xff;
 234        init[0x05 * 2 - 1] = timing->vactive & 0xff;
 235        init[0x06 * 2 - 1] = timing->hdelay & 0xff;
 236        init[0x07 * 2 - 1] = timing->hactive & 0xff;
 237        init[0x08 * 2 - 1] = timing->hscale >> 8;
 238        init[0x09 * 2 - 1] = timing->hscale & 0xff;
 239        init[0x19*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};
 502static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 503
 504static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
 505static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
 506static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
 507static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
 508static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
 509                                                                                
 510static struct i2c_client_address_data addr_data = {
 511        .normal_i2c             = normal_i2c,
 512        .normal_i2c_range       = normal_i2c_range,
 513        .probe                  = probe,
 514        .probe_range            = probe_range,
 515        .ignore                 = ignore,
 516        .ignore_range           = ignore_range,
 517        .force                  = force
 518};
 519
 520static int bt819_i2c_id = 0;
 521static struct i2c_driver i2c_driver_bt819;
 522
 523static int
 524bt819_detect_client (struct i2c_adapter *adapter,
 525                     int                 address,
 526                     int                 kind)
 527{
 528        int i, id;
 529        struct bt819 *decoder;
 530        struct i2c_client *client;
 531
 532        dprintk(1,
 533                KERN_INFO
 534                "saa7111.c: detecting bt819 client on address 0x%x\n",
 535                address << 1);
 536
 537        /* Check if the adapter supports the needed features */
 538        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 539                return 0;
 540
 541        client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
 542        if (client == 0)
 543                return -ENOMEM;
 544        memset(client, 0, sizeof(struct i2c_client));
 545        client->addr = address;
 546        client->adapter = adapter;
 547        client->driver = &i2c_driver_bt819;
 548        client->flags = I2C_CLIENT_ALLOW_USE;
 549        client->id = bt819_i2c_id++;
 550
 551        decoder = kmalloc(sizeof(struct bt819), GFP_KERNEL);
 552        if (decoder == NULL) {
 553                kfree(client);
 554                return -ENOMEM;
 555        }
 556
 557        memset(decoder, 0, sizeof(struct bt819));
 558        decoder->norm = VIDEO_MODE_NTSC;
 559        decoder->input = 0;
 560        decoder->enable = 1;
 561        decoder->bright = 32768;
 562        decoder->contrast = 32768;
 563        decoder->hue = 32768;
 564        decoder->sat = 32768;
 565        decoder->initialized = 0;
 566        i2c_set_clientdata(client, decoder);
 567
 568        id = bt819_read(client, 0x17);
 569        switch (id & 0xf0) {
 570        case 0x70:
 571                snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
 572                         "bt819a[%d]", client->id);
 573                break;
 574        case 0x60:
 575                snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
 576                         "bt817a[%d]", client->id);
 577                break;
 578        case 0x20:
 579                snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
 580                         "bt815a[%d]", client->id);
 581                break;
 582        default:
 583                dprintk(1,
 584                        KERN_ERR
 585                        "bt819: unknown chip version 0x%x (ver 0x%x)\n",
 586                        id & 0xf0, id & 0x0f);
 587                kfree(decoder);
 588                kfree(client);
 589                return 0;
 590        }
 591
 592        i = i2c_attach_client(client);
 593        if (i) {
 594                kfree(client);
 595                kfree(decoder);
 596                return i;
 597        }
 598
 599        i = bt819_init(client);
 600        if (i < 0) {
 601                dprintk(1, KERN_ERR "%s_attach: init status %d\n",
 602                        I2C_NAME(client), i);
 603        } else {
 604                dprintk(1,
 605                        KERN_INFO
 606                        "%s_attach: chip version 0x%x at address 0x%x\n",
 607                        I2C_NAME(client), id & 0x0f,
 608                        client->addr << 1);
 609        }
 610
 611        return 0;
 612}
 613
 614static int
 615bt819_attach_adapter (struct i2c_adapter *adapter)
 616{
 617        return i2c_probe(adapter, &addr_data, &bt819_detect_client);
 618}
 619
 620static int
 621bt819_detach_client (struct i2c_client *client)
 622{
 623        struct bt819 *decoder = i2c_get_clientdata(client);
 624        int err;
 625
 626        err = i2c_detach_client(client);
 627        if (err) {
 628                return err;
 629        }
 630
 631        kfree(decoder);
 632        kfree(client);
 633
 634        return 0;
 635}
 636
 637/* ----------------------------------------------------------------------- */
 638
 639static struct i2c_driver i2c_driver_bt819 = {
 640        .owner = THIS_MODULE,
 641        .name = "bt819",
 642
 643        .id = I2C_DRIVERID_BT819,
 644        .flags = I2C_DF_NOTIFY,
 645
 646        .attach_adapter = bt819_attach_adapter,
 647        .detach_client = bt819_detach_client,
 648        .command = bt819_command,
 649};
 650
 651static int __init
 652bt819_init_module (void)
 653{
 654        return i2c_add_driver(&i2c_driver_bt819);
 655}
 656
 657static void __exit
 658bt819_exit (void)
 659{
 660        i2c_del_driver(&i2c_driver_bt819);
 661}
 662
 663module_init(bt819_init_module);
 664module_exit(bt819_exit);
 665
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.