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