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-common.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,              0x9e },
 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        v4l2_std_id std;
 235        u32 ident;
 236        enum saa7127_input_type input_type;
 237        enum saa7127_output_type output_type;
 238        int video_enable;
 239        int wss_enable;
 240        u16 wss_mode;
 241        int cc_enable;
 242        u16 cc_data;
 243        int xds_enable;
 244        u16 xds_data;
 245        int vps_enable;
 246        u8 vps_data[5];
 247        u8 reg_2d;
 248        u8 reg_3a;
 249        u8 reg_3a_cb;   /* colorbar bit */
 250        u8 reg_61;
 251};
 252
 253static const char * const output_strs[] =
 254{
 255        "S-Video + Composite",
 256        "Composite",
 257        "S-Video",
 258        "RGB",
 259        "YUV C",
 260        "YUV V"
 261};
 262
 263static const char * const wss_strs[] = {
 264        "invalid",
 265        "letterbox 14:9 center",
 266        "letterbox 14:9 top",
 267        "invalid",
 268        "letterbox 16:9 top",
 269        "invalid",
 270        "invalid",
 271        "16:9 full format anamorphic",
 272        "4:3 full format",
 273        "invalid",
 274        "invalid",
 275        "letterbox 16:9 center",
 276        "invalid",
 277        "letterbox >16:9 center",
 278        "14:9 full format center",
 279        "invalid",
 280};
 281
 282/* ----------------------------------------------------------------------- */
 283
 284static int saa7127_read(struct i2c_client *client, u8 reg)
 285{
 286        return i2c_smbus_read_byte_data(client, reg);
 287}
 288
 289/* ----------------------------------------------------------------------- */
 290
 291static int saa7127_write(struct i2c_client *client, u8 reg, u8 val)
 292{
 293        int i;
 294
 295        for (i = 0; i < 3; i++) {
 296                if (i2c_smbus_write_byte_data(client, reg, val) == 0)
 297                        return 0;
 298        }
 299        v4l_err(client, "I2C Write Problem\n");
 300        return -1;
 301}
 302
 303/* ----------------------------------------------------------------------- */
 304
 305static int saa7127_write_inittab(struct i2c_client *client,
 306                                 const struct i2c_reg_value *regs)
 307{
 308        while (regs->reg != 0) {
 309                saa7127_write(client, regs->reg, regs->value);
 310                regs++;
 311        }
 312        return 0;
 313}
 314
 315/* ----------------------------------------------------------------------- */
 316
 317static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_data *data)
 318{
 319        struct saa7127_state *state = i2c_get_clientdata(client);
 320        int enable = (data->line != 0);
 321
 322        if (enable && (data->field != 0 || data->line != 16))
 323                return -EINVAL;
 324        if (state->vps_enable != enable) {
 325                v4l_dbg(1, debug, client, "Turn VPS Signal %s\n", enable ? "on" : "off");
 326                saa7127_write(client, 0x54, enable << 7);
 327                state->vps_enable = enable;
 328        }
 329        if (!enable)
 330                return 0;
 331
 332        state->vps_data[0] = data->data[2];
 333        state->vps_data[1] = data->data[8];
 334        state->vps_data[2] = data->data[9];
 335        state->vps_data[3] = data->data[10];
 336        state->vps_data[4] = data->data[11];
 337        v4l_dbg(1, debug, client, "Set VPS data %02x %02x %02x %02x %02x\n",
 338                state->vps_data[0], state->vps_data[1],
 339                state->vps_data[2], state->vps_data[3],
 340                state->vps_data[4]);
 341        saa7127_write(client, 0x55, state->vps_data[0]);
 342        saa7127_write(client, 0x56, state->vps_data[1]);
 343        saa7127_write(client, 0x57, state->vps_data[2]);
 344        saa7127_write(client, 0x58, state->vps_data[3]);
 345        saa7127_write(client, 0x59, state->vps_data[4]);
 346        return 0;
 347}
 348
 349/* ----------------------------------------------------------------------- */
 350
 351static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data *data)
 352{
 353        struct saa7127_state *state = i2c_get_clientdata(client);
 354        u16 cc = data->data[1] << 8 | data->data[0];
 355        int enable = (data->line != 0);
 356
 357        if (enable && (data->field != 0 || data->line != 21))
 358                return -EINVAL;
 359        if (state->cc_enable != enable) {
 360                v4l_dbg(1, debug, client,
 361                        "Turn CC %s\n", enable ? "on" : "off");
 362                saa7127_write(client, SAA7127_REG_CLOSED_CAPTION,
 363                        (state->xds_enable << 7) | (enable << 6) | 0x11);
 364                state->cc_enable = enable;
 365        }
 366        if (!enable)
 367                return 0;
 368
 369        v4l_dbg(2, debug, client, "CC data: %04x\n", cc);
 370        saa7127_write(client, SAA7127_REG_LINE_21_ODD_0, cc & 0xff);
 371        saa7127_write(client, SAA7127_REG_LINE_21_ODD_1, cc >> 8);
 372        state->cc_data = cc;
 373        return 0;
 374}
 375
 376/* ----------------------------------------------------------------------- */
 377
 378static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_data *data)
 379{
 380        struct saa7127_state *state = i2c_get_clientdata(client);
 381        u16 xds = data->data[1] << 8 | data->data[0];
 382        int enable = (data->line != 0);
 383
 384        if (enable && (data->field != 1 || data->line != 21))
 385                return -EINVAL;
 386        if (state->xds_enable != enable) {
 387                v4l_dbg(1, debug, client, "Turn XDS %s\n", enable ? "on" : "off");
 388                saa7127_write(client, SAA7127_REG_CLOSED_CAPTION,
 389                                (enable << 7) | (state->cc_enable << 6) | 0x11);
 390                state->xds_enable = enable;
 391        }
 392        if (!enable)
 393                return 0;
 394
 395        v4l_dbg(2, debug, client, "XDS data: %04x\n", xds);
 396        saa7127_write(client, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff);
 397        saa7127_write(client, SAA7127_REG_LINE_21_EVEN_1, xds >> 8);
 398        state->xds_data = xds;
 399        return 0;
 400}
 401
 402/* ----------------------------------------------------------------------- */
 403
 404static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_data *data)
 405{
 406        struct saa7127_state *state = i2c_get_clientdata(client);
 407        int enable = (data->line != 0);
 408
 409        if (enable && (data->field != 0 || data->line != 23))
 410                return -EINVAL;
 411        if (state->wss_enable != enable) {
 412                v4l_dbg(1, debug, client, "Turn WSS %s\n", enable ? "on" : "off");
 413                saa7127_write(client, 0x27, enable << 7);
 414                state->wss_enable = enable;
 415        }
 416        if (!enable)
 417                return 0;
 418
 419        saa7127_write(client, 0x26, data->data[0]);
 420        saa7127_write(client, 0x27, 0x80 | (data->data[1] & 0x3f));
 421        v4l_dbg(1, debug, client,
 422                "WSS mode: %s\n", wss_strs[data->data[0] & 0xf]);
 423        state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0];
 424        return 0;
 425}
 426
 427/* ----------------------------------------------------------------------- */
 428
 429static int saa7127_set_video_enable(struct i2c_client *client, int enable)
 430{
 431        struct saa7127_state *state = i2c_get_clientdata(client);
 432
 433        if (enable) {
 434                v4l_dbg(1, debug, client, "Enable Video Output\n");
 435                saa7127_write(client, 0x2d, state->reg_2d);
 436                saa7127_write(client, 0x61, state->reg_61);
 437        } else {
 438                v4l_dbg(1, debug, client, "Disable Video Output\n");
 439                saa7127_write(client, 0x2d, (state->reg_2d & 0xf0));
 440                saa7127_write(client, 0x61, (state->reg_61 | 0xc0));
 441        }
 442        state->video_enable = enable;
 443        return 0;
 444}
 445
 446/* ----------------------------------------------------------------------- */
 447
 448static int saa7127_set_std(struct i2c_client *client, v4l2_std_id std)
 449{
 450        struct saa7127_state *state = i2c_get_clientdata(client);
 451        const struct i2c_reg_value *inittab;
 452
 453        if (std & V4L2_STD_525_60) {
 454                v4l_dbg(1, debug, client, "Selecting 60 Hz video Standard\n");
 455                inittab = saa7127_init_config_60hz;
 456                state->reg_61 = SAA7127_60HZ_DAC_CONTROL;
 457        } else {
 458                v4l_dbg(1, debug, client, "Selecting 50 Hz video Standard\n");
 459                inittab = saa7127_init_config_50hz;
 460                state->reg_61 = SAA7127_50HZ_DAC_CONTROL;
 461        }
 462
 463        /* Write Table */
 464        saa7127_write_inittab(client, inittab);
 465        state->std = std;
 466        return 0;
 467}
 468
 469/* ----------------------------------------------------------------------- */
 470
 471static int saa7127_set_output_type(struct i2c_client *client, int output)
 472{
 473        struct saa7127_state *state = i2c_get_clientdata(client);
 474
 475        switch (output) {
 476        case SAA7127_OUTPUT_TYPE_RGB:
 477                state->reg_2d = 0x0f;   /* RGB + CVBS (for sync) */
 478                state->reg_3a = 0x13;   /* by default switch YUV to RGB-matrix on */
 479                break;
 480
 481        case SAA7127_OUTPUT_TYPE_COMPOSITE:
 482                state->reg_2d = 0x08;   /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */
 483                state->reg_3a = 0x13;   /* by default switch YUV to RGB-matrix on */
 484                break;
 485
 486        case SAA7127_OUTPUT_TYPE_SVIDEO:
 487                state->reg_2d = 0xff;   /* 11111111  croma -> R, luma -> CVBS + G + B */
 488                state->reg_3a = 0x13;   /* by default switch YUV to RGB-matrix on */
 489                break;
 490
 491        case SAA7127_OUTPUT_TYPE_YUV_V:
 492                state->reg_2d = 0x4f;   /* reg 2D = 01001111, all DAC's on, RGB + VBS */
 493                state->reg_3a = 0x0b;   /* reg 3A = 00001011, bypass RGB-matrix */
 494                break;
 495
 496        case SAA7127_OUTPUT_TYPE_YUV_C:
 497                state->reg_2d = 0x0f;   /* reg 2D = 00001111, all DAC's on, RGB + CVBS */
 498                state->reg_3a = 0x0b;   /* reg 3A = 00001011, bypass RGB-matrix */
 499                break;
 500
 501        case SAA7127_OUTPUT_TYPE_BOTH:
 502                state->reg_2d = 0xbf;
 503                state->reg_3a = 0x13;   /* by default switch YUV to RGB-matrix on */
 504                break;
 505
 506        default:
 507                return -EINVAL;
 508        }
 509        v4l_dbg(1, debug, client,
 510                "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                if (rc == 0 && state->output_type != route->output)
 575                        rc = saa7127_set_output_type(client, route->output);
 576                return rc;
 577        }
 578
 579        case VIDIOC_STREAMON:
 580        case VIDIOC_STREAMOFF:
 581                if (state->video_enable == (cmd == VIDIOC_STREAMON))
 582                        break;
 583                return saa7127_set_video_enable(client, cmd == VIDIOC_STREAMON);
 584
 585        case VIDIOC_G_FMT:
 586                if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
 587                        return -EINVAL;
 588
 589                memset(&fmt->fmt.sliced, 0, sizeof(fmt->fmt.sliced));
 590                if (state->vps_enable)
 591                        fmt->fmt.sliced.service_lines[0][16] = V4L2_SLICED_VPS;
 592                if (state->wss_enable)
 593                        fmt->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
 594                if (state->cc_enable) {
 595                        fmt->fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525;
 596                        fmt->fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525;
 597                }
 598                fmt->fmt.sliced.service_set =
 599                        (state->vps_enable ? V4L2_SLICED_VPS : 0) |
 600                        (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) |
 601                        (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0);
 602                break;
 603
 604        case VIDIOC_LOG_STATUS:
 605                v4l_info(client, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz");
 606                v4l_info(client, "Input:    %s\n", state->input_type ?  "color bars" : "normal");
 607                v4l_info(client, "Output:   %s\n", state->video_enable ?
 608                        output_strs[state->output_type] : "disabled");
 609                v4l_info(client, "WSS:      %s\n", state->wss_enable ?
 610                        wss_strs[state->wss_mode] : "disabled");
 611                v4l_info(client, "VPS:      %s\n", state->vps_enable ? "enabled" : "disabled");
 612                v4l_info(client, "CC:       %s\n", state->cc_enable ? "enabled" : "disabled");
 613                break;
 614
 615#ifdef CONFIG_VIDEO_ADV_DEBUG
 616        case VIDIOC_DBG_G_REGISTER:
 617        case VIDIOC_DBG_S_REGISTER:
 618        {
 619                struct v4l2_register *reg = arg;
 620
 621                if (!v4l2_chip_match_i2c_client(client,
 622                                        reg->match_type, reg->match_chip))
 623                        return -EINVAL;
 624                if (!capable(CAP_SYS_ADMIN))
 625                        return -EPERM;
 626                if (cmd == VIDIOC_DBG_G_REGISTER)
 627                        reg->val = saa7127_read(client, reg->reg & 0xff);
 628                else
 629                        saa7127_write(client, reg->reg & 0xff, reg->val & 0xff);
 630                break;
 631        }
 632#endif
 633
 634        case VIDIOC_INT_S_VBI_DATA:
 635        {
 636                struct v4l2_sliced_vbi_data *data = arg;
 637
 638                switch (data->id) {
 639                case V4L2_SLICED_WSS_625:
 640                        return saa7127_set_wss(client, data);
 641                case V4L2_SLICED_VPS:
 642                        return saa7127_set_vps(client, data);
 643                case V4L2_SLICED_CAPTION_525:
 644                        if (data->field == 0)
 645                                return saa7127_set_cc(client, data);
 646                        return saa7127_set_xds(client, data);
 647                default:
 648                        return -EINVAL;
 649                }
 650                break;
 651        }
 652
 653        case VIDIOC_G_CHIP_IDENT:
 654                return v4l2_chip_ident_i2c_client(client, arg, state->ident, 0);
 655
 656        default:
 657                return -EINVAL;
 658        }
 659        return 0;
 660}
 661
 662/* ----------------------------------------------------------------------- */
 663
 664static int saa7127_probe(struct i2c_client *client,
 665                         const struct i2c_device_id *id)
 666{
 667        struct saa7127_state *state;
 668        struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 };  /* set to disabled */
 669
 670        /* Check if the adapter supports the needed features */
 671        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 672                return -EIO;
 673
 674        v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n",
 675                        client->addr << 1);
 676
 677        /* First test register 0: Bits 5-7 are a version ID (should be 0),
 678           and bit 2 should also be 0.
 679           This is rather general, so the second test is more specific and
 680           looks at the 'ending point of burst in clock cycles' which is
 681           0x1d after a reset and not expected to ever change. */
 682        if ((saa7127_read(client, 0) & 0xe4) != 0 ||
 683                        (saa7127_read(client, 0x29) & 0x3f) != 0x1d) {
 684                v4l_dbg(1, debug, client, "saa7127 not found\n");
 685                return -ENODEV;
 686        }
 687        state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL);
 688
 689        if (state == NULL)
 690                return -ENOMEM;
 691
 692        i2c_set_clientdata(client, state);
 693
 694        /* Configure Encoder */
 695
 696        v4l_dbg(1, debug, client, "Configuring encoder\n");
 697        saa7127_write_inittab(client, saa7127_init_config_common);
 698        saa7127_set_std(client, V4L2_STD_NTSC);
 699        saa7127_set_output_type(client, SAA7127_OUTPUT_TYPE_BOTH);
 700        saa7127_set_vps(client, &vbi);
 701        saa7127_set_wss(client, &vbi);
 702        saa7127_set_cc(client, &vbi);
 703        saa7127_set_xds(client, &vbi);
 704        if (test_image == 1)
 705                /* The Encoder has an internal Colorbar generator */
 706                /* This can be used for debugging */
 707                saa7127_set_input_type(client, SAA7127_INPUT_TYPE_TEST_IMAGE);
 708        else
 709                saa7127_set_input_type(client, SAA7127_INPUT_TYPE_NORMAL);
 710        saa7127_set_video_enable(client, 1);
 711
 712        if (id->driver_data) {  /* Chip type is already known */
 713                state->ident = id->driver_data;
 714        } else {                /* Needs detection */
 715                int read_result;
 716
 717                /* Detect if it's an saa7129 */
 718                read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2);
 719                saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa);
 720                if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
 721                        saa7127_write(client, SAA7129_REG_FADE_KEY_COL2,
 722                                        read_result);
 723                        state->ident = V4L2_IDENT_SAA7129;
 724                        strlcpy(client->name, "saa7129", I2C_NAME_SIZE);
 725                } else {
 726                        state->ident = V4L2_IDENT_SAA7127;
 727                        strlcpy(client->name, "saa7127", I2C_NAME_SIZE);
 728                }
 729        }
 730
 731        v4l_info(client, "%s found @ 0x%x (%s)\n", client->name,
 732                        client->addr << 1, client->adapter->name);
 733        if (state->ident == V4L2_IDENT_SAA7129)
 734                saa7127_write_inittab(client, saa7129_init_config_extra);
 735        return 0;
 736}
 737
 738/* ----------------------------------------------------------------------- */
 739
 740static int saa7127_remove(struct i2c_client *client)
 741{
 742        /* Turn off TV output */
 743        saa7127_set_video_enable(client, 0);
 744        kfree(i2c_get_clientdata(client));
 745        return 0;
 746}
 747
 748/* ----------------------------------------------------------------------- */
 749
 750static struct i2c_device_id saa7127_id[] = {
 751        { "saa7127_auto", 0 },  /* auto-detection */
 752        { "saa7126", V4L2_IDENT_SAA7127 },
 753        { "saa7127", V4L2_IDENT_SAA7127 },
 754        { "saa7128", V4L2_IDENT_SAA7129 },
 755        { "saa7129", V4L2_IDENT_SAA7129 },
 756        { }
 757};
 758MODULE_DEVICE_TABLE(i2c, saa7127_id);
 759
 760static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 761        .name = "saa7127",
 762        .driverid = I2C_DRIVERID_SAA7127,
 763        .command = saa7127_command,
 764        .probe = saa7127_probe,
 765        .remove = saa7127_remove,
 766        .id_table = saa7127_id,
 767};
 768
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.