linux/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/types.h>
  33#include <linux/ioctl.h>
  34#include <linux/delay.h>
  35#include <linux/i2c.h>
  36#include <linux/videodev2.h>
  37#include <linux/slab.h>
  38#include <media/v4l2-device.h>
  39#include <media/v4l2-chip-ident.h>
  40#include <media/bt819.h>
  41
  42MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
  43MODULE_AUTHOR("Mike Bernson & Dave Perks");
  44MODULE_LICENSE("GPL");
  45
  46static int debug;
  47module_param(debug, int, 0);
  48MODULE_PARM_DESC(debug, "Debug level (0-1)");
  49
  50
  51/* ----------------------------------------------------------------------- */
  52
  53struct bt819 {
  54        struct v4l2_subdev sd;
  55        unsigned char reg[32];
  56
  57        v4l2_std_id norm;
  58        int ident;
  59        int input;
  60        int enable;
  61        int bright;
  62        int contrast;
  63        int hue;
  64        int sat;
  65};
  66
  67static inline struct bt819 *to_bt819(struct v4l2_subdev *sd)
  68{
  69        return container_of(sd, struct bt819, sd);
  70}
  71
  72struct timing {
  73        int hactive;
  74        int hdelay;
  75        int vactive;
  76        int vdelay;
  77        int hscale;
  78        int vscale;
  79};
  80
  81/* for values, see the bt819 datasheet */
  82static struct timing timing_data[] = {
  83        {864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
  84        {858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
  85};
  86
  87/* ----------------------------------------------------------------------- */
  88
  89static inline int bt819_write(struct bt819 *decoder, u8 reg, u8 value)
  90{
  91        struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
  92
  93        decoder->reg[reg] = value;
  94        return i2c_smbus_write_byte_data(client, reg, value);
  95}
  96
  97static inline int bt819_setbit(struct bt819 *decoder, u8 reg, u8 bit, u8 value)
  98{
  99        return bt819_write(decoder, reg,
 100                (decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0));
 101}
 102
 103static int bt819_write_block(struct bt819 *decoder, const u8 *data, unsigned int len)
 104{
 105        struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
 106        int ret = -1;
 107        u8 reg;
 108
 109        /* the bt819 has an autoincrement function, use it if
 110         * the adapter understands raw I2C */
 111        if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 112                /* do raw I2C, not smbus compatible */
 113                u8 block_data[32];
 114                int block_len;
 115
 116                while (len >= 2) {
 117                        block_len = 0;
 118                        block_data[block_len++] = reg = data[0];
 119                        do {
 120                                block_data[block_len++] =
 121                                    decoder->reg[reg++] = data[1];
 122                                len -= 2;
 123                                data += 2;
 124                        } while (len >= 2 && data[0] == reg && block_len < 32);
 125                        ret = i2c_master_send(client, block_data, block_len);
 126                        if (ret < 0)
 127                                break;
 128                }
 129        } else {
 130                /* do some slow I2C emulation kind of thing */
 131                while (len >= 2) {
 132                        reg = *data++;
 133                        ret = bt819_write(decoder, reg, *data++);
 134                        if (ret < 0)
 135                                break;
 136                        len -= 2;
 137                }
 138        }
 139
 140        return ret;
 141}
 142
 143static inline int bt819_read(struct bt819 *decoder, u8 reg)
 144{
 145        struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
 146
 147        return i2c_smbus_read_byte_data(client, reg);
 148}
 149
 150static int bt819_init(struct v4l2_subdev *sd)
 151{
 152        static unsigned char init[] = {
 153                /*0x1f, 0x00,*/     /* Reset */
 154                0x01, 0x59,     /* 0x01 input format */
 155                0x02, 0x00,     /* 0x02 temporal decimation */
 156                0x03, 0x12,     /* 0x03 Cropping msb */
 157                0x04, 0x16,     /* 0x04 Vertical Delay, lsb */
 158                0x05, 0xe0,     /* 0x05 Vertical Active lsb */
 159                0x06, 0x80,     /* 0x06 Horizontal Delay lsb */
 160                0x07, 0xd0,     /* 0x07 Horizontal Active lsb */
 161                0x08, 0x00,     /* 0x08 Horizontal Scaling msb */
 162                0x09, 0xf8,     /* 0x09 Horizontal Scaling lsb */
 163                0x0a, 0x00,     /* 0x0a Brightness control */
 164                0x0b, 0x30,     /* 0x0b Miscellaneous control */
 165                0x0c, 0xd8,     /* 0x0c Luma Gain lsb */
 166                0x0d, 0xfe,     /* 0x0d Chroma Gain (U) lsb */
 167                0x0e, 0xb4,     /* 0x0e Chroma Gain (V) msb */
 168                0x0f, 0x00,     /* 0x0f Hue control */
 169                0x12, 0x04,     /* 0x12 Output Format */
 170                0x13, 0x20,     /* 0x13 Vertial Scaling msb 0x00
 171                                           chroma comb OFF, line drop scaling, interlace scaling
 172                                           BUG? Why does turning the chroma comb on fuck up color?
 173                                           Bug in the bt819 stepping on my board?
 174                                        */
 175                0x14, 0x00,     /* 0x14 Vertial Scaling lsb */
 176                0x16, 0x07,     /* 0x16 Video Timing Polarity
 177                                           ACTIVE=active low
 178                                           FIELD: high=odd,
 179                                           vreset=active high,
 180                                           hreset=active high */
 181                0x18, 0x68,     /* 0x18 AGC Delay */
 182                0x19, 0x5d,     /* 0x19 Burst Gate Delay */
 183                0x1a, 0x80,     /* 0x1a ADC Interface */
 184        };
 185
 186        struct bt819 *decoder = to_bt819(sd);
 187        struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0];
 188
 189        init[0x03 * 2 - 1] =
 190            (((timing->vdelay >> 8) & 0x03) << 6) |
 191            (((timing->vactive >> 8) & 0x03) << 4) |
 192            (((timing->hdelay >> 8) & 0x03) << 2) |
 193            ((timing->hactive >> 8) & 0x03);
 194        init[0x04 * 2 - 1] = timing->vdelay & 0xff;
 195        init[0x05 * 2 - 1] = timing->vactive & 0xff;
 196        init[0x06 * 2 - 1] = timing->hdelay & 0xff;
 197        init[0x07 * 2 - 1] = timing->hactive & 0xff;
 198        init[0x08 * 2 - 1] = timing->hscale >> 8;
 199        init[0x09 * 2 - 1] = timing->hscale & 0xff;
 200        /* 0x15 in array is address 0x19 */
 201        init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93;      /* Chroma burst delay */
 202        /* reset */
 203        bt819_write(decoder, 0x1f, 0x00);
 204        mdelay(1);
 205
 206        /* init */
 207        return bt819_write_block(decoder, init, sizeof(init));
 208}
 209
 210/* ----------------------------------------------------------------------- */
 211
 212static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
 213{
 214        struct bt819 *decoder = to_bt819(sd);
 215        int status = bt819_read(decoder, 0x00);
 216        int res = V4L2_IN_ST_NO_SIGNAL;
 217        v4l2_std_id std;
 218
 219        if ((status & 0x80))
 220                res = 0;
 221
 222        if ((status & 0x10))
 223                std = V4L2_STD_PAL;
 224        else
 225                std = V4L2_STD_NTSC;
 226        if (pstd)
 227                *pstd = std;
 228        if (pstatus)
 229                *pstatus = status;
 230
 231        v4l2_dbg(1, debug, sd, "get status %x\n", status);
 232        return 0;
 233}
 234
 235static int bt819_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
 236{
 237        return bt819_status(sd, NULL, std);
 238}
 239
 240static int bt819_g_input_status(struct v4l2_subdev *sd, u32 *status)
 241{
 242        return bt819_status(sd, status, NULL);
 243}
 244
 245static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
 246{
 247        struct bt819 *decoder = to_bt819(sd);
 248        struct timing *timing = NULL;
 249
 250        v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
 251
 252        if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
 253                v4l2_err(sd, "no notify found!\n");
 254
 255        if (std & V4L2_STD_NTSC) {
 256                v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
 257                bt819_setbit(decoder, 0x01, 0, 1);
 258                bt819_setbit(decoder, 0x01, 1, 0);
 259                bt819_setbit(decoder, 0x01, 5, 0);
 260                bt819_write(decoder, 0x18, 0x68);
 261                bt819_write(decoder, 0x19, 0x5d);
 262                /* bt819_setbit(decoder, 0x1a,  5, 1); */
 263                timing = &timing_data[1];
 264        } else if (std & V4L2_STD_PAL) {
 265                v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
 266                bt819_setbit(decoder, 0x01, 0, 1);
 267                bt819_setbit(decoder, 0x01, 1, 1);
 268                bt819_setbit(decoder, 0x01, 5, 1);
 269                bt819_write(decoder, 0x18, 0x7f);
 270                bt819_write(decoder, 0x19, 0x72);
 271                /* bt819_setbit(decoder, 0x1a,  5, 0); */
 272                timing = &timing_data[0];
 273        } else {
 274                v4l2_dbg(1, debug, sd, "unsupported norm %llx\n",
 275                                (unsigned long long)std);
 276                return -EINVAL;
 277        }
 278        bt819_write(decoder, 0x03,
 279                        (((timing->vdelay >> 8) & 0x03) << 6) |
 280                        (((timing->vactive >> 8) & 0x03) << 4) |
 281                        (((timing->hdelay >> 8) & 0x03) << 2) |
 282                        ((timing->hactive >> 8) & 0x03));
 283        bt819_write(decoder, 0x04, timing->vdelay & 0xff);
 284        bt819_write(decoder, 0x05, timing->vactive & 0xff);
 285        bt819_write(decoder, 0x06, timing->hdelay & 0xff);
 286        bt819_write(decoder, 0x07, timing->hactive & 0xff);
 287        bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff);
 288        bt819_write(decoder, 0x09, timing->hscale & 0xff);
 289        decoder->norm = std;
 290        v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
 291        return 0;
 292}
 293
 294static int bt819_s_routing(struct v4l2_subdev *sd,
 295                           u32 input, u32 output, u32 config)
 296{
 297        struct bt819 *decoder = to_bt819(sd);
 298
 299        v4l2_dbg(1, debug, sd, "set input %x\n", input);
 300
 301        if (input > 7)
 302                return -EINVAL;
 303
 304        if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
 305                v4l2_err(sd, "no notify found!\n");
 306
 307        if (decoder->input != input) {
 308                v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
 309                decoder->input = input;
 310                /* select mode */
 311                if (decoder->input == 0) {
 312                        bt819_setbit(decoder, 0x0b, 6, 0);
 313                        bt819_setbit(decoder, 0x1a, 1, 1);
 314                } else {
 315                        bt819_setbit(decoder, 0x0b, 6, 1);
 316                        bt819_setbit(decoder, 0x1a, 1, 0);
 317                }
 318                v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
 319        }
 320        return 0;
 321}
 322
 323static int bt819_s_stream(struct v4l2_subdev *sd, int enable)
 324{
 325        struct bt819 *decoder = to_bt819(sd);
 326
 327        v4l2_dbg(1, debug, sd, "enable output %x\n", enable);
 328
 329        if (decoder->enable != enable) {
 330                decoder->enable = enable;
 331                bt819_setbit(decoder, 0x16, 7, !enable);
 332        }
 333        return 0;
 334}
 335
 336static int bt819_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
 337{
 338        switch (qc->id) {
 339        case V4L2_CID_BRIGHTNESS:
 340                v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
 341                break;
 342
 343        case V4L2_CID_CONTRAST:
 344                v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
 345                break;
 346
 347        case V4L2_CID_SATURATION:
 348                v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
 349                break;
 350
 351        case V4L2_CID_HUE:
 352                v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
 353                break;
 354
 355        default:
 356                return -EINVAL;
 357        }
 358        return 0;
 359}
 360
 361static int bt819_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 362{
 363        struct bt819 *decoder = to_bt819(sd);
 364        int temp;
 365
 366        switch (ctrl->id) {
 367        case V4L2_CID_BRIGHTNESS:
 368                if (decoder->bright == ctrl->value)
 369                        break;
 370                decoder->bright = ctrl->value;
 371                bt819_write(decoder, 0x0a, decoder->bright);
 372                break;
 373
 374        case V4L2_CID_CONTRAST:
 375                if (decoder->contrast == ctrl->value)
 376                        break;
 377                decoder->contrast = ctrl->value;
 378                bt819_write(decoder, 0x0c, decoder->contrast & 0xff);
 379                bt819_setbit(decoder, 0x0b, 2, ((decoder->contrast >> 8) & 0x01));
 380                break;
 381
 382        case V4L2_CID_SATURATION:
 383                if (decoder->sat == ctrl->value)
 384                        break;
 385                decoder->sat = ctrl->value;
 386                bt819_write(decoder, 0x0d, (decoder->sat >> 7) & 0xff);
 387                bt819_setbit(decoder, 0x0b, 1, ((decoder->sat >> 15) & 0x01));
 388
 389                /* Ratio between U gain and V gain must stay the same as
 390                   the ratio between the default U and V gain values. */
 391                temp = (decoder->sat * 180) / 254;
 392                bt819_write(decoder, 0x0e, (temp >> 7) & 0xff);
 393                bt819_setbit(decoder, 0x0b, 0, (temp >> 15) & 0x01);
 394                break;
 395
 396        case V4L2_CID_HUE:
 397                if (decoder->hue == ctrl->value)
 398                        break;
 399                decoder->hue = ctrl->value;
 400                bt819_write(decoder, 0x0f, decoder->hue);
 401                break;
 402
 403        default:
 404                return -EINVAL;
 405        }
 406        return 0;
 407}
 408
 409static int bt819_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 410{
 411        struct bt819 *decoder = to_bt819(sd);
 412
 413        switch (ctrl->id) {
 414        case V4L2_CID_BRIGHTNESS:
 415                ctrl->value = decoder->bright;
 416                break;
 417        case V4L2_CID_CONTRAST:
 418                ctrl->value = decoder->contrast;
 419                break;
 420        case V4L2_CID_SATURATION:
 421                ctrl->value = decoder->sat;
 422                break;
 423        case V4L2_CID_HUE:
 424                ctrl->value = decoder->hue;
 425                break;
 426        default:
 427                return -EINVAL;
 428        }
 429        return 0;
 430}
 431
 432static int bt819_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 433{
 434        struct bt819 *decoder = to_bt819(sd);
 435        struct i2c_client *client = v4l2_get_subdevdata(sd);
 436
 437        return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0);
 438}
 439
 440/* ----------------------------------------------------------------------- */
 441
 442static const struct v4l2_subdev_core_ops bt819_core_ops = {
 443        .g_chip_ident = bt819_g_chip_ident,
 444        .g_ctrl = bt819_g_ctrl,
 445        .s_ctrl = bt819_s_ctrl,
 446        .queryctrl = bt819_queryctrl,
 447        .s_std = bt819_s_std,
 448};
 449
 450static const struct v4l2_subdev_video_ops bt819_video_ops = {
 451        .s_routing = bt819_s_routing,
 452        .s_stream = bt819_s_stream,
 453        .querystd = bt819_querystd,
 454        .g_input_status = bt819_g_input_status,
 455};
 456
 457static const struct v4l2_subdev_ops bt819_ops = {
 458        .core = &bt819_core_ops,
 459        .video = &bt819_video_ops,
 460};
 461
 462/* ----------------------------------------------------------------------- */
 463
 464static int bt819_probe(struct i2c_client *client,
 465                        const struct i2c_device_id *id)
 466{
 467        int i, ver;
 468        struct bt819 *decoder;
 469        struct v4l2_subdev *sd;
 470        const char *name;
 471
 472        /* Check if the adapter supports the needed features */
 473        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 474                return -ENODEV;
 475
 476        decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
 477        if (decoder == NULL)
 478                return -ENOMEM;
 479        sd = &decoder->sd;
 480        v4l2_i2c_subdev_init(sd, client, &bt819_ops);
 481
 482        ver = bt819_read(decoder, 0x17);
 483        switch (ver & 0xf0) {
 484        case 0x70:
 485                name = "bt819a";
 486                decoder->ident = V4L2_IDENT_BT819A;
 487                break;
 488        case 0x60:
 489                name = "bt817a";
 490                decoder->ident = V4L2_IDENT_BT817A;
 491                break;
 492        case 0x20:
 493                name = "bt815a";
 494                decoder->ident = V4L2_IDENT_BT815A;
 495                break;
 496        default:
 497                v4l2_dbg(1, debug, sd,
 498                        "unknown chip version 0x%02x\n", ver);
 499                return -ENODEV;
 500        }
 501
 502        v4l_info(client, "%s found @ 0x%x (%s)\n", name,
 503                        client->addr << 1, client->adapter->name);
 504
 505        decoder->norm = V4L2_STD_NTSC;
 506        decoder->input = 0;
 507        decoder->enable = 1;
 508        decoder->bright = 0;
 509        decoder->contrast = 0xd8;       /* 100% of original signal */
 510        decoder->hue = 0;
 511        decoder->sat = 0xfe;            /* 100% of original signal */
 512
 513        i = bt819_init(sd);
 514        if (i < 0)
 515                v4l2_dbg(1, debug, sd, "init status %d\n", i);
 516        return 0;
 517}
 518
 519static int bt819_remove(struct i2c_client *client)
 520{
 521        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 522
 523        v4l2_device_unregister_subdev(sd);
 524        kfree(to_bt819(sd));
 525        return 0;
 526}
 527
 528/* ----------------------------------------------------------------------- */
 529
 530static const struct i2c_device_id bt819_id[] = {
 531        { "bt819a", 0 },
 532        { "bt817a", 0 },
 533        { "bt815a", 0 },
 534        { }
 535};
 536MODULE_DEVICE_TABLE(i2c, bt819_id);
 537
 538static struct i2c_driver bt819_driver = {
 539        .driver = {
 540                .owner  = THIS_MODULE,
 541                .name   = "bt819",
 542        },
 543        .probe          = bt819_probe,
 544        .remove         = bt819_remove,
 545        .id_table       = bt819_id,
 546};
 547
 548static __init int init_bt819(void)
 549{
 550        return i2c_add_driver(&bt819_driver);
 551}
 552
 553static __exit void exit_bt819(void)
 554{
 555        i2c_del_driver(&bt819_driver);
 556}
 557
 558module_init(init_bt819);
 559module_exit(exit_bt819);
 560