Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * saa7127 - Philips SAA7127/SAA7129 video encoder driver
0004  *
0005  * Copyright (C) 2003 Roy Bulter <rbulter@hetnet.nl>
0006  *
0007  * Based on SAA7126 video encoder driver by Gillem & Andreas Oberritter
0008  *
0009  * Copyright (C) 2000-2001 Gillem <htoa@gmx.net>
0010  * Copyright (C) 2002 Andreas Oberritter <obi@saftware.de>
0011  *
0012  * Based on Stadis 4:2:2 MPEG-2 Decoder Driver by Nathan Laredo
0013  *
0014  * Copyright (C) 1999 Nathan Laredo <laredo@gnu.org>
0015  *
0016  * This driver is designed for the Hauppauge 250/350 Linux driver
0017  * from the ivtv Project
0018  *
0019  * Copyright (C) 2003 Kevin Thayer <nufan_wfk@yahoo.com>
0020  *
0021  * Dual output support:
0022  * Copyright (C) 2004 Eric Varsanyi
0023  *
0024  * NTSC Tuning and 7.5 IRE Setup
0025  * Copyright (C) 2004  Chris Kennedy <c@groovy.org>
0026  *
0027  * VBI additions & cleanup:
0028  * Copyright (C) 2004, 2005 Hans Verkuil <hverkuil@xs4all.nl>
0029  *
0030  * Note: the saa7126 is identical to the saa7127, and the saa7128 is
0031  * identical to the saa7129, except that the saa7126 and saa7128 have
0032  * macrovision anti-taping support. This driver will almost certainly
0033  * work fine for those chips, except of course for the missing anti-taping
0034  * support.
0035  */
0036 
0037 
0038 #include <linux/kernel.h>
0039 #include <linux/module.h>
0040 #include <linux/slab.h>
0041 #include <linux/i2c.h>
0042 #include <linux/videodev2.h>
0043 #include <media/v4l2-device.h>
0044 #include <media/i2c/saa7127.h>
0045 
0046 static int debug;
0047 static int test_image;
0048 
0049 MODULE_DESCRIPTION("Philips SAA7127/9 video encoder driver");
0050 MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil");
0051 MODULE_LICENSE("GPL");
0052 module_param(debug, int, 0644);
0053 module_param(test_image, int, 0644);
0054 MODULE_PARM_DESC(debug, "debug level (0-2)");
0055 MODULE_PARM_DESC(test_image, "test_image (0-1)");
0056 
0057 
0058 /*
0059  * SAA7127 registers
0060  */
0061 
0062 #define SAA7127_REG_STATUS                           0x00
0063 #define SAA7127_REG_WIDESCREEN_CONFIG                0x26
0064 #define SAA7127_REG_WIDESCREEN_ENABLE                0x27
0065 #define SAA7127_REG_BURST_START                      0x28
0066 #define SAA7127_REG_BURST_END                        0x29
0067 #define SAA7127_REG_COPYGEN_0                        0x2a
0068 #define SAA7127_REG_COPYGEN_1                        0x2b
0069 #define SAA7127_REG_COPYGEN_2                        0x2c
0070 #define SAA7127_REG_OUTPUT_PORT_CONTROL              0x2d
0071 #define SAA7127_REG_GAIN_LUMINANCE_RGB               0x38
0072 #define SAA7127_REG_GAIN_COLORDIFF_RGB               0x39
0073 #define SAA7127_REG_INPUT_PORT_CONTROL_1             0x3a
0074 #define SAA7129_REG_FADE_KEY_COL2            0x4f
0075 #define SAA7127_REG_CHROMA_PHASE                     0x5a
0076 #define SAA7127_REG_GAINU                            0x5b
0077 #define SAA7127_REG_GAINV                            0x5c
0078 #define SAA7127_REG_BLACK_LEVEL                      0x5d
0079 #define SAA7127_REG_BLANKING_LEVEL                   0x5e
0080 #define SAA7127_REG_VBI_BLANKING                     0x5f
0081 #define SAA7127_REG_DAC_CONTROL                      0x61
0082 #define SAA7127_REG_BURST_AMP                        0x62
0083 #define SAA7127_REG_SUBC3                            0x63
0084 #define SAA7127_REG_SUBC2                            0x64
0085 #define SAA7127_REG_SUBC1                            0x65
0086 #define SAA7127_REG_SUBC0                            0x66
0087 #define SAA7127_REG_LINE_21_ODD_0                    0x67
0088 #define SAA7127_REG_LINE_21_ODD_1                    0x68
0089 #define SAA7127_REG_LINE_21_EVEN_0                   0x69
0090 #define SAA7127_REG_LINE_21_EVEN_1                   0x6a
0091 #define SAA7127_REG_RCV_PORT_CONTROL                 0x6b
0092 #define SAA7127_REG_VTRIG                            0x6c
0093 #define SAA7127_REG_HTRIG_HI                         0x6d
0094 #define SAA7127_REG_MULTI                            0x6e
0095 #define SAA7127_REG_CLOSED_CAPTION                   0x6f
0096 #define SAA7127_REG_RCV2_OUTPUT_START                0x70
0097 #define SAA7127_REG_RCV2_OUTPUT_END                  0x71
0098 #define SAA7127_REG_RCV2_OUTPUT_MSBS                 0x72
0099 #define SAA7127_REG_TTX_REQUEST_H_START              0x73
0100 #define SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH       0x74
0101 #define SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT        0x75
0102 #define SAA7127_REG_TTX_ODD_REQ_VERT_START           0x76
0103 #define SAA7127_REG_TTX_ODD_REQ_VERT_END             0x77
0104 #define SAA7127_REG_TTX_EVEN_REQ_VERT_START          0x78
0105 #define SAA7127_REG_TTX_EVEN_REQ_VERT_END            0x79
0106 #define SAA7127_REG_FIRST_ACTIVE                     0x7a
0107 #define SAA7127_REG_LAST_ACTIVE                      0x7b
0108 #define SAA7127_REG_MSB_VERTICAL                     0x7c
0109 #define SAA7127_REG_DISABLE_TTX_LINE_LO_0            0x7e
0110 #define SAA7127_REG_DISABLE_TTX_LINE_LO_1            0x7f
0111 
0112 /*
0113  **********************************************************************
0114  *
0115  *  Arrays with configuration parameters for the SAA7127
0116  *
0117  **********************************************************************
0118  */
0119 
0120 struct i2c_reg_value {
0121     unsigned char reg;
0122     unsigned char value;
0123 };
0124 
0125 static const struct i2c_reg_value saa7129_init_config_extra[] = {
0126     { SAA7127_REG_OUTPUT_PORT_CONTROL,      0x38 },
0127     { SAA7127_REG_VTRIG,                0xfa },
0128     { 0, 0 }
0129 };
0130 
0131 static const struct i2c_reg_value saa7127_init_config_common[] = {
0132     { SAA7127_REG_WIDESCREEN_CONFIG,        0x0d },
0133     { SAA7127_REG_WIDESCREEN_ENABLE,        0x00 },
0134     { SAA7127_REG_COPYGEN_0,            0x77 },
0135     { SAA7127_REG_COPYGEN_1,            0x41 },
0136     { SAA7127_REG_COPYGEN_2,            0x00 }, /* Macrovision enable/disable */
0137     { SAA7127_REG_OUTPUT_PORT_CONTROL,      0xbf },
0138     { SAA7127_REG_GAIN_LUMINANCE_RGB,       0x00 },
0139     { SAA7127_REG_GAIN_COLORDIFF_RGB,       0x00 },
0140     { SAA7127_REG_INPUT_PORT_CONTROL_1,     0x80 }, /* for color bars */
0141     { SAA7127_REG_LINE_21_ODD_0,            0x77 },
0142     { SAA7127_REG_LINE_21_ODD_1,            0x41 },
0143     { SAA7127_REG_LINE_21_EVEN_0,           0x88 },
0144     { SAA7127_REG_LINE_21_EVEN_1,           0x41 },
0145     { SAA7127_REG_RCV_PORT_CONTROL,         0x12 },
0146     { SAA7127_REG_VTRIG,                0xf9 },
0147     { SAA7127_REG_HTRIG_HI,             0x00 },
0148     { SAA7127_REG_RCV2_OUTPUT_START,        0x41 },
0149     { SAA7127_REG_RCV2_OUTPUT_END,          0xc3 },
0150     { SAA7127_REG_RCV2_OUTPUT_MSBS,         0x00 },
0151     { SAA7127_REG_TTX_REQUEST_H_START,      0x3e },
0152     { SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH,   0xb8 },
0153     { SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT,    0x03 },
0154     { SAA7127_REG_TTX_ODD_REQ_VERT_START,       0x15 },
0155     { SAA7127_REG_TTX_ODD_REQ_VERT_END,     0x16 },
0156     { SAA7127_REG_TTX_EVEN_REQ_VERT_START,      0x15 },
0157     { SAA7127_REG_TTX_EVEN_REQ_VERT_END,        0x16 },
0158     { SAA7127_REG_FIRST_ACTIVE,         0x1a },
0159     { SAA7127_REG_LAST_ACTIVE,          0x01 },
0160     { SAA7127_REG_MSB_VERTICAL,         0xc0 },
0161     { SAA7127_REG_DISABLE_TTX_LINE_LO_0,        0x00 },
0162     { SAA7127_REG_DISABLE_TTX_LINE_LO_1,        0x00 },
0163     { 0, 0 }
0164 };
0165 
0166 #define SAA7127_60HZ_DAC_CONTROL 0x15
0167 static const struct i2c_reg_value saa7127_init_config_60hz[] = {
0168     { SAA7127_REG_BURST_START,          0x19 },
0169     /* BURST_END is also used as a chip ID in saa7127_probe */
0170     { SAA7127_REG_BURST_END,            0x1d },
0171     { SAA7127_REG_CHROMA_PHASE,         0xa3 },
0172     { SAA7127_REG_GAINU,                0x98 },
0173     { SAA7127_REG_GAINV,                0xd3 },
0174     { SAA7127_REG_BLACK_LEVEL,          0x39 },
0175     { SAA7127_REG_BLANKING_LEVEL,           0x2e },
0176     { SAA7127_REG_VBI_BLANKING,         0x2e },
0177     { SAA7127_REG_DAC_CONTROL,          0x15 },
0178     { SAA7127_REG_BURST_AMP,            0x4d },
0179     { SAA7127_REG_SUBC3,                0x1f },
0180     { SAA7127_REG_SUBC2,                0x7c },
0181     { SAA7127_REG_SUBC1,                0xf0 },
0182     { SAA7127_REG_SUBC0,                0x21 },
0183     { SAA7127_REG_MULTI,                0x90 },
0184     { SAA7127_REG_CLOSED_CAPTION,           0x11 },
0185     { 0, 0 }
0186 };
0187 
0188 #define SAA7127_50HZ_PAL_DAC_CONTROL 0x02
0189 static struct i2c_reg_value saa7127_init_config_50hz_pal[] = {
0190     { SAA7127_REG_BURST_START,          0x21 },
0191     /* BURST_END is also used as a chip ID in saa7127_probe */
0192     { SAA7127_REG_BURST_END,            0x1d },
0193     { SAA7127_REG_CHROMA_PHASE,         0x3f },
0194     { SAA7127_REG_GAINU,                0x7d },
0195     { SAA7127_REG_GAINV,                0xaf },
0196     { SAA7127_REG_BLACK_LEVEL,          0x33 },
0197     { SAA7127_REG_BLANKING_LEVEL,           0x35 },
0198     { SAA7127_REG_VBI_BLANKING,         0x35 },
0199     { SAA7127_REG_DAC_CONTROL,          0x02 },
0200     { SAA7127_REG_BURST_AMP,            0x2f },
0201     { SAA7127_REG_SUBC3,                0xcb },
0202     { SAA7127_REG_SUBC2,                0x8a },
0203     { SAA7127_REG_SUBC1,                0x09 },
0204     { SAA7127_REG_SUBC0,                0x2a },
0205     { SAA7127_REG_MULTI,                0xa0 },
0206     { SAA7127_REG_CLOSED_CAPTION,           0x00 },
0207     { 0, 0 }
0208 };
0209 
0210 #define SAA7127_50HZ_SECAM_DAC_CONTROL 0x08
0211 static struct i2c_reg_value saa7127_init_config_50hz_secam[] = {
0212     { SAA7127_REG_BURST_START,          0x21 },
0213     /* BURST_END is also used as a chip ID in saa7127_probe */
0214     { SAA7127_REG_BURST_END,            0x1d },
0215     { SAA7127_REG_CHROMA_PHASE,         0x3f },
0216     { SAA7127_REG_GAINU,                0x6a },
0217     { SAA7127_REG_GAINV,                0x81 },
0218     { SAA7127_REG_BLACK_LEVEL,          0x33 },
0219     { SAA7127_REG_BLANKING_LEVEL,           0x35 },
0220     { SAA7127_REG_VBI_BLANKING,         0x35 },
0221     { SAA7127_REG_DAC_CONTROL,          0x08 },
0222     { SAA7127_REG_BURST_AMP,            0x2f },
0223     { SAA7127_REG_SUBC3,                0xb2 },
0224     { SAA7127_REG_SUBC2,                0x3b },
0225     { SAA7127_REG_SUBC1,                0xa3 },
0226     { SAA7127_REG_SUBC0,                0x28 },
0227     { SAA7127_REG_MULTI,                0x90 },
0228     { SAA7127_REG_CLOSED_CAPTION,           0x00 },
0229     { 0, 0 }
0230 };
0231 
0232 /*
0233  **********************************************************************
0234  *
0235  *  Encoder Struct, holds the configuration state of the encoder
0236  *
0237  **********************************************************************
0238  */
0239 
0240 enum saa712x_model {
0241     SAA7127,
0242     SAA7129,
0243 };
0244 
0245 struct saa7127_state {
0246     struct v4l2_subdev sd;
0247     v4l2_std_id std;
0248     enum saa712x_model ident;
0249     enum saa7127_input_type input_type;
0250     enum saa7127_output_type output_type;
0251     int video_enable;
0252     int wss_enable;
0253     u16 wss_mode;
0254     int cc_enable;
0255     u16 cc_data;
0256     int xds_enable;
0257     u16 xds_data;
0258     int vps_enable;
0259     u8 vps_data[5];
0260     u8 reg_2d;
0261     u8 reg_3a;
0262     u8 reg_3a_cb;   /* colorbar bit */
0263     u8 reg_61;
0264 };
0265 
0266 static inline struct saa7127_state *to_state(struct v4l2_subdev *sd)
0267 {
0268     return container_of(sd, struct saa7127_state, sd);
0269 }
0270 
0271 static const char * const output_strs[] =
0272 {
0273     "S-Video + Composite",
0274     "Composite",
0275     "S-Video",
0276     "RGB",
0277     "YUV C",
0278     "YUV V"
0279 };
0280 
0281 static const char * const wss_strs[] = {
0282     "invalid",
0283     "letterbox 14:9 center",
0284     "letterbox 14:9 top",
0285     "invalid",
0286     "letterbox 16:9 top",
0287     "invalid",
0288     "invalid",
0289     "16:9 full format anamorphic",
0290     "4:3 full format",
0291     "invalid",
0292     "invalid",
0293     "letterbox 16:9 center",
0294     "invalid",
0295     "letterbox >16:9 center",
0296     "14:9 full format center",
0297     "invalid",
0298 };
0299 
0300 /* ----------------------------------------------------------------------- */
0301 
0302 static int saa7127_read(struct v4l2_subdev *sd, u8 reg)
0303 {
0304     struct i2c_client *client = v4l2_get_subdevdata(sd);
0305 
0306     return i2c_smbus_read_byte_data(client, reg);
0307 }
0308 
0309 /* ----------------------------------------------------------------------- */
0310 
0311 static int saa7127_write(struct v4l2_subdev *sd, u8 reg, u8 val)
0312 {
0313     struct i2c_client *client = v4l2_get_subdevdata(sd);
0314     int i;
0315 
0316     for (i = 0; i < 3; i++) {
0317         if (i2c_smbus_write_byte_data(client, reg, val) == 0)
0318             return 0;
0319     }
0320     v4l2_err(sd, "I2C Write Problem\n");
0321     return -1;
0322 }
0323 
0324 /* ----------------------------------------------------------------------- */
0325 
0326 static int saa7127_write_inittab(struct v4l2_subdev *sd,
0327                  const struct i2c_reg_value *regs)
0328 {
0329     while (regs->reg != 0) {
0330         saa7127_write(sd, regs->reg, regs->value);
0331         regs++;
0332     }
0333     return 0;
0334 }
0335 
0336 /* ----------------------------------------------------------------------- */
0337 
0338 static int saa7127_set_vps(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
0339 {
0340     struct saa7127_state *state = to_state(sd);
0341     int enable = (data->line != 0);
0342 
0343     if (enable && (data->field != 0 || data->line != 16))
0344         return -EINVAL;
0345     if (state->vps_enable != enable) {
0346         v4l2_dbg(1, debug, sd, "Turn VPS Signal %s\n", enable ? "on" : "off");
0347         saa7127_write(sd, 0x54, enable << 7);
0348         state->vps_enable = enable;
0349     }
0350     if (!enable)
0351         return 0;
0352 
0353     state->vps_data[0] = data->data[2];
0354     state->vps_data[1] = data->data[8];
0355     state->vps_data[2] = data->data[9];
0356     state->vps_data[3] = data->data[10];
0357     state->vps_data[4] = data->data[11];
0358     v4l2_dbg(1, debug, sd, "Set VPS data %*ph\n", 5, state->vps_data);
0359     saa7127_write(sd, 0x55, state->vps_data[0]);
0360     saa7127_write(sd, 0x56, state->vps_data[1]);
0361     saa7127_write(sd, 0x57, state->vps_data[2]);
0362     saa7127_write(sd, 0x58, state->vps_data[3]);
0363     saa7127_write(sd, 0x59, state->vps_data[4]);
0364     return 0;
0365 }
0366 
0367 /* ----------------------------------------------------------------------- */
0368 
0369 static int saa7127_set_cc(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
0370 {
0371     struct saa7127_state *state = to_state(sd);
0372     u16 cc = data->data[1] << 8 | data->data[0];
0373     int enable = (data->line != 0);
0374 
0375     if (enable && (data->field != 0 || data->line != 21))
0376         return -EINVAL;
0377     if (state->cc_enable != enable) {
0378         v4l2_dbg(1, debug, sd,
0379             "Turn CC %s\n", enable ? "on" : "off");
0380         saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION,
0381             (state->xds_enable << 7) | (enable << 6) | 0x11);
0382         state->cc_enable = enable;
0383     }
0384     if (!enable)
0385         return 0;
0386 
0387     v4l2_dbg(2, debug, sd, "CC data: %04x\n", cc);
0388     saa7127_write(sd, SAA7127_REG_LINE_21_ODD_0, cc & 0xff);
0389     saa7127_write(sd, SAA7127_REG_LINE_21_ODD_1, cc >> 8);
0390     state->cc_data = cc;
0391     return 0;
0392 }
0393 
0394 /* ----------------------------------------------------------------------- */
0395 
0396 static int saa7127_set_xds(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
0397 {
0398     struct saa7127_state *state = to_state(sd);
0399     u16 xds = data->data[1] << 8 | data->data[0];
0400     int enable = (data->line != 0);
0401 
0402     if (enable && (data->field != 1 || data->line != 21))
0403         return -EINVAL;
0404     if (state->xds_enable != enable) {
0405         v4l2_dbg(1, debug, sd, "Turn XDS %s\n", enable ? "on" : "off");
0406         saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION,
0407                 (enable << 7) | (state->cc_enable << 6) | 0x11);
0408         state->xds_enable = enable;
0409     }
0410     if (!enable)
0411         return 0;
0412 
0413     v4l2_dbg(2, debug, sd, "XDS data: %04x\n", xds);
0414     saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff);
0415     saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_1, xds >> 8);
0416     state->xds_data = xds;
0417     return 0;
0418 }
0419 
0420 /* ----------------------------------------------------------------------- */
0421 
0422 static int saa7127_set_wss(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
0423 {
0424     struct saa7127_state *state = to_state(sd);
0425     int enable = (data->line != 0);
0426 
0427     if (enable && (data->field != 0 || data->line != 23))
0428         return -EINVAL;
0429     if (state->wss_enable != enable) {
0430         v4l2_dbg(1, debug, sd, "Turn WSS %s\n", enable ? "on" : "off");
0431         saa7127_write(sd, 0x27, enable << 7);
0432         state->wss_enable = enable;
0433     }
0434     if (!enable)
0435         return 0;
0436 
0437     saa7127_write(sd, 0x26, data->data[0]);
0438     saa7127_write(sd, 0x27, 0x80 | (data->data[1] & 0x3f));
0439     v4l2_dbg(1, debug, sd,
0440         "WSS mode: %s\n", wss_strs[data->data[0] & 0xf]);
0441     state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0];
0442     return 0;
0443 }
0444 
0445 /* ----------------------------------------------------------------------- */
0446 
0447 static int saa7127_set_video_enable(struct v4l2_subdev *sd, int enable)
0448 {
0449     struct saa7127_state *state = to_state(sd);
0450 
0451     if (enable) {
0452         v4l2_dbg(1, debug, sd, "Enable Video Output\n");
0453         saa7127_write(sd, 0x2d, state->reg_2d);
0454         saa7127_write(sd, 0x61, state->reg_61);
0455     } else {
0456         v4l2_dbg(1, debug, sd, "Disable Video Output\n");
0457         saa7127_write(sd, 0x2d, (state->reg_2d & 0xf0));
0458         saa7127_write(sd, 0x61, (state->reg_61 | 0xc0));
0459     }
0460     state->video_enable = enable;
0461     return 0;
0462 }
0463 
0464 /* ----------------------------------------------------------------------- */
0465 
0466 static int saa7127_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
0467 {
0468     struct saa7127_state *state = to_state(sd);
0469     const struct i2c_reg_value *inittab;
0470 
0471     if (std & V4L2_STD_525_60) {
0472         v4l2_dbg(1, debug, sd, "Selecting 60 Hz video Standard\n");
0473         inittab = saa7127_init_config_60hz;
0474         state->reg_61 = SAA7127_60HZ_DAC_CONTROL;
0475 
0476     } else if (state->ident == SAA7129 &&
0477            (std & V4L2_STD_SECAM) &&
0478            !(std & (V4L2_STD_625_50 & ~V4L2_STD_SECAM))) {
0479 
0480         /* If and only if SECAM, with a SAA712[89] */
0481         v4l2_dbg(1, debug, sd,
0482              "Selecting 50 Hz SECAM video Standard\n");
0483         inittab = saa7127_init_config_50hz_secam;
0484         state->reg_61 = SAA7127_50HZ_SECAM_DAC_CONTROL;
0485 
0486     } else {
0487         v4l2_dbg(1, debug, sd, "Selecting 50 Hz PAL video Standard\n");
0488         inittab = saa7127_init_config_50hz_pal;
0489         state->reg_61 = SAA7127_50HZ_PAL_DAC_CONTROL;
0490     }
0491 
0492     /* Write Table */
0493     saa7127_write_inittab(sd, inittab);
0494     state->std = std;
0495     return 0;
0496 }
0497 
0498 /* ----------------------------------------------------------------------- */
0499 
0500 static int saa7127_set_output_type(struct v4l2_subdev *sd, int output)
0501 {
0502     struct saa7127_state *state = to_state(sd);
0503 
0504     switch (output) {
0505     case SAA7127_OUTPUT_TYPE_RGB:
0506         state->reg_2d = 0x0f;   /* RGB + CVBS (for sync) */
0507         state->reg_3a = 0x13;   /* by default switch YUV to RGB-matrix on */
0508         break;
0509 
0510     case SAA7127_OUTPUT_TYPE_COMPOSITE:
0511         if (state->ident == SAA7129)
0512             state->reg_2d = 0x20;   /* CVBS only */
0513         else
0514             state->reg_2d = 0x08;   /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */
0515         state->reg_3a = 0x13;   /* by default switch YUV to RGB-matrix on */
0516         break;
0517 
0518     case SAA7127_OUTPUT_TYPE_SVIDEO:
0519         if (state->ident == SAA7129)
0520             state->reg_2d = 0x18;   /* Y + C */
0521         else
0522             state->reg_2d = 0xff;   /*11111111  croma -> R, luma -> CVBS + G + B */
0523         state->reg_3a = 0x13;   /* by default switch YUV to RGB-matrix on */
0524         break;
0525 
0526     case SAA7127_OUTPUT_TYPE_YUV_V:
0527         state->reg_2d = 0x4f;   /* reg 2D = 01001111, all DAC's on, RGB + VBS */
0528         state->reg_3a = 0x0b;   /* reg 3A = 00001011, bypass RGB-matrix */
0529         break;
0530 
0531     case SAA7127_OUTPUT_TYPE_YUV_C:
0532         state->reg_2d = 0x0f;   /* reg 2D = 00001111, all DAC's on, RGB + CVBS */
0533         state->reg_3a = 0x0b;   /* reg 3A = 00001011, bypass RGB-matrix */
0534         break;
0535 
0536     case SAA7127_OUTPUT_TYPE_BOTH:
0537         if (state->ident == SAA7129)
0538             state->reg_2d = 0x38;
0539         else
0540             state->reg_2d = 0xbf;
0541         state->reg_3a = 0x13;   /* by default switch YUV to RGB-matrix on */
0542         break;
0543 
0544     default:
0545         return -EINVAL;
0546     }
0547     v4l2_dbg(1, debug, sd,
0548         "Selecting %s output type\n", output_strs[output]);
0549 
0550     /* Configure Encoder */
0551     saa7127_write(sd, 0x2d, state->reg_2d);
0552     saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb);
0553     state->output_type = output;
0554     return 0;
0555 }
0556 
0557 /* ----------------------------------------------------------------------- */
0558 
0559 static int saa7127_set_input_type(struct v4l2_subdev *sd, int input)
0560 {
0561     struct saa7127_state *state = to_state(sd);
0562 
0563     switch (input) {
0564     case SAA7127_INPUT_TYPE_NORMAL: /* avia */
0565         v4l2_dbg(1, debug, sd, "Selecting Normal Encoder Input\n");
0566         state->reg_3a_cb = 0;
0567         break;
0568 
0569     case SAA7127_INPUT_TYPE_TEST_IMAGE: /* color bar */
0570         v4l2_dbg(1, debug, sd, "Selecting Color Bar generator\n");
0571         state->reg_3a_cb = 0x80;
0572         break;
0573 
0574     default:
0575         return -EINVAL;
0576     }
0577     saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb);
0578     state->input_type = input;
0579     return 0;
0580 }
0581 
0582 /* ----------------------------------------------------------------------- */
0583 
0584 static int saa7127_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
0585 {
0586     struct saa7127_state *state = to_state(sd);
0587 
0588     if (state->std == std)
0589         return 0;
0590     return saa7127_set_std(sd, std);
0591 }
0592 
0593 static int saa7127_s_routing(struct v4l2_subdev *sd,
0594                  u32 input, u32 output, u32 config)
0595 {
0596     struct saa7127_state *state = to_state(sd);
0597     int rc = 0;
0598 
0599     if (state->input_type != input)
0600         rc = saa7127_set_input_type(sd, input);
0601     if (rc == 0 && state->output_type != output)
0602         rc = saa7127_set_output_type(sd, output);
0603     return rc;
0604 }
0605 
0606 static int saa7127_s_stream(struct v4l2_subdev *sd, int enable)
0607 {
0608     struct saa7127_state *state = to_state(sd);
0609 
0610     if (state->video_enable == enable)
0611         return 0;
0612     return saa7127_set_video_enable(sd, enable);
0613 }
0614 
0615 static int saa7127_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
0616 {
0617     struct saa7127_state *state = to_state(sd);
0618 
0619     memset(fmt->service_lines, 0, sizeof(fmt->service_lines));
0620     if (state->vps_enable)
0621         fmt->service_lines[0][16] = V4L2_SLICED_VPS;
0622     if (state->wss_enable)
0623         fmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
0624     if (state->cc_enable) {
0625         fmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
0626         fmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
0627     }
0628     fmt->service_set =
0629         (state->vps_enable ? V4L2_SLICED_VPS : 0) |
0630         (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) |
0631         (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0);
0632     return 0;
0633 }
0634 
0635 static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
0636 {
0637     switch (data->id) {
0638     case V4L2_SLICED_WSS_625:
0639         return saa7127_set_wss(sd, data);
0640     case V4L2_SLICED_VPS:
0641         return saa7127_set_vps(sd, data);
0642     case V4L2_SLICED_CAPTION_525:
0643         if (data->field == 0)
0644             return saa7127_set_cc(sd, data);
0645         return saa7127_set_xds(sd, data);
0646     default:
0647         return -EINVAL;
0648     }
0649     return 0;
0650 }
0651 
0652 #ifdef CONFIG_VIDEO_ADV_DEBUG
0653 static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
0654 {
0655     reg->val = saa7127_read(sd, reg->reg & 0xff);
0656     reg->size = 1;
0657     return 0;
0658 }
0659 
0660 static int saa7127_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
0661 {
0662     saa7127_write(sd, reg->reg & 0xff, reg->val & 0xff);
0663     return 0;
0664 }
0665 #endif
0666 
0667 static int saa7127_log_status(struct v4l2_subdev *sd)
0668 {
0669     struct saa7127_state *state = to_state(sd);
0670 
0671     v4l2_info(sd, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz");
0672     v4l2_info(sd, "Input:    %s\n", state->input_type ?  "color bars" : "normal");
0673     v4l2_info(sd, "Output:   %s\n", state->video_enable ?
0674             output_strs[state->output_type] : "disabled");
0675     v4l2_info(sd, "WSS:      %s\n", state->wss_enable ?
0676             wss_strs[state->wss_mode] : "disabled");
0677     v4l2_info(sd, "VPS:      %s\n", state->vps_enable ? "enabled" : "disabled");
0678     v4l2_info(sd, "CC:       %s\n", state->cc_enable ? "enabled" : "disabled");
0679     return 0;
0680 }
0681 
0682 /* ----------------------------------------------------------------------- */
0683 
0684 static const struct v4l2_subdev_core_ops saa7127_core_ops = {
0685     .log_status = saa7127_log_status,
0686 #ifdef CONFIG_VIDEO_ADV_DEBUG
0687     .g_register = saa7127_g_register,
0688     .s_register = saa7127_s_register,
0689 #endif
0690 };
0691 
0692 static const struct v4l2_subdev_video_ops saa7127_video_ops = {
0693     .s_std_output = saa7127_s_std_output,
0694     .s_routing = saa7127_s_routing,
0695     .s_stream = saa7127_s_stream,
0696 };
0697 
0698 static const struct v4l2_subdev_vbi_ops saa7127_vbi_ops = {
0699     .s_vbi_data = saa7127_s_vbi_data,
0700     .g_sliced_fmt = saa7127_g_sliced_fmt,
0701 };
0702 
0703 static const struct v4l2_subdev_ops saa7127_ops = {
0704     .core = &saa7127_core_ops,
0705     .video = &saa7127_video_ops,
0706     .vbi = &saa7127_vbi_ops,
0707 };
0708 
0709 /* ----------------------------------------------------------------------- */
0710 
0711 static int saa7127_probe(struct i2c_client *client,
0712              const struct i2c_device_id *id)
0713 {
0714     struct saa7127_state *state;
0715     struct v4l2_subdev *sd;
0716     struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 };  /* set to disabled */
0717 
0718     /* Check if the adapter supports the needed features */
0719     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
0720         return -EIO;
0721 
0722     v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n",
0723             client->addr << 1);
0724 
0725     state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
0726     if (state == NULL)
0727         return -ENOMEM;
0728 
0729     sd = &state->sd;
0730     v4l2_i2c_subdev_init(sd, client, &saa7127_ops);
0731 
0732     /* First test register 0: Bits 5-7 are a version ID (should be 0),
0733        and bit 2 should also be 0.
0734        This is rather general, so the second test is more specific and
0735        looks at the 'ending point of burst in clock cycles' which is
0736        0x1d after a reset and not expected to ever change. */
0737     if ((saa7127_read(sd, 0) & 0xe4) != 0 ||
0738             (saa7127_read(sd, 0x29) & 0x3f) != 0x1d) {
0739         v4l2_dbg(1, debug, sd, "saa7127 not found\n");
0740         return -ENODEV;
0741     }
0742 
0743     if (id->driver_data) {  /* Chip type is already known */
0744         state->ident = id->driver_data;
0745     } else {        /* Needs detection */
0746         int read_result;
0747 
0748         /* Detect if it's an saa7129 */
0749         read_result = saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2);
0750         saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2, 0xaa);
0751         if (saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
0752             saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2,
0753                     read_result);
0754             state->ident = SAA7129;
0755             strscpy(client->name, "saa7129", I2C_NAME_SIZE);
0756         } else {
0757             state->ident = SAA7127;
0758             strscpy(client->name, "saa7127", I2C_NAME_SIZE);
0759         }
0760     }
0761 
0762     v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
0763             client->addr << 1, client->adapter->name);
0764 
0765     v4l2_dbg(1, debug, sd, "Configuring encoder\n");
0766     saa7127_write_inittab(sd, saa7127_init_config_common);
0767     saa7127_set_std(sd, V4L2_STD_NTSC);
0768     saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH);
0769     saa7127_set_vps(sd, &vbi);
0770     saa7127_set_wss(sd, &vbi);
0771     saa7127_set_cc(sd, &vbi);
0772     saa7127_set_xds(sd, &vbi);
0773     if (test_image == 1)
0774         /* The Encoder has an internal Colorbar generator */
0775         /* This can be used for debugging */
0776         saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE);
0777     else
0778         saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL);
0779     saa7127_set_video_enable(sd, 1);
0780 
0781     if (state->ident == SAA7129)
0782         saa7127_write_inittab(sd, saa7129_init_config_extra);
0783     return 0;
0784 }
0785 
0786 /* ----------------------------------------------------------------------- */
0787 
0788 static int saa7127_remove(struct i2c_client *client)
0789 {
0790     struct v4l2_subdev *sd = i2c_get_clientdata(client);
0791 
0792     v4l2_device_unregister_subdev(sd);
0793     /* Turn off TV output */
0794     saa7127_set_video_enable(sd, 0);
0795     return 0;
0796 }
0797 
0798 /* ----------------------------------------------------------------------- */
0799 
0800 static const struct i2c_device_id saa7127_id[] = {
0801     { "saa7127_auto", 0 },  /* auto-detection */
0802     { "saa7126", SAA7127 },
0803     { "saa7127", SAA7127 },
0804     { "saa7128", SAA7129 },
0805     { "saa7129", SAA7129 },
0806     { }
0807 };
0808 MODULE_DEVICE_TABLE(i2c, saa7127_id);
0809 
0810 static struct i2c_driver saa7127_driver = {
0811     .driver = {
0812         .name   = "saa7127",
0813     },
0814     .probe      = saa7127_probe,
0815     .remove     = saa7127_remove,
0816     .id_table   = saa7127_id,
0817 };
0818 
0819 module_i2c_driver(saa7127_driver);