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