0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
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
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
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 },
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 },
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
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
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
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
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;
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
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
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;
0507 state->reg_3a = 0x13;
0508 break;
0509
0510 case SAA7127_OUTPUT_TYPE_COMPOSITE:
0511 if (state->ident == SAA7129)
0512 state->reg_2d = 0x20;
0513 else
0514 state->reg_2d = 0x08;
0515 state->reg_3a = 0x13;
0516 break;
0517
0518 case SAA7127_OUTPUT_TYPE_SVIDEO:
0519 if (state->ident == SAA7129)
0520 state->reg_2d = 0x18;
0521 else
0522 state->reg_2d = 0xff;
0523 state->reg_3a = 0x13;
0524 break;
0525
0526 case SAA7127_OUTPUT_TYPE_YUV_V:
0527 state->reg_2d = 0x4f;
0528 state->reg_3a = 0x0b;
0529 break;
0530
0531 case SAA7127_OUTPUT_TYPE_YUV_C:
0532 state->reg_2d = 0x0f;
0533 state->reg_3a = 0x0b;
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;
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
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:
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:
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 };
0717
0718
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
0733
0734
0735
0736
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) {
0744 state->ident = id->driver_data;
0745 } else {
0746 int read_result;
0747
0748
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
0775
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
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 },
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);