linux/drivers/media/i2c/saa7110.c
<<
>>
Prefs
   1/*
   2 * saa7110 - Philips SAA7110(A) video decoder driver
   3 *
   4 * Copyright (C) 1998 Pauline Middelink <middelin@polyware.nl>
   5 *
   6 * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
   7 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
   8 *    - some corrections for Pinnacle Systems Inc. DC10plus card.
   9 *
  10 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
  11 *    - moved over to linux>=2.4.x i2c protocol (1/1/2003)
  12 *
  13 * This program is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2 of the License, or
  16 * (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 */
  23
  24#include <linux/module.h>
  25#include <linux/init.h>
  26#include <linux/types.h>
  27#include <linux/delay.h>
  28#include <linux/slab.h>
  29#include <linux/wait.h>
  30#include <linux/uaccess.h>
  31#include <linux/i2c.h>
  32#include <linux/videodev2.h>
  33#include <media/v4l2-device.h>
  34#include <media/v4l2-ctrls.h>
  35
  36MODULE_DESCRIPTION("Philips SAA7110 video decoder driver");
  37MODULE_AUTHOR("Pauline Middelink");
  38MODULE_LICENSE("GPL");
  39
  40
  41static int debug;
  42module_param(debug, int, 0);
  43MODULE_PARM_DESC(debug, "Debug level (0-1)");
  44
  45#define SAA7110_MAX_INPUT       9       /* 6 CVBS, 3 SVHS */
  46#define SAA7110_MAX_OUTPUT      1       /* 1 YUV */
  47
  48#define SAA7110_NR_REG          0x35
  49
  50struct saa7110 {
  51        struct v4l2_subdev sd;
  52        struct v4l2_ctrl_handler hdl;
  53        u8 reg[SAA7110_NR_REG];
  54
  55        v4l2_std_id norm;
  56        int input;
  57        int enable;
  58
  59        wait_queue_head_t wq;
  60};
  61
  62static inline struct saa7110 *to_saa7110(struct v4l2_subdev *sd)
  63{
  64        return container_of(sd, struct saa7110, sd);
  65}
  66
  67static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
  68{
  69        return &container_of(ctrl->handler, struct saa7110, hdl)->sd;
  70}
  71
  72/* ----------------------------------------------------------------------- */
  73/* I2C support functions                                                   */
  74/* ----------------------------------------------------------------------- */
  75
  76static int saa7110_write(struct v4l2_subdev *sd, u8 reg, u8 value)
  77{
  78        struct i2c_client *client = v4l2_get_subdevdata(sd);
  79        struct saa7110 *decoder = to_saa7110(sd);
  80
  81        decoder->reg[reg] = value;
  82        return i2c_smbus_write_byte_data(client, reg, value);
  83}
  84
  85static int saa7110_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len)
  86{
  87        struct i2c_client *client = v4l2_get_subdevdata(sd);
  88        struct saa7110 *decoder = to_saa7110(sd);
  89        int ret = -1;
  90        u8 reg = *data;         /* first register to write to */
  91
  92        /* Sanity check */
  93        if (reg + (len - 1) > SAA7110_NR_REG)
  94                return ret;
  95
  96        /* the saa7110 has an autoincrement function, use it if
  97         * the adapter understands raw I2C */
  98        if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
  99                ret = i2c_master_send(client, data, len);
 100
 101                /* Cache the written data */
 102                memcpy(decoder->reg + reg, data + 1, len - 1);
 103        } else {
 104                for (++data, --len; len; len--) {
 105                        ret = saa7110_write(sd, reg++, *data++);
 106                        if (ret < 0)
 107                                break;
 108                }
 109        }
 110
 111        return ret;
 112}
 113
 114static inline int saa7110_read(struct v4l2_subdev *sd)
 115{
 116        struct i2c_client *client = v4l2_get_subdevdata(sd);
 117
 118        return i2c_smbus_read_byte(client);
 119}
 120
 121/* ----------------------------------------------------------------------- */
 122/* SAA7110 functions                                                       */
 123/* ----------------------------------------------------------------------- */
 124
 125#define FRESP_06H_COMPST 0x03   /*0x13*/
 126#define FRESP_06H_SVIDEO 0x83   /*0xC0*/
 127
 128
 129static int saa7110_selmux(struct v4l2_subdev *sd, int chan)
 130{
 131        static const unsigned char modes[9][8] = {
 132                /* mode 0 */
 133                {FRESP_06H_COMPST, 0xD9, 0x17, 0x40, 0x03,
 134                              0x44, 0x75, 0x16},
 135                /* mode 1 */
 136                {FRESP_06H_COMPST, 0xD8, 0x17, 0x40, 0x03,
 137                              0x44, 0x75, 0x16},
 138                /* mode 2 */
 139                {FRESP_06H_COMPST, 0xBA, 0x07, 0x91, 0x03,
 140                              0x60, 0xB5, 0x05},
 141                /* mode 3 */
 142                {FRESP_06H_COMPST, 0xB8, 0x07, 0x91, 0x03,
 143                              0x60, 0xB5, 0x05},
 144                /* mode 4 */
 145                {FRESP_06H_COMPST, 0x7C, 0x07, 0xD2, 0x83,
 146                              0x60, 0xB5, 0x03},
 147                /* mode 5 */
 148                {FRESP_06H_COMPST, 0x78, 0x07, 0xD2, 0x83,
 149                              0x60, 0xB5, 0x03},
 150                /* mode 6 */
 151                {FRESP_06H_SVIDEO, 0x59, 0x17, 0x42, 0xA3,
 152                              0x44, 0x75, 0x12},
 153                /* mode 7 */
 154                {FRESP_06H_SVIDEO, 0x9A, 0x17, 0xB1, 0x13,
 155                              0x60, 0xB5, 0x14},
 156                /* mode 8 */
 157                {FRESP_06H_SVIDEO, 0x3C, 0x27, 0xC1, 0x23,
 158                              0x44, 0x75, 0x21}
 159        };
 160        struct saa7110 *decoder = to_saa7110(sd);
 161        const unsigned char *ptr = modes[chan];
 162
 163        saa7110_write(sd, 0x06, ptr[0]);        /* Luminance control    */
 164        saa7110_write(sd, 0x20, ptr[1]);        /* Analog Control #1    */
 165        saa7110_write(sd, 0x21, ptr[2]);        /* Analog Control #2    */
 166        saa7110_write(sd, 0x22, ptr[3]);        /* Mixer Control #1     */
 167        saa7110_write(sd, 0x2C, ptr[4]);        /* Mixer Control #2     */
 168        saa7110_write(sd, 0x30, ptr[5]);        /* ADCs gain control    */
 169        saa7110_write(sd, 0x31, ptr[6]);        /* Mixer Control #3     */
 170        saa7110_write(sd, 0x21, ptr[7]);        /* Analog Control #2    */
 171        decoder->input = chan;
 172
 173        return 0;
 174}
 175
 176static const unsigned char initseq[1 + SAA7110_NR_REG] = {
 177        0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF2, 0x03, 0x00,
 178        /* 0x08 */ 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x86, 0x18, 0x90,
 179        /* 0x10 */ 0x00, 0x59, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA,
 180        /* 0x18 */ 0xF2, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 181        /* 0x20 */ 0xD9, 0x16, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F,
 182        /* 0x28 */ 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x03, 0x0C,
 183        /* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02
 184};
 185
 186static v4l2_std_id determine_norm(struct v4l2_subdev *sd)
 187{
 188        DEFINE_WAIT(wait);
 189        struct saa7110 *decoder = to_saa7110(sd);
 190        int status;
 191
 192        /* mode changed, start automatic detection */
 193        saa7110_write_block(sd, initseq, sizeof(initseq));
 194        saa7110_selmux(sd, decoder->input);
 195        prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
 196        schedule_timeout(msecs_to_jiffies(250));
 197        finish_wait(&decoder->wq, &wait);
 198        status = saa7110_read(sd);
 199        if (status & 0x40) {
 200                v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)\n", status);
 201                return V4L2_STD_UNKNOWN;
 202        }
 203        if ((status & 3) == 0) {
 204                saa7110_write(sd, 0x06, 0x83);
 205                if (status & 0x20) {
 206                        v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC/no color)\n", status);
 207                        /*saa7110_write(sd,0x2E,0x81);*/
 208                        return V4L2_STD_NTSC;
 209                }
 210                v4l2_dbg(1, debug, sd, "status=0x%02x (PAL/no color)\n", status);
 211                /*saa7110_write(sd,0x2E,0x9A);*/
 212                return V4L2_STD_PAL;
 213        }
 214        /*saa7110_write(sd,0x06,0x03);*/
 215        if (status & 0x20) {    /* 60Hz */
 216                v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC)\n", status);
 217                saa7110_write(sd, 0x0D, 0x86);
 218                saa7110_write(sd, 0x0F, 0x50);
 219                saa7110_write(sd, 0x11, 0x2C);
 220                /*saa7110_write(sd,0x2E,0x81);*/
 221                return V4L2_STD_NTSC;
 222        }
 223
 224        /* 50Hz -> PAL/SECAM */
 225        saa7110_write(sd, 0x0D, 0x86);
 226        saa7110_write(sd, 0x0F, 0x10);
 227        saa7110_write(sd, 0x11, 0x59);
 228        /*saa7110_write(sd,0x2E,0x9A);*/
 229
 230        prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
 231        schedule_timeout(msecs_to_jiffies(250));
 232        finish_wait(&decoder->wq, &wait);
 233
 234        status = saa7110_read(sd);
 235        if ((status & 0x03) == 0x01) {
 236                v4l2_dbg(1, debug, sd, "status=0x%02x (SECAM)\n", status);
 237                saa7110_write(sd, 0x0D, 0x87);
 238                return V4L2_STD_SECAM;
 239        }
 240        v4l2_dbg(1, debug, sd, "status=0x%02x (PAL)\n", status);
 241        return V4L2_STD_PAL;
 242}
 243
 244static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus)
 245{
 246        struct saa7110 *decoder = to_saa7110(sd);
 247        int res = V4L2_IN_ST_NO_SIGNAL;
 248        int status = saa7110_read(sd);
 249
 250        v4l2_dbg(1, debug, sd, "status=0x%02x norm=%llx\n",
 251                       status, (unsigned long long)decoder->norm);
 252        if (!(status & 0x40))
 253                res = 0;
 254        if (!(status & 0x03))
 255                res |= V4L2_IN_ST_NO_COLOR;
 256
 257        *pstatus = res;
 258        return 0;
 259}
 260
 261static int saa7110_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
 262{
 263        *std &= determine_norm(sd);
 264        return 0;
 265}
 266
 267static int saa7110_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
 268{
 269        struct saa7110 *decoder = to_saa7110(sd);
 270
 271        if (decoder->norm != std) {
 272                decoder->norm = std;
 273                /*saa7110_write(sd, 0x06, 0x03);*/
 274                if (std & V4L2_STD_NTSC) {
 275                        saa7110_write(sd, 0x0D, 0x86);
 276                        saa7110_write(sd, 0x0F, 0x50);
 277                        saa7110_write(sd, 0x11, 0x2C);
 278                        /*saa7110_write(sd, 0x2E, 0x81);*/
 279                        v4l2_dbg(1, debug, sd, "switched to NTSC\n");
 280                } else if (std & V4L2_STD_PAL) {
 281                        saa7110_write(sd, 0x0D, 0x86);
 282                        saa7110_write(sd, 0x0F, 0x10);
 283                        saa7110_write(sd, 0x11, 0x59);
 284                        /*saa7110_write(sd, 0x2E, 0x9A);*/
 285                        v4l2_dbg(1, debug, sd, "switched to PAL\n");
 286                } else if (std & V4L2_STD_SECAM) {
 287                        saa7110_write(sd, 0x0D, 0x87);
 288                        saa7110_write(sd, 0x0F, 0x10);
 289                        saa7110_write(sd, 0x11, 0x59);
 290                        /*saa7110_write(sd, 0x2E, 0x9A);*/
 291                        v4l2_dbg(1, debug, sd, "switched to SECAM\n");
 292                } else {
 293                        return -EINVAL;
 294                }
 295        }
 296        return 0;
 297}
 298
 299static int saa7110_s_routing(struct v4l2_subdev *sd,
 300                             u32 input, u32 output, u32 config)
 301{
 302        struct saa7110 *decoder = to_saa7110(sd);
 303
 304        if (input >= SAA7110_MAX_INPUT) {
 305                v4l2_dbg(1, debug, sd, "input=%d not available\n", input);
 306                return -EINVAL;
 307        }
 308        if (decoder->input != input) {
 309                saa7110_selmux(sd, input);
 310                v4l2_dbg(1, debug, sd, "switched to input=%d\n", input);
 311        }
 312        return 0;
 313}
 314
 315static int saa7110_s_stream(struct v4l2_subdev *sd, int enable)
 316{
 317        struct saa7110 *decoder = to_saa7110(sd);
 318
 319        if (decoder->enable != enable) {
 320                decoder->enable = enable;
 321                saa7110_write(sd, 0x0E, enable ? 0x18 : 0x80);
 322                v4l2_dbg(1, debug, sd, "YUV %s\n", enable ? "on" : "off");
 323        }
 324        return 0;
 325}
 326
 327static int saa7110_s_ctrl(struct v4l2_ctrl *ctrl)
 328{
 329        struct v4l2_subdev *sd = to_sd(ctrl);
 330
 331        switch (ctrl->id) {
 332        case V4L2_CID_BRIGHTNESS:
 333                saa7110_write(sd, 0x19, ctrl->val);
 334                break;
 335        case V4L2_CID_CONTRAST:
 336                saa7110_write(sd, 0x13, ctrl->val);
 337                break;
 338        case V4L2_CID_SATURATION:
 339                saa7110_write(sd, 0x12, ctrl->val);
 340                break;
 341        case V4L2_CID_HUE:
 342                saa7110_write(sd, 0x07, ctrl->val);
 343                break;
 344        default:
 345                return -EINVAL;
 346        }
 347        return 0;
 348}
 349
 350/* ----------------------------------------------------------------------- */
 351
 352static const struct v4l2_ctrl_ops saa7110_ctrl_ops = {
 353        .s_ctrl = saa7110_s_ctrl,
 354};
 355
 356static const struct v4l2_subdev_video_ops saa7110_video_ops = {
 357        .s_std = saa7110_s_std,
 358        .s_routing = saa7110_s_routing,
 359        .s_stream = saa7110_s_stream,
 360        .querystd = saa7110_querystd,
 361        .g_input_status = saa7110_g_input_status,
 362};
 363
 364static const struct v4l2_subdev_ops saa7110_ops = {
 365        .video = &saa7110_video_ops,
 366};
 367
 368/* ----------------------------------------------------------------------- */
 369
 370static int saa7110_probe(struct i2c_client *client,
 371                        const struct i2c_device_id *id)
 372{
 373        struct saa7110 *decoder;
 374        struct v4l2_subdev *sd;
 375        int rv;
 376
 377        /* Check if the adapter supports the needed features */
 378        if (!i2c_check_functionality(client->adapter,
 379                I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
 380                return -ENODEV;
 381
 382        v4l_info(client, "chip found @ 0x%x (%s)\n",
 383                        client->addr << 1, client->adapter->name);
 384
 385        decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
 386        if (!decoder)
 387                return -ENOMEM;
 388        sd = &decoder->sd;
 389        v4l2_i2c_subdev_init(sd, client, &saa7110_ops);
 390        decoder->norm = V4L2_STD_PAL;
 391        decoder->input = 0;
 392        decoder->enable = 1;
 393        v4l2_ctrl_handler_init(&decoder->hdl, 2);
 394        v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
 395                V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
 396        v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
 397                V4L2_CID_CONTRAST, 0, 127, 1, 64);
 398        v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
 399                V4L2_CID_SATURATION, 0, 127, 1, 64);
 400        v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
 401                V4L2_CID_HUE, -128, 127, 1, 0);
 402        sd->ctrl_handler = &decoder->hdl;
 403        if (decoder->hdl.error) {
 404                int err = decoder->hdl.error;
 405
 406                v4l2_ctrl_handler_free(&decoder->hdl);
 407                return err;
 408        }
 409        v4l2_ctrl_handler_setup(&decoder->hdl);
 410
 411        init_waitqueue_head(&decoder->wq);
 412
 413        rv = saa7110_write_block(sd, initseq, sizeof(initseq));
 414        if (rv < 0) {
 415                v4l2_dbg(1, debug, sd, "init status %d\n", rv);
 416        } else {
 417                int ver, status;
 418                saa7110_write(sd, 0x21, 0x10);
 419                saa7110_write(sd, 0x0e, 0x18);
 420                saa7110_write(sd, 0x0D, 0x04);
 421                ver = saa7110_read(sd);
 422                saa7110_write(sd, 0x0D, 0x06);
 423                /*mdelay(150);*/
 424                status = saa7110_read(sd);
 425                v4l2_dbg(1, debug, sd, "version %x, status=0x%02x\n",
 426                               ver, status);
 427                saa7110_write(sd, 0x0D, 0x86);
 428                saa7110_write(sd, 0x0F, 0x10);
 429                saa7110_write(sd, 0x11, 0x59);
 430                /*saa7110_write(sd, 0x2E, 0x9A);*/
 431        }
 432
 433        /*saa7110_selmux(sd,0);*/
 434        /*determine_norm(sd);*/
 435        /* setup and implicit mode 0 select has been performed */
 436
 437        return 0;
 438}
 439
 440static int saa7110_remove(struct i2c_client *client)
 441{
 442        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 443        struct saa7110 *decoder = to_saa7110(sd);
 444
 445        v4l2_device_unregister_subdev(sd);
 446        v4l2_ctrl_handler_free(&decoder->hdl);
 447        return 0;
 448}
 449
 450/* ----------------------------------------------------------------------- */
 451
 452static const struct i2c_device_id saa7110_id[] = {
 453        { "saa7110", 0 },
 454        { }
 455};
 456MODULE_DEVICE_TABLE(i2c, saa7110_id);
 457
 458static struct i2c_driver saa7110_driver = {
 459        .driver = {
 460                .name   = "saa7110",
 461        },
 462        .probe          = saa7110_probe,
 463        .remove         = saa7110_remove,
 464        .id_table       = saa7110_id,
 465};
 466
 467module_i2c_driver(saa7110_driver);
 468