0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/init.h>
0010 #include <linux/delay.h>
0011 #include <linux/types.h>
0012 #include <linux/slab.h>
0013 #include <linux/uaccess.h>
0014 #include <linux/i2c.h>
0015 #include <linux/videodev2.h>
0016 #include <media/v4l2-device.h>
0017 #include <media/v4l2-ctrls.h>
0018
0019 MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
0020 MODULE_AUTHOR("Laurent Pinchart");
0021 MODULE_LICENSE("GPL");
0022
0023 static int debug;
0024 module_param(debug, int, 0);
0025 MODULE_PARM_DESC(debug, "Debug level (0-1)");
0026
0027
0028 #define VPX_TIMEOUT_COUNT 10
0029
0030
0031
0032 struct vpx3220 {
0033 struct v4l2_subdev sd;
0034 struct v4l2_ctrl_handler hdl;
0035 unsigned char reg[255];
0036
0037 v4l2_std_id norm;
0038 int input;
0039 int enable;
0040 };
0041
0042 static inline struct vpx3220 *to_vpx3220(struct v4l2_subdev *sd)
0043 {
0044 return container_of(sd, struct vpx3220, sd);
0045 }
0046
0047 static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
0048 {
0049 return &container_of(ctrl->handler, struct vpx3220, hdl)->sd;
0050 }
0051
0052 static char *inputs[] = { "internal", "composite", "svideo" };
0053
0054
0055
0056 static inline int vpx3220_write(struct v4l2_subdev *sd, u8 reg, u8 value)
0057 {
0058 struct i2c_client *client = v4l2_get_subdevdata(sd);
0059 struct vpx3220 *decoder = i2c_get_clientdata(client);
0060
0061 decoder->reg[reg] = value;
0062 return i2c_smbus_write_byte_data(client, reg, value);
0063 }
0064
0065 static inline int vpx3220_read(struct v4l2_subdev *sd, u8 reg)
0066 {
0067 struct i2c_client *client = v4l2_get_subdevdata(sd);
0068
0069 return i2c_smbus_read_byte_data(client, reg);
0070 }
0071
0072 static int vpx3220_fp_status(struct v4l2_subdev *sd)
0073 {
0074 unsigned char status;
0075 unsigned int i;
0076
0077 for (i = 0; i < VPX_TIMEOUT_COUNT; i++) {
0078 status = vpx3220_read(sd, 0x29);
0079
0080 if (!(status & 4))
0081 return 0;
0082
0083 udelay(10);
0084
0085 if (need_resched())
0086 cond_resched();
0087 }
0088
0089 return -1;
0090 }
0091
0092 static int vpx3220_fp_write(struct v4l2_subdev *sd, u8 fpaddr, u16 data)
0093 {
0094 struct i2c_client *client = v4l2_get_subdevdata(sd);
0095
0096
0097 if (i2c_smbus_write_word_data(client, 0x27, swab16(fpaddr)) == -1) {
0098 v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
0099 return -1;
0100 }
0101
0102 if (vpx3220_fp_status(sd) < 0)
0103 return -1;
0104
0105
0106 if (i2c_smbus_write_word_data(client, 0x28, swab16(data)) == -1) {
0107 v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
0108 return -1;
0109 }
0110
0111 return 0;
0112 }
0113
0114 static int vpx3220_fp_read(struct v4l2_subdev *sd, u16 fpaddr)
0115 {
0116 struct i2c_client *client = v4l2_get_subdevdata(sd);
0117 s16 data;
0118
0119
0120 if (i2c_smbus_write_word_data(client, 0x26, swab16(fpaddr)) == -1) {
0121 v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
0122 return -1;
0123 }
0124
0125 if (vpx3220_fp_status(sd) < 0)
0126 return -1;
0127
0128
0129 data = i2c_smbus_read_word_data(client, 0x28);
0130 if (data == -1) {
0131 v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
0132 return -1;
0133 }
0134
0135 return swab16(data);
0136 }
0137
0138 static int vpx3220_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len)
0139 {
0140 u8 reg;
0141 int ret = -1;
0142
0143 while (len >= 2) {
0144 reg = *data++;
0145 ret = vpx3220_write(sd, reg, *data++);
0146 if (ret < 0)
0147 break;
0148 len -= 2;
0149 }
0150
0151 return ret;
0152 }
0153
0154 static int vpx3220_write_fp_block(struct v4l2_subdev *sd,
0155 const u16 *data, unsigned int len)
0156 {
0157 u8 reg;
0158 int ret = 0;
0159
0160 while (len > 1) {
0161 reg = *data++;
0162 ret |= vpx3220_fp_write(sd, reg, *data++);
0163 len -= 2;
0164 }
0165
0166 return ret;
0167 }
0168
0169
0170
0171 static const unsigned short init_ntsc[] = {
0172 0x1c, 0x00,
0173 0x88, 17,
0174 0x89, 240,
0175 0x8a, 240,
0176 0x8b, 000,
0177 0x8c, 640,
0178 0x8d, 640,
0179 0x8f, 0xc00,
0180 0xf0, 0x73,
0181
0182 0xf2, 0x13,
0183 0xe7, 0x1e1,
0184
0185 };
0186
0187 static const unsigned short init_pal[] = {
0188 0x88, 23,
0189 0x89, 288,
0190
0191 0x8a, 288,
0192
0193 0x8b, 16,
0194 0x8c, 768,
0195 0x8d, 784,
0196
0197 0x8f, 0xc00,
0198 0xf0, 0x77,
0199
0200 0xf2, 0x3d1,
0201 0xe7, 0x241,
0202 };
0203
0204 static const unsigned short init_secam[] = {
0205 0x88, 23,
0206 0x89, 288,
0207
0208 0x8a, 288,
0209
0210 0x8b, 16,
0211 0x8c, 768,
0212 0x8d, 784,
0213
0214 0x8f, 0xc00,
0215 0xf0, 0x77,
0216
0217 0xf2, 0x3d5,
0218 0xe7, 0x241,
0219 };
0220
0221 static const unsigned char init_common[] = {
0222 0xf2, 0x00,
0223 0x33, 0x0d,
0224
0225 0xd8, 0xa8,
0226
0227 0x20, 0x03,
0228 0xe0, 0xff,
0229 0xe1, 0x00,
0230 0xe2, 0x7f,
0231 0xe3, 0x80,
0232 0xe4, 0x7f,
0233 0xe5, 0x80,
0234 0xe6, 0x00,
0235 0xe7, 0xe0,
0236
0237 0xe8, 0xf8,
0238
0239 0xea, 0x18,
0240
0241 0xf0, 0x8a,
0242
0243 0xf1, 0x18,
0244
0245 0xf8, 0x12,
0246
0247 0xf9, 0x24,
0248
0249 };
0250
0251 static const unsigned short init_fp[] = {
0252 0x59, 0,
0253 0xa0, 2070,
0254 0xa3, 0,
0255 0xa4, 0,
0256 0xa8, 30,
0257 0xb2, 768,
0258 0xbe, 27,
0259 0x58, 0,
0260 0x26, 0,
0261 0x4b, 0x298,
0262 };
0263
0264
0265 static int vpx3220_init(struct v4l2_subdev *sd, u32 val)
0266 {
0267 struct vpx3220 *decoder = to_vpx3220(sd);
0268
0269 vpx3220_write_block(sd, init_common, sizeof(init_common));
0270 vpx3220_write_fp_block(sd, init_fp, sizeof(init_fp) >> 1);
0271 if (decoder->norm & V4L2_STD_NTSC)
0272 vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1);
0273 else if (decoder->norm & V4L2_STD_PAL)
0274 vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
0275 else if (decoder->norm & V4L2_STD_SECAM)
0276 vpx3220_write_fp_block(sd, init_secam, sizeof(init_secam) >> 1);
0277 else
0278 vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
0279 return 0;
0280 }
0281
0282 static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
0283 {
0284 int res = V4L2_IN_ST_NO_SIGNAL, status;
0285 v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL;
0286
0287 status = vpx3220_fp_read(sd, 0x0f3);
0288
0289 v4l2_dbg(1, debug, sd, "status: 0x%04x\n", status);
0290
0291 if (status < 0)
0292 return status;
0293
0294 if ((status & 0x20) == 0) {
0295 res = 0;
0296
0297 switch (status & 0x18) {
0298 case 0x00:
0299 case 0x10:
0300 case 0x14:
0301 case 0x18:
0302 std &= V4L2_STD_PAL;
0303 break;
0304
0305 case 0x08:
0306 std &= V4L2_STD_SECAM;
0307 break;
0308
0309 case 0x04:
0310 case 0x0c:
0311 case 0x1c:
0312 std &= V4L2_STD_NTSC;
0313 break;
0314 }
0315 } else {
0316 std = V4L2_STD_UNKNOWN;
0317 }
0318 if (pstd)
0319 *pstd = std;
0320 if (pstatus)
0321 *pstatus = res;
0322 return 0;
0323 }
0324
0325 static int vpx3220_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
0326 {
0327 v4l2_dbg(1, debug, sd, "querystd\n");
0328 return vpx3220_status(sd, NULL, std);
0329 }
0330
0331 static int vpx3220_g_input_status(struct v4l2_subdev *sd, u32 *status)
0332 {
0333 v4l2_dbg(1, debug, sd, "g_input_status\n");
0334 return vpx3220_status(sd, status, NULL);
0335 }
0336
0337 static int vpx3220_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
0338 {
0339 struct vpx3220 *decoder = to_vpx3220(sd);
0340 int temp_input;
0341
0342
0343
0344
0345 temp_input = vpx3220_fp_read(sd, 0xf2);
0346
0347 v4l2_dbg(1, debug, sd, "s_std %llx\n", (unsigned long long)std);
0348 if (std & V4L2_STD_NTSC) {
0349 vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1);
0350 v4l2_dbg(1, debug, sd, "norm switched to NTSC\n");
0351 } else if (std & V4L2_STD_PAL) {
0352 vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
0353 v4l2_dbg(1, debug, sd, "norm switched to PAL\n");
0354 } else if (std & V4L2_STD_SECAM) {
0355 vpx3220_write_fp_block(sd, init_secam, sizeof(init_secam) >> 1);
0356 v4l2_dbg(1, debug, sd, "norm switched to SECAM\n");
0357 } else {
0358 return -EINVAL;
0359 }
0360
0361 decoder->norm = std;
0362
0363
0364 vpx3220_fp_write(sd, 0xf2, temp_input | 0x0010);
0365 udelay(10);
0366 return 0;
0367 }
0368
0369 static int vpx3220_s_routing(struct v4l2_subdev *sd,
0370 u32 input, u32 output, u32 config)
0371 {
0372 int data;
0373
0374
0375
0376
0377
0378 static const int input_vals[3][2] = {
0379 {0x0c, 0},
0380 {0x0d, 0},
0381 {0x0e, 1}
0382 };
0383
0384 if (input > 2)
0385 return -EINVAL;
0386
0387 v4l2_dbg(1, debug, sd, "input switched to %s\n", inputs[input]);
0388
0389 vpx3220_write(sd, 0x33, input_vals[input][0]);
0390
0391 data = vpx3220_fp_read(sd, 0xf2) & ~(0x0020);
0392 if (data < 0)
0393 return data;
0394
0395 vpx3220_fp_write(sd, 0xf2,
0396 data | (input_vals[input][1] << 5) | 0x0010);
0397
0398 udelay(10);
0399 return 0;
0400 }
0401
0402 static int vpx3220_s_stream(struct v4l2_subdev *sd, int enable)
0403 {
0404 v4l2_dbg(1, debug, sd, "s_stream %s\n", enable ? "on" : "off");
0405
0406 vpx3220_write(sd, 0xf2, (enable ? 0x1b : 0x00));
0407 return 0;
0408 }
0409
0410 static int vpx3220_s_ctrl(struct v4l2_ctrl *ctrl)
0411 {
0412 struct v4l2_subdev *sd = to_sd(ctrl);
0413
0414 switch (ctrl->id) {
0415 case V4L2_CID_BRIGHTNESS:
0416 vpx3220_write(sd, 0xe6, ctrl->val);
0417 return 0;
0418 case V4L2_CID_CONTRAST:
0419
0420 vpx3220_write(sd, 0xe7, ctrl->val + 192);
0421 return 0;
0422 case V4L2_CID_SATURATION:
0423 vpx3220_fp_write(sd, 0xa0, ctrl->val);
0424 return 0;
0425 case V4L2_CID_HUE:
0426 vpx3220_fp_write(sd, 0x1c, ctrl->val);
0427 return 0;
0428 }
0429 return -EINVAL;
0430 }
0431
0432
0433
0434 static const struct v4l2_ctrl_ops vpx3220_ctrl_ops = {
0435 .s_ctrl = vpx3220_s_ctrl,
0436 };
0437
0438 static const struct v4l2_subdev_core_ops vpx3220_core_ops = {
0439 .init = vpx3220_init,
0440 };
0441
0442 static const struct v4l2_subdev_video_ops vpx3220_video_ops = {
0443 .s_std = vpx3220_s_std,
0444 .s_routing = vpx3220_s_routing,
0445 .s_stream = vpx3220_s_stream,
0446 .querystd = vpx3220_querystd,
0447 .g_input_status = vpx3220_g_input_status,
0448 };
0449
0450 static const struct v4l2_subdev_ops vpx3220_ops = {
0451 .core = &vpx3220_core_ops,
0452 .video = &vpx3220_video_ops,
0453 };
0454
0455
0456
0457
0458
0459 static int vpx3220_probe(struct i2c_client *client,
0460 const struct i2c_device_id *id)
0461 {
0462 struct vpx3220 *decoder;
0463 struct v4l2_subdev *sd;
0464 const char *name = NULL;
0465 u8 ver;
0466 u16 pn;
0467
0468
0469 if (!i2c_check_functionality(client->adapter,
0470 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
0471 return -ENODEV;
0472
0473 decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
0474 if (decoder == NULL)
0475 return -ENOMEM;
0476 sd = &decoder->sd;
0477 v4l2_i2c_subdev_init(sd, client, &vpx3220_ops);
0478 decoder->norm = V4L2_STD_PAL;
0479 decoder->input = 0;
0480 decoder->enable = 1;
0481 v4l2_ctrl_handler_init(&decoder->hdl, 4);
0482 v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
0483 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
0484 v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
0485 V4L2_CID_CONTRAST, 0, 63, 1, 32);
0486 v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
0487 V4L2_CID_SATURATION, 0, 4095, 1, 2048);
0488 v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
0489 V4L2_CID_HUE, -512, 511, 1, 0);
0490 sd->ctrl_handler = &decoder->hdl;
0491 if (decoder->hdl.error) {
0492 int err = decoder->hdl.error;
0493
0494 v4l2_ctrl_handler_free(&decoder->hdl);
0495 return err;
0496 }
0497 v4l2_ctrl_handler_setup(&decoder->hdl);
0498
0499 ver = i2c_smbus_read_byte_data(client, 0x00);
0500 pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) +
0501 i2c_smbus_read_byte_data(client, 0x01);
0502 if (ver == 0xec) {
0503 switch (pn) {
0504 case 0x4680:
0505 name = "vpx3220a";
0506 break;
0507 case 0x4260:
0508 name = "vpx3216b";
0509 break;
0510 case 0x4280:
0511 name = "vpx3214c";
0512 break;
0513 }
0514 }
0515 if (name)
0516 v4l2_info(sd, "%s found @ 0x%x (%s)\n", name,
0517 client->addr << 1, client->adapter->name);
0518 else
0519 v4l2_info(sd, "chip (%02x:%04x) found @ 0x%x (%s)\n",
0520 ver, pn, client->addr << 1, client->adapter->name);
0521
0522 vpx3220_write_block(sd, init_common, sizeof(init_common));
0523 vpx3220_write_fp_block(sd, init_fp, sizeof(init_fp) >> 1);
0524
0525 vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
0526 return 0;
0527 }
0528
0529 static int vpx3220_remove(struct i2c_client *client)
0530 {
0531 struct v4l2_subdev *sd = i2c_get_clientdata(client);
0532 struct vpx3220 *decoder = to_vpx3220(sd);
0533
0534 v4l2_device_unregister_subdev(sd);
0535 v4l2_ctrl_handler_free(&decoder->hdl);
0536
0537 return 0;
0538 }
0539
0540 static const struct i2c_device_id vpx3220_id[] = {
0541 { "vpx3220a", 0 },
0542 { "vpx3216b", 0 },
0543 { "vpx3214c", 0 },
0544 { }
0545 };
0546 MODULE_DEVICE_TABLE(i2c, vpx3220_id);
0547
0548 static struct i2c_driver vpx3220_driver = {
0549 .driver = {
0550 .name = "vpx3220",
0551 },
0552 .probe = vpx3220_probe,
0553 .remove = vpx3220_remove,
0554 .id_table = vpx3220_id,
0555 };
0556
0557 module_i2c_driver(vpx3220_driver);