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