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