linux/drivers/media/i2c/saa7127.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * saa7127 - Philips SAA7127/SAA7129 video encoder driver
   4 *
   5 * Copyright (C) 2003 Roy Bulter <rbulter@hetnet.nl>
   6 *
   7 * Based on SAA7126 video encoder driver by Gillem & Andreas Oberritter
   8 *
   9 * Copyright (C) 2000-2001 Gillem <htoa@gmx.net>
  10 * Copyright (C) 2002 Andreas Oberritter <obi@saftware.de>
  11 *
  12 * Based on Stadis 4:2:2 MPEG-2 Decoder Driver by Nathan Laredo
  13 *
  14 * Copyright (C) 1999 Nathan Laredo <laredo@gnu.org>
  15 *
  16 * This driver is designed for the Hauppauge 250/350 Linux driver
  17 * from the ivtv Project
  18 *
  19 * Copyright (C) 2003 Kevin Thayer <nufan_wfk@yahoo.com>
  20 *
  21 * Dual output support:
  22 * Copyright (C) 2004 Eric Varsanyi
  23 *
  24 * NTSC Tuning and 7.5 IRE Setup
  25 * Copyright (C) 2004  Chris Kennedy <c@groovy.org>
  26 *
  27 * VBI additions & cleanup:
  28 * Copyright (C) 2004, 2005 Hans Verkuil <hverkuil@xs4all.nl>
  29 *
  30 * Note: the saa7126 is identical to the saa7127, and the saa7128 is
  31 * identical to the saa7129, except that the saa7126 and saa7128 have
  32 * macrovision anti-taping support. This driver will almost certainly
  33 * work fine for those chips, except of course for the missing anti-taping
  34 * support.
  35 */
  36
  37
  38#include <linux/kernel.h>
  39#include <linux/module.h>
  40#include <linux/slab.h>
  41#include <linux/i2c.h>
  42#include <linux/videodev2.h>
  43#include <media/v4l2-device.h>
  44#include <media/i2c/saa7127.h>
  45
  46static int debug;
  47static int test_image;
  48
  49MODULE_DESCRIPTION("Philips SAA7127/9 video encoder driver");
  50MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil");
  51MODULE_LICENSE("GPL");
  52module_param(debug, int, 0644);
  53module_param(test_image, int, 0644);
  54MODULE_PARM_DESC(debug, "debug level (0-2)");
  55MODULE_PARM_DESC(test_image, "test_image (0-1)");
  56
  57
  58/*
  59 * SAA7127 registers
  60 */
  61
  62#define SAA7127_REG_STATUS                           0x00
  63#define SAA7127_REG_WIDESCREEN_CONFIG                0x26
  64#define SAA7127_REG_WIDESCREEN_ENABLE                0x27
  65#define SAA7127_REG_BURST_START                      0x28
  66#define SAA7127_REG_BURST_END                        0x29
  67#define SAA7127_REG_COPYGEN_0                        0x2a
  68#define SAA7127_REG_COPYGEN_1                        0x2b
  69#define SAA7127_REG_COPYGEN_2                        0x2c
  70#define SAA7127_REG_OUTPUT_PORT_CONTROL              0x2d
  71#define SAA7127_REG_GAIN_LUMINANCE_RGB               0x38
  72#define SAA7127_REG_GAIN_COLORDIFF_RGB               0x39
  73#define SAA7127_REG_INPUT_PORT_CONTROL_1             0x3a
  74#define SAA7129_REG_FADE_KEY_COL2                    0x4f
  75#define SAA7127_REG_CHROMA_PHASE                     0x5a
  76#define SAA7127_REG_GAINU                            0x5b
  77#define SAA7127_REG_GAINV                            0x5c
  78#define SAA7127_REG_BLACK_LEVEL                      0x5d
  79#define SAA7127_REG_BLANKING_LEVEL                   0x5e
  80#define SAA7127_REG_VBI_BLANKING                     0x5f
  81#define SAA7127_REG_DAC_CONTROL                      0x61
  82#define SAA7127_REG_BURST_AMP                        0x62
  83#define SAA7127_REG_SUBC3                            0x63
  84#define SAA7127_REG_SUBC2                            0x64
  85#define SAA7127_REG_SUBC1                            0x65
  86#define SAA7127_REG_SUBC0                            0x66
  87#define SAA7127_REG_LINE_21_ODD_0                    0x67
  88#define SAA7127_REG_LINE_21_ODD_1                    0x68
  89#define SAA7127_REG_LINE_21_EVEN_0                   0x69
  90#define SAA7127_REG_LINE_21_EVEN_1                   0x6a
  91#define SAA7127_REG_RCV_PORT_CONTROL                 0x6b
  92#define SAA7127_REG_VTRIG                            0x6c
  93#define SAA7127_REG_HTRIG_HI                         0x6d
  94#define SAA7127_REG_MULTI                            0x6e
  95#define SAA7127_REG_CLOSED_CAPTION                   0x6f
  96#define SAA7127_REG_RCV2_OUTPUT_START                0x70
  97#define SAA7127_REG_RCV2_OUTPUT_END                  0x71
  98#define SAA7127_REG_RCV2_OUTPUT_MSBS                 0x72
  99#define SAA7127_REG_TTX_REQUEST_H_START              0x73
 100#define SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH       0x74
 101#define SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT        0x75
 102#define SAA7127_REG_TTX_ODD_REQ_VERT_START           0x76
 103#define SAA7127_REG_TTX_ODD_REQ_VERT_END             0x77
 104#define SAA7127_REG_TTX_EVEN_REQ_VERT_START          0x78
 105#define SAA7127_REG_TTX_EVEN_REQ_VERT_END            0x79
 106#define SAA7127_REG_FIRST_ACTIVE                     0x7a
 107#define SAA7127_REG_LAST_ACTIVE                      0x7b
 108#define SAA7127_REG_MSB_VERTICAL                     0x7c
 109#define SAA7127_REG_DISABLE_TTX_LINE_LO_0            0x7e
 110#define SAA7127_REG_DISABLE_TTX_LINE_LO_1            0x7f
 111
 112/*
 113 **********************************************************************
 114 *
 115 *  Arrays with configuration parameters for the SAA7127
 116 *
 117 **********************************************************************
 118 */
 119
 120struct i2c_reg_value {
 121        unsigned char reg;
 122        unsigned char value;
 123};
 124
 125static const struct i2c_reg_value saa7129_init_config_extra[] = {
 126        { SAA7127_REG_OUTPUT_PORT_CONTROL,              0x38 },
 127        { SAA7127_REG_VTRIG,                            0xfa },
 128        { 0, 0 }
 129};
 130
 131static const struct i2c_reg_value saa7127_init_config_common[] = {
 132        { SAA7127_REG_WIDESCREEN_CONFIG,                0x0d },
 133        { SAA7127_REG_WIDESCREEN_ENABLE,                0x00 },
 134        { SAA7127_REG_COPYGEN_0,                        0x77 },
 135        { SAA7127_REG_COPYGEN_1,                        0x41 },
 136        { SAA7127_REG_COPYGEN_2,                        0x00 }, /* Macrovision enable/disable */
 137        { SAA7127_REG_OUTPUT_PORT_CONTROL,              0xbf },
 138        { SAA7127_REG_GAIN_LUMINANCE_RGB,               0x00 },
 139        { SAA7127_REG_GAIN_COLORDIFF_RGB,               0x00 },
 140        { SAA7127_REG_INPUT_PORT_CONTROL_1,             0x80 }, /* for color bars */
 141        { SAA7127_REG_LINE_21_ODD_0,                    0x77 },
 142        { SAA7127_REG_LINE_21_ODD_1,                    0x41 },
 143        { SAA7127_REG_LINE_21_EVEN_0,                   0x88 },
 144        { SAA7127_REG_LINE_21_EVEN_1,                   0x41 },
 145        { SAA7127_REG_RCV_PORT_CONTROL,                 0x12 },
 146        { SAA7127_REG_VTRIG,                            0xf9 },
 147        { SAA7127_REG_HTRIG_HI,                         0x00 },
 148        { SAA7127_REG_RCV2_OUTPUT_START,                0x41 },
 149        { SAA7127_REG_RCV2_OUTPUT_END,                  0xc3 },
 150        { SAA7127_REG_RCV2_OUTPUT_MSBS,                 0x00 },
 151        { SAA7127_REG_TTX_REQUEST_H_START,              0x3e },
 152        { SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH,       0xb8 },
 153        { SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT,        0x03 },
 154        { SAA7127_REG_TTX_ODD_REQ_VERT_START,           0x15 },
 155        { SAA7127_REG_TTX_ODD_REQ_VERT_END,             0x16 },
 156        { SAA7127_REG_TTX_EVEN_REQ_VERT_START,          0x15 },
 157        { SAA7127_REG_TTX_EVEN_REQ_VERT_END,            0x16 },
 158        { SAA7127_REG_FIRST_ACTIVE,                     0x1a },
 159        { SAA7127_REG_LAST_ACTIVE,                      0x01 },
 160        { SAA7127_REG_MSB_VERTICAL,                     0xc0 },
 161        { SAA7127_REG_DISABLE_TTX_LINE_LO_0,            0x00 },
 162        { SAA7127_REG_DISABLE_TTX_LINE_LO_1,            0x00 },
 163        { 0, 0 }
 164};
 165
 166#define SAA7127_60HZ_DAC_CONTROL 0x15
 167static const struct i2c_reg_value saa7127_init_config_60hz[] = {
 168        { SAA7127_REG_BURST_START,                      0x19 },
 169        /* BURST_END is also used as a chip ID in saa7127_probe */
 170        { SAA7127_REG_BURST_END,                        0x1d },
 171        { SAA7127_REG_CHROMA_PHASE,                     0xa3 },
 172        { SAA7127_REG_GAINU,                            0x98 },
 173        { SAA7127_REG_GAINV,                            0xd3 },
 174        { SAA7127_REG_BLACK_LEVEL,                      0x39 },
 175        { SAA7127_REG_BLANKING_LEVEL,                   0x2e },
 176        { SAA7127_REG_VBI_BLANKING,                     0x2e },
 177        { SAA7127_REG_DAC_CONTROL,                      0x15 },
 178        { SAA7127_REG_BURST_AMP,                        0x4d },
 179        { SAA7127_REG_SUBC3,                            0x1f },
 180        { SAA7127_REG_SUBC2,                            0x7c },
 181        { SAA7127_REG_SUBC1,                            0xf0 },
 182        { SAA7127_REG_SUBC0,                            0x21 },
 183        { SAA7127_REG_MULTI,                            0x90 },
 184        { SAA7127_REG_CLOSED_CAPTION,                   0x11 },
 185        { 0, 0 }
 186};
 187
 188#define SAA7127_50HZ_PAL_DAC_CONTROL 0x02
 189static struct i2c_reg_value saa7127_init_config_50hz_pal[] = {
 190        { SAA7127_REG_BURST_START,                      0x21 },
 191        /* BURST_END is also used as a chip ID in saa7127_probe */
 192        { SAA7127_REG_BURST_END,                        0x1d },
 193        { SAA7127_REG_CHROMA_PHASE,                     0x3f },
 194        { SAA7127_REG_GAINU,                            0x7d },
 195        { SAA7127_REG_GAINV,                            0xaf },
 196        { SAA7127_REG_BLACK_LEVEL,                      0x33 },
 197        { SAA7127_REG_BLANKING_LEVEL,                   0x35 },
 198        { SAA7127_REG_VBI_BLANKING,                     0x35 },
 199        { SAA7127_REG_DAC_CONTROL,                      0x02 },
 200        { SAA7127_REG_BURST_AMP,                        0x2f },
 201        { SAA7127_REG_SUBC3,                            0xcb },
 202        { SAA7127_REG_SUBC2,                            0x8a },
 203        { SAA7127_REG_SUBC1,                            0x09 },
 204        { SAA7127_REG_SUBC0,                            0x2a },
 205        { SAA7127_REG_MULTI,                            0xa0 },
 206        { SAA7127_REG_CLOSED_CAPTION,                   0x00 },
 207        { 0, 0 }
 208};
 209
 210#define SAA7127_50HZ_SECAM_DAC_CONTROL 0x08
 211static struct i2c_reg_value saa7127_init_config_50hz_secam[] = {
 212        { SAA7127_REG_BURST_START,                      0x21 },
 213        /* BURST_END is also used as a chip ID in saa7127_probe */
 214        { SAA7127_REG_BURST_END,                        0x1d },
 215        { SAA7127_REG_CHROMA_PHASE,                     0x3f },
 216        { SAA7127_REG_GAINU,                            0x6a },
 217        { SAA7127_REG_GAINV,                            0x81 },
 218        { SAA7127_REG_BLACK_LEVEL,                      0x33 },
 219        { SAA7127_REG_BLANKING_LEVEL,                   0x35 },
 220        { SAA7127_REG_VBI_BLANKING,                     0x35 },
 221        { SAA7127_REG_DAC_CONTROL,                      0x08 },
 222        { SAA7127_REG_BURST_AMP,                        0x2f },
 223        { SAA7127_REG_SUBC3,                            0xb2 },
 224        { SAA7127_REG_SUBC2,                            0x3b },
 225        { SAA7127_REG_SUBC1,                            0xa3 },
 226        { SAA7127_REG_SUBC0,                            0x28 },
 227        { SAA7127_REG_MULTI,                            0x90 },
 228        { SAA7127_REG_CLOSED_CAPTION,                   0x00 },
 229        { 0, 0 }
 230};
 231
 232/*
 233 **********************************************************************
 234 *
 235 *  Encoder Struct, holds the configuration state of the encoder
 236 *
 237 **********************************************************************
 238 */
 239
 240enum saa712x_model {
 241        SAA7127,
 242        SAA7129,
 243};
 244
 245struct saa7127_state {
 246        struct v4l2_subdev sd;
 247        v4l2_std_id std;
 248        enum saa712x_model ident;
 249        enum saa7127_input_type input_type;
 250        enum saa7127_output_type output_type;
 251        int video_enable;
 252        int wss_enable;
 253        u16 wss_mode;
 254        int cc_enable;
 255        u16 cc_data;
 256        int xds_enable;
 257        u16 xds_data;
 258        int vps_enable;
 259        u8 vps_data[5];
 260        u8 reg_2d;
 261        u8 reg_3a;
 262        u8 reg_3a_cb;   /* colorbar bit */
 263        u8 reg_61;
 264};
 265
 266static inline struct saa7127_state *to_state(struct v4l2_subdev *sd)
 267{
 268        return container_of(sd, struct saa7127_state, sd);
 269}
 270
 271static const char * const output_strs[] =
 272{
 273        "S-Video + Composite",
 274        "Composite",
 275        "S-Video",
 276        "RGB",
 277        "YUV C",
 278        "YUV V"
 279};
 280
 281static const char * const wss_strs[] = {
 282        "invalid",
 283        "letterbox 14:9 center",
 284        "letterbox 14:9 top",
 285        "invalid",
 286        "letterbox 16:9 top",
 287        "invalid",
 288        "invalid",
 289        "16:9 full format anamorphic",
 290        "4:3 full format",
 291        "invalid",
 292        "invalid",
 293        "letterbox 16:9 center",
 294        "invalid",
 295        "letterbox >16:9 center",
 296        "14:9 full format center",
 297        "invalid",
 298};
 299
 300/* ----------------------------------------------------------------------- */
 301
 302static int saa7127_read(struct v4l2_subdev *sd, u8 reg)
 303{
 304        struct i2c_client *client = v4l2_get_subdevdata(sd);
 305
 306        return i2c_smbus_read_byte_data(client, reg);
 307}
 308
 309/* ----------------------------------------------------------------------- */
 310
 311static int saa7127_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 312{
 313        struct i2c_client *client = v4l2_get_subdevdata(sd);
 314        int i;
 315
 316        for (i = 0; i < 3; i++) {
 317                if (i2c_smbus_write_byte_data(client, reg, val) == 0)
 318                        return 0;
 319        }
 320        v4l2_err(sd, "I2C Write Problem\n");
 321        return -1;
 322}
 323
 324/* ----------------------------------------------------------------------- */
 325
 326static int saa7127_write_inittab(struct v4l2_subdev *sd,
 327                                 const struct i2c_reg_value *regs)
 328{
 329        while (regs->reg != 0) {
 330                saa7127_write(sd, regs->reg, regs->value);
 331                regs++;
 332        }
 333        return 0;
 334}
 335
 336/* ----------------------------------------------------------------------- */
 337
 338static int saa7127_set_vps(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
 339{
 340        struct saa7127_state *state = to_state(sd);
 341        int enable = (data->line != 0);
 342
 343        if (enable && (data->field != 0 || data->line != 16))
 344                return -EINVAL;
 345        if (state->vps_enable != enable) {
 346                v4l2_dbg(1, debug, sd, "Turn VPS Signal %s\n", enable ? "on" : "off");
 347                saa7127_write(sd, 0x54, enable << 7);
 348                state->vps_enable = enable;
 349        }
 350        if (!enable)
 351                return 0;
 352
 353        state->vps_data[0] = data->data[2];
 354        state->vps_data[1] = data->data[8];
 355        state->vps_data[2] = data->data[9];
 356        state->vps_data[3] = data->data[10];
 357        state->vps_data[4] = data->data[11];
 358        v4l2_dbg(1, debug, sd, "Set VPS data %*ph\n", 5, state->vps_data);
 359        saa7127_write(sd, 0x55, state->vps_data[0]);
 360        saa7127_write(sd, 0x56, state->vps_data[1]);
 361        saa7127_write(sd, 0x57, state->vps_data[2]);
 362        saa7127_write(sd, 0x58, state->vps_data[3]);
 363        saa7127_write(sd, 0x59, state->vps_data[4]);
 364        return 0;
 365}
 366
 367/* ----------------------------------------------------------------------- */
 368
 369static int saa7127_set_cc(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
 370{
 371        struct saa7127_state *state = to_state(sd);
 372        u16 cc = data->data[1] << 8 | data->data[0];
 373        int enable = (data->line != 0);
 374
 375        if (enable && (data->field != 0 || data->line != 21))
 376                return -EINVAL;
 377        if (state->cc_enable != enable) {
 378                v4l2_dbg(1, debug, sd,
 379                        "Turn CC %s\n", enable ? "on" : "off");
 380                saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION,
 381                        (state->xds_enable << 7) | (enable << 6) | 0x11);
 382                state->cc_enable = enable;
 383        }
 384        if (!enable)
 385                return 0;
 386
 387        v4l2_dbg(2, debug, sd, "CC data: %04x\n", cc);
 388        saa7127_write(sd, SAA7127_REG_LINE_21_ODD_0, cc & 0xff);
 389        saa7127_write(sd, SAA7127_REG_LINE_21_ODD_1, cc >> 8);
 390        state->cc_data = cc;
 391        return 0;
 392}
 393
 394/* ----------------------------------------------------------------------- */
 395
 396static int saa7127_set_xds(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
 397{
 398        struct saa7127_state *state = to_state(sd);
 399        u16 xds = data->data[1] << 8 | data->data[0];
 400        int enable = (data->line != 0);
 401
 402        if (enable && (data->field != 1 || data->line != 21))
 403                return -EINVAL;
 404        if (state->xds_enable != enable) {
 405                v4l2_dbg(1, debug, sd, "Turn XDS %s\n", enable ? "on" : "off");
 406                saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION,
 407                                (enable << 7) | (state->cc_enable << 6) | 0x11);
 408                state->xds_enable = enable;
 409        }
 410        if (!enable)
 411                return 0;
 412
 413        v4l2_dbg(2, debug, sd, "XDS data: %04x\n", xds);
 414        saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff);
 415        saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_1, xds >> 8);
 416        state->xds_data = xds;
 417        return 0;
 418}
 419
 420/* ----------------------------------------------------------------------- */
 421
 422static int saa7127_set_wss(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
 423{
 424        struct saa7127_state *state = to_state(sd);
 425        int enable = (data->line != 0);
 426
 427        if (enable && (data->field != 0 || data->line != 23))
 428                return -EINVAL;
 429        if (state->wss_enable != enable) {
 430                v4l2_dbg(1, debug, sd, "Turn WSS %s\n", enable ? "on" : "off");
 431                saa7127_write(sd, 0x27, enable << 7);
 432                state->wss_enable = enable;
 433        }
 434        if (!enable)
 435                return 0;
 436
 437        saa7127_write(sd, 0x26, data->data[0]);
 438        saa7127_write(sd, 0x27, 0x80 | (data->data[1] & 0x3f));
 439        v4l2_dbg(1, debug, sd,
 440                "WSS mode: %s\n", wss_strs[data->data[0] & 0xf]);
 441        state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0];
 442        return 0;
 443}
 444
 445/* ----------------------------------------------------------------------- */
 446
 447static int saa7127_set_video_enable(struct v4l2_subdev *sd, int enable)
 448{
 449        struct saa7127_state *state = to_state(sd);
 450
 451        if (enable) {
 452                v4l2_dbg(1, debug, sd, "Enable Video Output\n");
 453                saa7127_write(sd, 0x2d, state->reg_2d);
 454                saa7127_write(sd, 0x61, state->reg_61);
 455        } else {
 456                v4l2_dbg(1, debug, sd, "Disable Video Output\n");
 457                saa7127_write(sd, 0x2d, (state->reg_2d & 0xf0));
 458                saa7127_write(sd, 0x61, (state->reg_61 | 0xc0));
 459        }
 460        state->video_enable = enable;
 461        return 0;
 462}
 463
 464/* ----------------------------------------------------------------------- */
 465
 466static int saa7127_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
 467{
 468        struct saa7127_state *state = to_state(sd);
 469        const struct i2c_reg_value *inittab;
 470
 471        if (std & V4L2_STD_525_60) {
 472                v4l2_dbg(1, debug, sd, "Selecting 60 Hz video Standard\n");
 473                inittab = saa7127_init_config_60hz;
 474                state->reg_61 = SAA7127_60HZ_DAC_CONTROL;
 475
 476        } else if (state->ident == SAA7129 &&
 477                   (std & V4L2_STD_SECAM) &&
 478                   !(std & (V4L2_STD_625_50 & ~V4L2_STD_SECAM))) {
 479
 480                /* If and only if SECAM, with a SAA712[89] */
 481                v4l2_dbg(1, debug, sd,
 482                         "Selecting 50 Hz SECAM video Standard\n");
 483                inittab = saa7127_init_config_50hz_secam;
 484                state->reg_61 = SAA7127_50HZ_SECAM_DAC_CONTROL;
 485
 486        } else {
 487                v4l2_dbg(1, debug, sd, "Selecting 50 Hz PAL video Standard\n");
 488                inittab = saa7127_init_config_50hz_pal;
 489                state->reg_61 = SAA7127_50HZ_PAL_DAC_CONTROL;
 490        }
 491
 492        /* Write Table */
 493        saa7127_write_inittab(sd, inittab);
 494        state->std = std;
 495        return 0;
 496}
 497
 498/* ----------------------------------------------------------------------- */
 499
 500static int saa7127_set_output_type(struct v4l2_subdev *sd, int output)
 501{
 502        struct saa7127_state *state = to_state(sd);
 503
 504        switch (output) {
 505        case SAA7127_OUTPUT_TYPE_RGB:
 506                state->reg_2d = 0x0f;   /* RGB + CVBS (for sync) */
 507                state->reg_3a = 0x13;   /* by default switch YUV to RGB-matrix on */
 508                break;
 509
 510        case SAA7127_OUTPUT_TYPE_COMPOSITE:
 511                if (state->ident == SAA7129)
 512                        state->reg_2d = 0x20;   /* CVBS only */
 513                else
 514                        state->reg_2d = 0x08;   /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */
 515                state->reg_3a = 0x13;   /* by default switch YUV to RGB-matrix on */
 516                break;
 517
 518        case SAA7127_OUTPUT_TYPE_SVIDEO:
 519                if (state->ident == SAA7129)
 520                        state->reg_2d = 0x18;   /* Y + C */
 521                else
 522                        state->reg_2d = 0xff;   /*11111111  croma -> R, luma -> CVBS + G + B */
 523                state->reg_3a = 0x13;   /* by default switch YUV to RGB-matrix on */
 524                break;
 525
 526        case SAA7127_OUTPUT_TYPE_YUV_V:
 527                state->reg_2d = 0x4f;   /* reg 2D = 01001111, all DAC's on, RGB + VBS */
 528                state->reg_3a = 0x0b;   /* reg 3A = 00001011, bypass RGB-matrix */
 529                break;
 530
 531        case SAA7127_OUTPUT_TYPE_YUV_C:
 532                state->reg_2d = 0x0f;   /* reg 2D = 00001111, all DAC's on, RGB + CVBS */
 533                state->reg_3a = 0x0b;   /* reg 3A = 00001011, bypass RGB-matrix */
 534                break;
 535
 536        case SAA7127_OUTPUT_TYPE_BOTH:
 537                if (state->ident == SAA7129)
 538                        state->reg_2d = 0x38;
 539                else
 540                        state->reg_2d = 0xbf;
 541                state->reg_3a = 0x13;   /* by default switch YUV to RGB-matrix on */
 542                break;
 543
 544        default:
 545                return -EINVAL;
 546        }
 547        v4l2_dbg(1, debug, sd,
 548                "Selecting %s output type\n", output_strs[output]);
 549
 550        /* Configure Encoder */
 551        saa7127_write(sd, 0x2d, state->reg_2d);
 552        saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb);
 553        state->output_type = output;
 554        return 0;
 555}
 556
 557/* ----------------------------------------------------------------------- */
 558
 559static int saa7127_set_input_type(struct v4l2_subdev *sd, int input)
 560{
 561        struct saa7127_state *state = to_state(sd);
 562
 563        switch (input) {
 564        case SAA7127_INPUT_TYPE_NORMAL: /* avia */
 565                v4l2_dbg(1, debug, sd, "Selecting Normal Encoder Input\n");
 566                state->reg_3a_cb = 0;
 567                break;
 568
 569        case SAA7127_INPUT_TYPE_TEST_IMAGE:     /* color bar */
 570                v4l2_dbg(1, debug, sd, "Selecting Color Bar generator\n");
 571                state->reg_3a_cb = 0x80;
 572                break;
 573
 574        default:
 575                return -EINVAL;
 576        }
 577        saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb);
 578        state->input_type = input;
 579        return 0;
 580}
 581
 582/* ----------------------------------------------------------------------- */
 583
 584static int saa7127_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
 585{
 586        struct saa7127_state *state = to_state(sd);
 587
 588        if (state->std == std)
 589                return 0;
 590        return saa7127_set_std(sd, std);
 591}
 592
 593static int saa7127_s_routing(struct v4l2_subdev *sd,
 594                             u32 input, u32 output, u32 config)
 595{
 596        struct saa7127_state *state = to_state(sd);
 597        int rc = 0;
 598
 599        if (state->input_type != input)
 600                rc = saa7127_set_input_type(sd, input);
 601        if (rc == 0 && state->output_type != output)
 602                rc = saa7127_set_output_type(sd, output);
 603        return rc;
 604}
 605
 606static int saa7127_s_stream(struct v4l2_subdev *sd, int enable)
 607{
 608        struct saa7127_state *state = to_state(sd);
 609
 610        if (state->video_enable == enable)
 611                return 0;
 612        return saa7127_set_video_enable(sd, enable);
 613}
 614
 615static int saa7127_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
 616{
 617        struct saa7127_state *state = to_state(sd);
 618
 619        memset(fmt->service_lines, 0, sizeof(fmt->service_lines));
 620        if (state->vps_enable)
 621                fmt->service_lines[0][16] = V4L2_SLICED_VPS;
 622        if (state->wss_enable)
 623                fmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
 624        if (state->cc_enable) {
 625                fmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
 626                fmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
 627        }
 628        fmt->service_set =
 629                (state->vps_enable ? V4L2_SLICED_VPS : 0) |
 630                (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) |
 631                (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0);
 632        return 0;
 633}
 634
 635static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
 636{
 637        switch (data->id) {
 638        case V4L2_SLICED_WSS_625:
 639                return saa7127_set_wss(sd, data);
 640        case V4L2_SLICED_VPS:
 641                return saa7127_set_vps(sd, data);
 642        case V4L2_SLICED_CAPTION_525:
 643                if (data->field == 0)
 644                        return saa7127_set_cc(sd, data);
 645                return saa7127_set_xds(sd, data);
 646        default:
 647                return -EINVAL;
 648        }
 649        return 0;
 650}
 651
 652#ifdef CONFIG_VIDEO_ADV_DEBUG
 653static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 654{
 655        reg->val = saa7127_read(sd, reg->reg & 0xff);
 656        reg->size = 1;
 657        return 0;
 658}
 659
 660static int saa7127_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 661{
 662        saa7127_write(sd, reg->reg & 0xff, reg->val & 0xff);
 663        return 0;
 664}
 665#endif
 666
 667static int saa7127_log_status(struct v4l2_subdev *sd)
 668{
 669        struct saa7127_state *state = to_state(sd);
 670
 671        v4l2_info(sd, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz");
 672        v4l2_info(sd, "Input:    %s\n", state->input_type ?  "color bars" : "normal");
 673        v4l2_info(sd, "Output:   %s\n", state->video_enable ?
 674                        output_strs[state->output_type] : "disabled");
 675        v4l2_info(sd, "WSS:      %s\n", state->wss_enable ?
 676                        wss_strs[state->wss_mode] : "disabled");
 677        v4l2_info(sd, "VPS:      %s\n", state->vps_enable ? "enabled" : "disabled");
 678        v4l2_info(sd, "CC:       %s\n", state->cc_enable ? "enabled" : "disabled");
 679        return 0;
 680}
 681
 682/* ----------------------------------------------------------------------- */
 683
 684static const struct v4l2_subdev_core_ops saa7127_core_ops = {
 685        .log_status = saa7127_log_status,
 686#ifdef CONFIG_VIDEO_ADV_DEBUG
 687        .g_register = saa7127_g_register,
 688        .s_register = saa7127_s_register,
 689#endif
 690};
 691
 692static const struct v4l2_subdev_video_ops saa7127_video_ops = {
 693        .s_std_output = saa7127_s_std_output,
 694        .s_routing = saa7127_s_routing,
 695        .s_stream = saa7127_s_stream,
 696};
 697
 698static const struct v4l2_subdev_vbi_ops saa7127_vbi_ops = {
 699        .s_vbi_data = saa7127_s_vbi_data,
 700        .g_sliced_fmt = saa7127_g_sliced_fmt,
 701};
 702
 703static const struct v4l2_subdev_ops saa7127_ops = {
 704        .core = &saa7127_core_ops,
 705        .video = &saa7127_video_ops,
 706        .vbi = &saa7127_vbi_ops,
 707};
 708
 709/* ----------------------------------------------------------------------- */
 710
 711static int saa7127_probe(struct i2c_client *client,
 712                         const struct i2c_device_id *id)
 713{
 714        struct saa7127_state *state;
 715        struct v4l2_subdev *sd;
 716        struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 };  /* set to disabled */
 717
 718        /* Check if the adapter supports the needed features */
 719        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 720                return -EIO;
 721
 722        v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n",
 723                        client->addr << 1);
 724
 725        state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
 726        if (state == NULL)
 727                return -ENOMEM;
 728
 729        sd = &state->sd;
 730        v4l2_i2c_subdev_init(sd, client, &saa7127_ops);
 731
 732        /* First test register 0: Bits 5-7 are a version ID (should be 0),
 733           and bit 2 should also be 0.
 734           This is rather general, so the second test is more specific and
 735           looks at the 'ending point of burst in clock cycles' which is
 736           0x1d after a reset and not expected to ever change. */
 737        if ((saa7127_read(sd, 0) & 0xe4) != 0 ||
 738                        (saa7127_read(sd, 0x29) & 0x3f) != 0x1d) {
 739                v4l2_dbg(1, debug, sd, "saa7127 not found\n");
 740                return -ENODEV;
 741        }
 742
 743        if (id->driver_data) {  /* Chip type is already known */
 744                state->ident = id->driver_data;
 745        } else {                /* Needs detection */
 746                int read_result;
 747
 748                /* Detect if it's an saa7129 */
 749                read_result = saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2);
 750                saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2, 0xaa);
 751                if (saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
 752                        saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2,
 753                                        read_result);
 754                        state->ident = SAA7129;
 755                        strscpy(client->name, "saa7129", I2C_NAME_SIZE);
 756                } else {
 757                        state->ident = SAA7127;
 758                        strscpy(client->name, "saa7127", I2C_NAME_SIZE);
 759                }
 760        }
 761
 762        v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
 763                        client->addr << 1, client->adapter->name);
 764
 765        v4l2_dbg(1, debug, sd, "Configuring encoder\n");
 766        saa7127_write_inittab(sd, saa7127_init_config_common);
 767        saa7127_set_std(sd, V4L2_STD_NTSC);
 768        saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH);
 769        saa7127_set_vps(sd, &vbi);
 770        saa7127_set_wss(sd, &vbi);
 771        saa7127_set_cc(sd, &vbi);
 772        saa7127_set_xds(sd, &vbi);
 773        if (test_image == 1)
 774                /* The Encoder has an internal Colorbar generator */
 775                /* This can be used for debugging */
 776                saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE);
 777        else
 778                saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL);
 779        saa7127_set_video_enable(sd, 1);
 780
 781        if (state->ident == SAA7129)
 782                saa7127_write_inittab(sd, saa7129_init_config_extra);
 783        return 0;
 784}
 785
 786/* ----------------------------------------------------------------------- */
 787
 788static int saa7127_remove(struct i2c_client *client)
 789{
 790        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 791
 792        v4l2_device_unregister_subdev(sd);
 793        /* Turn off TV output */
 794        saa7127_set_video_enable(sd, 0);
 795        return 0;
 796}
 797
 798/* ----------------------------------------------------------------------- */
 799
 800static const struct i2c_device_id saa7127_id[] = {
 801        { "saa7127_auto", 0 },  /* auto-detection */
 802        { "saa7126", SAA7127 },
 803        { "saa7127", SAA7127 },
 804        { "saa7128", SAA7129 },
 805        { "saa7129", SAA7129 },
 806        { }
 807};
 808MODULE_DEVICE_TABLE(i2c, saa7127_id);
 809
 810static struct i2c_driver saa7127_driver = {
 811        .driver = {
 812                .name   = "saa7127",
 813        },
 814        .probe          = saa7127_probe,
 815        .remove         = saa7127_remove,
 816        .id_table       = saa7127_id,
 817};
 818
 819module_i2c_driver(saa7127_driver);
 820