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