0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/delay.h>
0009 #include <linux/errno.h>
0010 #include <linux/gpio.h>
0011 #include <linux/i2c.h>
0012 #include <linux/init.h>
0013 #include <linux/module.h>
0014 #include <linux/slab.h>
0015 #include <linux/types.h>
0016 #include <linux/videodev2.h>
0017
0018 #include <media/v4l2-ctrls.h>
0019 #include <media/v4l2-device.h>
0020 #include <media/v4l2-mediabus.h>
0021 #include <media/v4l2-image-sizes.h>
0022
0023 #include "vs6624_regs.h"
0024
0025 #define MAX_FRAME_RATE 30
0026
0027 struct vs6624 {
0028 struct v4l2_subdev sd;
0029 struct v4l2_ctrl_handler hdl;
0030 struct v4l2_fract frame_rate;
0031 struct v4l2_mbus_framefmt fmt;
0032 unsigned ce_pin;
0033 };
0034
0035 static const struct vs6624_format {
0036 u32 mbus_code;
0037 enum v4l2_colorspace colorspace;
0038 } vs6624_formats[] = {
0039 {
0040 .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
0041 .colorspace = V4L2_COLORSPACE_JPEG,
0042 },
0043 {
0044 .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
0045 .colorspace = V4L2_COLORSPACE_JPEG,
0046 },
0047 {
0048 .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE,
0049 .colorspace = V4L2_COLORSPACE_SRGB,
0050 },
0051 };
0052
0053 static const struct v4l2_mbus_framefmt vs6624_default_fmt = {
0054 .width = VGA_WIDTH,
0055 .height = VGA_HEIGHT,
0056 .code = MEDIA_BUS_FMT_UYVY8_2X8,
0057 .field = V4L2_FIELD_NONE,
0058 .colorspace = V4L2_COLORSPACE_JPEG,
0059 };
0060
0061 static const u16 vs6624_p1[] = {
0062 0x8104, 0x03,
0063 0x8105, 0x01,
0064 0xc900, 0x03,
0065 0xc904, 0x47,
0066 0xc905, 0x10,
0067 0xc906, 0x80,
0068 0xc907, 0x3a,
0069 0x903a, 0x02,
0070 0x903b, 0x47,
0071 0x903c, 0x15,
0072 0xc908, 0x31,
0073 0xc909, 0xdc,
0074 0xc90a, 0x80,
0075 0xc90b, 0x44,
0076 0x9044, 0x02,
0077 0x9045, 0x31,
0078 0x9046, 0xe2,
0079 0xc90c, 0x07,
0080 0xc90d, 0xe0,
0081 0xc90e, 0x80,
0082 0xc90f, 0x47,
0083 0x9047, 0x90,
0084 0x9048, 0x83,
0085 0x9049, 0x81,
0086 0x904a, 0xe0,
0087 0x904b, 0x60,
0088 0x904c, 0x08,
0089 0x904d, 0x90,
0090 0x904e, 0xc0,
0091 0x904f, 0x43,
0092 0x9050, 0x74,
0093 0x9051, 0x01,
0094 0x9052, 0xf0,
0095 0x9053, 0x80,
0096 0x9054, 0x05,
0097 0x9055, 0xE4,
0098 0x9056, 0x90,
0099 0x9057, 0xc0,
0100 0x9058, 0x43,
0101 0x9059, 0xf0,
0102 0x905a, 0x02,
0103 0x905b, 0x07,
0104 0x905c, 0xec,
0105 0xc910, 0x5d,
0106 0xc911, 0xca,
0107 0xc912, 0x80,
0108 0xc913, 0x5d,
0109 0x905d, 0xa3,
0110 0x905e, 0x04,
0111 0x905f, 0xf0,
0112 0x9060, 0xa3,
0113 0x9061, 0x04,
0114 0x9062, 0xf0,
0115 0x9063, 0x22,
0116 0xc914, 0x72,
0117 0xc915, 0x92,
0118 0xc916, 0x80,
0119 0xc917, 0x64,
0120 0x9064, 0x74,
0121 0x9065, 0x01,
0122 0x9066, 0x02,
0123 0x9067, 0x72,
0124 0x9068, 0x95,
0125 0xc918, 0x47,
0126 0xc919, 0xf2,
0127 0xc91a, 0x81,
0128 0xc91b, 0x69,
0129 0x9169, 0x74,
0130 0x916a, 0x02,
0131 0x916b, 0xf0,
0132 0x916c, 0xec,
0133 0x916d, 0xb4,
0134 0x916e, 0x10,
0135 0x916f, 0x0a,
0136 0x9170, 0x90,
0137 0x9171, 0x80,
0138 0x9172, 0x16,
0139 0x9173, 0xe0,
0140 0x9174, 0x70,
0141 0x9175, 0x04,
0142 0x9176, 0x90,
0143 0x9177, 0xd3,
0144 0x9178, 0xc4,
0145 0x9179, 0xf0,
0146 0x917a, 0x22,
0147 0xc91c, 0x0a,
0148 0xc91d, 0xbe,
0149 0xc91e, 0x80,
0150 0xc91f, 0x73,
0151 0x9073, 0xfc,
0152 0x9074, 0xa3,
0153 0x9075, 0xe0,
0154 0x9076, 0xf5,
0155 0x9077, 0x82,
0156 0x9078, 0x8c,
0157 0x9079, 0x83,
0158 0x907a, 0xa3,
0159 0x907b, 0xa3,
0160 0x907c, 0xe0,
0161 0x907d, 0xfc,
0162 0x907e, 0xa3,
0163 0x907f, 0xe0,
0164 0x9080, 0xc3,
0165 0x9081, 0x9f,
0166 0x9082, 0xff,
0167 0x9083, 0xec,
0168 0x9084, 0x9e,
0169 0x9085, 0xfe,
0170 0x9086, 0x02,
0171 0x9087, 0x0a,
0172 0x9088, 0xea,
0173 0xc920, 0x47,
0174 0xc921, 0x38,
0175 0xc922, 0x80,
0176 0xc923, 0x89,
0177 0x9089, 0xec,
0178 0x908a, 0xd3,
0179 0x908b, 0x94,
0180 0x908c, 0x20,
0181 0x908d, 0x40,
0182 0x908e, 0x01,
0183 0x908f, 0x1c,
0184 0x9090, 0x90,
0185 0x9091, 0xd3,
0186 0x9092, 0xd4,
0187 0x9093, 0xec,
0188 0x9094, 0xf0,
0189 0x9095, 0x02,
0190 0x9096, 0x47,
0191 0x9097, 0x3d,
0192 0xc924, 0x45,
0193 0xc925, 0xca,
0194 0xc926, 0x80,
0195 0xc927, 0x98,
0196 0x9098, 0x12,
0197 0x9099, 0x77,
0198 0x909a, 0xd6,
0199 0x909b, 0x02,
0200 0x909c, 0x45,
0201 0x909d, 0xcd,
0202 0xc928, 0x20,
0203 0xc929, 0xd5,
0204 0xc92a, 0x80,
0205 0xc92b, 0x9e,
0206 0x909e, 0x90,
0207 0x909f, 0x82,
0208 0x90a0, 0x18,
0209 0x90a1, 0xe0,
0210 0x90a2, 0xb4,
0211 0x90a3, 0x03,
0212 0x90a4, 0x0e,
0213 0x90a5, 0x90,
0214 0x90a6, 0x83,
0215 0x90a7, 0xbf,
0216 0x90a8, 0xe0,
0217 0x90a9, 0x60,
0218 0x90aa, 0x08,
0219 0x90ab, 0x90,
0220 0x90ac, 0x81,
0221 0x90ad, 0xfc,
0222 0x90ae, 0xe0,
0223 0x90af, 0xff,
0224 0x90b0, 0xc3,
0225 0x90b1, 0x13,
0226 0x90b2, 0xf0,
0227 0x90b3, 0x90,
0228 0x90b4, 0x81,
0229 0x90b5, 0xfc,
0230 0x90b6, 0xe0,
0231 0x90b7, 0xff,
0232 0x90b8, 0x02,
0233 0x90b9, 0x20,
0234 0x90ba, 0xda,
0235 0xc92c, 0x70,
0236 0xc92d, 0xbc,
0237 0xc92e, 0x80,
0238 0xc92f, 0xbb,
0239 0x90bb, 0x90,
0240 0x90bc, 0x82,
0241 0x90bd, 0x18,
0242 0x90be, 0xe0,
0243 0x90bf, 0xb4,
0244 0x90c0, 0x03,
0245 0x90c1, 0x06,
0246 0x90c2, 0x90,
0247 0x90c3, 0xc1,
0248 0x90c4, 0x06,
0249 0x90c5, 0x74,
0250 0x90c6, 0x05,
0251 0x90c7, 0xf0,
0252 0x90c8, 0x90,
0253 0x90c9, 0xd3,
0254 0x90ca, 0xa0,
0255 0x90cb, 0x02,
0256 0x90cc, 0x70,
0257 0x90cd, 0xbf,
0258 0xc930, 0x72,
0259 0xc931, 0x21,
0260 0xc932, 0x81,
0261 0xc933, 0x3b,
0262 0x913b, 0x7d,
0263 0x913c, 0x02,
0264 0x913d, 0x7f,
0265 0x913e, 0x7b,
0266 0x913f, 0x02,
0267 0x9140, 0x72,
0268 0x9141, 0x25,
0269 0xc934, 0x28,
0270 0xc935, 0xae,
0271 0xc936, 0x80,
0272 0xc937, 0xd2,
0273 0x90d2, 0xf0,
0274 0x90d3, 0x90,
0275 0x90d4, 0xd2,
0276 0x90d5, 0x0a,
0277 0x90d6, 0x02,
0278 0x90d7, 0x28,
0279 0x90d8, 0xb4,
0280 0xc938, 0x28,
0281 0xc939, 0xb1,
0282 0xc93a, 0x80,
0283 0xc93b, 0xd9,
0284 0x90d9, 0x90,
0285 0x90da, 0x83,
0286 0x90db, 0xba,
0287 0x90dc, 0xe0,
0288 0x90dd, 0xff,
0289 0x90de, 0x90,
0290 0x90df, 0xd2,
0291 0x90e0, 0x08,
0292 0x90e1, 0xe0,
0293 0x90e2, 0xe4,
0294 0x90e3, 0xef,
0295 0x90e4, 0xf0,
0296 0x90e5, 0xa3,
0297 0x90e6, 0xe0,
0298 0x90e7, 0x74,
0299 0x90e8, 0xff,
0300 0x90e9, 0xf0,
0301 0x90ea, 0x90,
0302 0x90eb, 0xd2,
0303 0x90ec, 0x0a,
0304 0x90ed, 0x02,
0305 0x90ee, 0x28,
0306 0x90ef, 0xb4,
0307 0xc93c, 0x29,
0308 0xc93d, 0x79,
0309 0xc93e, 0x80,
0310 0xc93f, 0xf0,
0311 0x90f0, 0xf0,
0312 0x90f1, 0x90,
0313 0x90f2, 0xd2,
0314 0x90f3, 0x0e,
0315 0x90f4, 0x02,
0316 0x90f5, 0x29,
0317 0x90f6, 0x7f,
0318 0xc940, 0x29,
0319 0xc941, 0x7c,
0320 0xc942, 0x80,
0321 0xc943, 0xf7,
0322 0x90f7, 0x90,
0323 0x90f8, 0x83,
0324 0x90f9, 0xba,
0325 0x90fa, 0xe0,
0326 0x90fb, 0xff,
0327 0x90fc, 0x90,
0328 0x90fd, 0xd2,
0329 0x90fe, 0x0c,
0330 0x90ff, 0xe0,
0331 0x9100, 0xe4,
0332 0x9101, 0xef,
0333 0x9102, 0xf0,
0334 0x9103, 0xa3,
0335 0x9104, 0xe0,
0336 0x9105, 0x74,
0337 0x9106, 0xff,
0338 0x9107, 0xf0,
0339 0x9108, 0x90,
0340 0x9109, 0xd2,
0341 0x910a, 0x0e,
0342 0x910b, 0x02,
0343 0x910c, 0x29,
0344 0x910d, 0x7f,
0345 0xc944, 0x2a,
0346 0xc945, 0x42,
0347 0xc946, 0x81,
0348 0xc947, 0x0e,
0349 0x910e, 0xf0,
0350 0x910f, 0x90,
0351 0x9110, 0xd2,
0352 0x9111, 0x12,
0353 0x9112, 0x02,
0354 0x9113, 0x2a,
0355 0x9114, 0x48,
0356 0xc948, 0x2a,
0357 0xc949, 0x45,
0358 0xc94a, 0x81,
0359 0xc94b, 0x15,
0360 0x9115, 0x90,
0361 0x9116, 0x83,
0362 0x9117, 0xba,
0363 0x9118, 0xe0,
0364 0x9119, 0xff,
0365 0x911a, 0x90,
0366 0x911b, 0xd2,
0367 0x911c, 0x10,
0368 0x911d, 0xe0,
0369 0x911e, 0xe4,
0370 0x911f, 0xef,
0371 0x9120, 0xf0,
0372 0x9121, 0xa3,
0373 0x9122, 0xe0,
0374 0x9123, 0x74,
0375 0x9124, 0xff,
0376 0x9125, 0xf0,
0377 0x9126, 0x90,
0378 0x9127, 0xd2,
0379 0x9128, 0x12,
0380 0x9129, 0x02,
0381 0x912a, 0x2a,
0382 0x912b, 0x48,
0383 0xc900, 0x01,
0384 0x0000, 0x00,
0385 };
0386
0387 static const u16 vs6624_p2[] = {
0388 0x806f, 0x01,
0389 0x058c, 0x01,
0390 0x0000, 0x00,
0391 };
0392
0393 static const u16 vs6624_run_setup[] = {
0394 0x1d18, 0x00,
0395 VS6624_PEAK_MIN_OUT_G_MSB, 0x3c,
0396 VS6624_PEAK_MIN_OUT_G_LSB, 0x66,
0397 VS6624_CM_LOW_THR_MSB, 0x65,
0398 VS6624_CM_LOW_THR_LSB, 0xd1,
0399 VS6624_CM_HIGH_THR_MSB, 0x66,
0400 VS6624_CM_HIGH_THR_LSB, 0x62,
0401 VS6624_CM_MIN_OUT_MSB, 0x00,
0402 VS6624_CM_MIN_OUT_LSB, 0x00,
0403 VS6624_NORA_DISABLE, 0x00,
0404 VS6624_NORA_USAGE, 0x04,
0405 VS6624_NORA_LOW_THR_MSB, 0x63,
0406 VS6624_NORA_LOW_THR_LSB, 0xd1,
0407 VS6624_NORA_HIGH_THR_MSB, 0x68,
0408 VS6624_NORA_HIGH_THR_LSB, 0xdd,
0409 VS6624_NORA_MIN_OUT_MSB, 0x3a,
0410 VS6624_NORA_MIN_OUT_LSB, 0x00,
0411 VS6624_F2B_DISABLE, 0x00,
0412 0x1d8a, 0x30,
0413 0x1d91, 0x62,
0414 0x1d92, 0x4a,
0415 0x1d95, 0x65,
0416 0x1d96, 0x0e,
0417 0x1da1, 0x3a,
0418 0x1da2, 0xb8,
0419 0x1e08, 0x06,
0420 0x1e0a, 0x0a,
0421 0x1601, 0x3a,
0422 0x1602, 0x14,
0423 0x1605, 0x3b,
0424 0x1606, 0x85,
0425 0x1609, 0x3b,
0426 0x160a, 0x85,
0427 0x160d, 0x3a,
0428 0x160e, 0x14,
0429 0x1611, 0x30,
0430 0x1612, 0x8f,
0431 0x1614, 0x01,
0432 0x0000, 0x00,
0433 };
0434
0435 static const u16 vs6624_default[] = {
0436 VS6624_CONTRAST0, 0x84,
0437 VS6624_SATURATION0, 0x75,
0438 VS6624_GAMMA0, 0x11,
0439 VS6624_CONTRAST1, 0x84,
0440 VS6624_SATURATION1, 0x75,
0441 VS6624_GAMMA1, 0x11,
0442 VS6624_MAN_RG, 0x80,
0443 VS6624_MAN_GG, 0x80,
0444 VS6624_MAN_BG, 0x80,
0445 VS6624_WB_MODE, 0x1,
0446 VS6624_EXPO_COMPENSATION, 0xfe,
0447 VS6624_EXPO_METER, 0x0,
0448 VS6624_LIGHT_FREQ, 0x64,
0449 VS6624_PEAK_GAIN, 0xe,
0450 VS6624_PEAK_LOW_THR, 0x28,
0451 VS6624_HMIRROR0, 0x0,
0452 VS6624_VFLIP0, 0x0,
0453 VS6624_ZOOM_HSTEP0_MSB, 0x0,
0454 VS6624_ZOOM_HSTEP0_LSB, 0x1,
0455 VS6624_ZOOM_VSTEP0_MSB, 0x0,
0456 VS6624_ZOOM_VSTEP0_LSB, 0x1,
0457 VS6624_PAN_HSTEP0_MSB, 0x0,
0458 VS6624_PAN_HSTEP0_LSB, 0xf,
0459 VS6624_PAN_VSTEP0_MSB, 0x0,
0460 VS6624_PAN_VSTEP0_LSB, 0xf,
0461 VS6624_SENSOR_MODE, 0x1,
0462 VS6624_SYNC_CODE_SETUP, 0x21,
0463 VS6624_DISABLE_FR_DAMPER, 0x0,
0464 VS6624_FR_DEN, 0x1,
0465 VS6624_FR_NUM_LSB, 0xf,
0466 VS6624_INIT_PIPE_SETUP, 0x0,
0467 VS6624_IMG_FMT0, 0x0,
0468 VS6624_YUV_SETUP, 0x1,
0469 VS6624_IMAGE_SIZE0, 0x2,
0470 0x0000, 0x00,
0471 };
0472
0473 static inline struct vs6624 *to_vs6624(struct v4l2_subdev *sd)
0474 {
0475 return container_of(sd, struct vs6624, sd);
0476 }
0477 static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
0478 {
0479 return &container_of(ctrl->handler, struct vs6624, hdl)->sd;
0480 }
0481
0482 #ifdef CONFIG_VIDEO_ADV_DEBUG
0483 static int vs6624_read(struct v4l2_subdev *sd, u16 index)
0484 {
0485 struct i2c_client *client = v4l2_get_subdevdata(sd);
0486 u8 buf[2];
0487
0488 buf[0] = index >> 8;
0489 buf[1] = index;
0490 i2c_master_send(client, buf, 2);
0491 i2c_master_recv(client, buf, 1);
0492
0493 return buf[0];
0494 }
0495 #endif
0496
0497 static int vs6624_write(struct v4l2_subdev *sd, u16 index,
0498 u8 value)
0499 {
0500 struct i2c_client *client = v4l2_get_subdevdata(sd);
0501 u8 buf[3];
0502
0503 buf[0] = index >> 8;
0504 buf[1] = index;
0505 buf[2] = value;
0506
0507 return i2c_master_send(client, buf, 3);
0508 }
0509
0510 static int vs6624_writeregs(struct v4l2_subdev *sd, const u16 *regs)
0511 {
0512 u16 reg;
0513 u8 data;
0514
0515 while (*regs != 0x00) {
0516 reg = *regs++;
0517 data = *regs++;
0518
0519 vs6624_write(sd, reg, data);
0520 }
0521 return 0;
0522 }
0523
0524 static int vs6624_s_ctrl(struct v4l2_ctrl *ctrl)
0525 {
0526 struct v4l2_subdev *sd = to_sd(ctrl);
0527
0528 switch (ctrl->id) {
0529 case V4L2_CID_CONTRAST:
0530 vs6624_write(sd, VS6624_CONTRAST0, ctrl->val);
0531 break;
0532 case V4L2_CID_SATURATION:
0533 vs6624_write(sd, VS6624_SATURATION0, ctrl->val);
0534 break;
0535 case V4L2_CID_HFLIP:
0536 vs6624_write(sd, VS6624_HMIRROR0, ctrl->val);
0537 break;
0538 case V4L2_CID_VFLIP:
0539 vs6624_write(sd, VS6624_VFLIP0, ctrl->val);
0540 break;
0541 default:
0542 return -EINVAL;
0543 }
0544
0545 return 0;
0546 }
0547
0548 static int vs6624_enum_mbus_code(struct v4l2_subdev *sd,
0549 struct v4l2_subdev_state *sd_state,
0550 struct v4l2_subdev_mbus_code_enum *code)
0551 {
0552 if (code->pad || code->index >= ARRAY_SIZE(vs6624_formats))
0553 return -EINVAL;
0554
0555 code->code = vs6624_formats[code->index].mbus_code;
0556 return 0;
0557 }
0558
0559 static int vs6624_set_fmt(struct v4l2_subdev *sd,
0560 struct v4l2_subdev_state *sd_state,
0561 struct v4l2_subdev_format *format)
0562 {
0563 struct v4l2_mbus_framefmt *fmt = &format->format;
0564 struct vs6624 *sensor = to_vs6624(sd);
0565 int index;
0566
0567 if (format->pad)
0568 return -EINVAL;
0569
0570 for (index = 0; index < ARRAY_SIZE(vs6624_formats); index++)
0571 if (vs6624_formats[index].mbus_code == fmt->code)
0572 break;
0573 if (index >= ARRAY_SIZE(vs6624_formats)) {
0574
0575 index = 0;
0576 fmt->code = vs6624_formats[0].mbus_code;
0577 }
0578
0579
0580 if (fmt->width > VGA_WIDTH)
0581 fmt->width = VGA_WIDTH;
0582 if (fmt->height > VGA_HEIGHT)
0583 fmt->height = VGA_HEIGHT;
0584 fmt->width = fmt->width & (~3);
0585 fmt->height = fmt->height & (~3);
0586 fmt->field = V4L2_FIELD_NONE;
0587 fmt->colorspace = vs6624_formats[index].colorspace;
0588
0589 if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
0590 sd_state->pads->try_fmt = *fmt;
0591 return 0;
0592 }
0593
0594
0595 switch (fmt->code) {
0596 case MEDIA_BUS_FMT_UYVY8_2X8:
0597 vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
0598 vs6624_write(sd, VS6624_YUV_SETUP, 0x1);
0599 break;
0600 case MEDIA_BUS_FMT_YUYV8_2X8:
0601 vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
0602 vs6624_write(sd, VS6624_YUV_SETUP, 0x3);
0603 break;
0604 case MEDIA_BUS_FMT_RGB565_2X8_LE:
0605 vs6624_write(sd, VS6624_IMG_FMT0, 0x4);
0606 vs6624_write(sd, VS6624_RGB_SETUP, 0x0);
0607 break;
0608 default:
0609 return -EINVAL;
0610 }
0611
0612
0613 if ((fmt->width == VGA_WIDTH) && (fmt->height == VGA_HEIGHT))
0614 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x2);
0615 else if ((fmt->width == QVGA_WIDTH) && (fmt->height == QVGA_HEIGHT))
0616 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x4);
0617 else if ((fmt->width == QQVGA_WIDTH) && (fmt->height == QQVGA_HEIGHT))
0618 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x6);
0619 else if ((fmt->width == CIF_WIDTH) && (fmt->height == CIF_HEIGHT))
0620 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x3);
0621 else if ((fmt->width == QCIF_WIDTH) && (fmt->height == QCIF_HEIGHT))
0622 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x5);
0623 else if ((fmt->width == QQCIF_WIDTH) && (fmt->height == QQCIF_HEIGHT))
0624 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x7);
0625 else {
0626 vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x8);
0627 vs6624_write(sd, VS6624_MAN_HSIZE0_MSB, fmt->width >> 8);
0628 vs6624_write(sd, VS6624_MAN_HSIZE0_LSB, fmt->width & 0xFF);
0629 vs6624_write(sd, VS6624_MAN_VSIZE0_MSB, fmt->height >> 8);
0630 vs6624_write(sd, VS6624_MAN_VSIZE0_LSB, fmt->height & 0xFF);
0631 vs6624_write(sd, VS6624_CROP_CTRL0, 0x1);
0632 }
0633
0634 sensor->fmt = *fmt;
0635
0636 return 0;
0637 }
0638
0639 static int vs6624_get_fmt(struct v4l2_subdev *sd,
0640 struct v4l2_subdev_state *sd_state,
0641 struct v4l2_subdev_format *format)
0642 {
0643 struct vs6624 *sensor = to_vs6624(sd);
0644
0645 if (format->pad)
0646 return -EINVAL;
0647
0648 format->format = sensor->fmt;
0649 return 0;
0650 }
0651
0652 static int vs6624_g_frame_interval(struct v4l2_subdev *sd,
0653 struct v4l2_subdev_frame_interval *ival)
0654 {
0655 struct vs6624 *sensor = to_vs6624(sd);
0656
0657 ival->interval.numerator = sensor->frame_rate.denominator;
0658 ival->interval.denominator = sensor->frame_rate.numerator;
0659 return 0;
0660 }
0661
0662 static int vs6624_s_frame_interval(struct v4l2_subdev *sd,
0663 struct v4l2_subdev_frame_interval *ival)
0664 {
0665 struct vs6624 *sensor = to_vs6624(sd);
0666 struct v4l2_fract *tpf = &ival->interval;
0667
0668
0669 if (tpf->numerator == 0 || tpf->denominator == 0
0670 || (tpf->denominator > tpf->numerator * MAX_FRAME_RATE)) {
0671
0672 tpf->numerator = 1;
0673 tpf->denominator = MAX_FRAME_RATE;
0674 }
0675 sensor->frame_rate.numerator = tpf->denominator;
0676 sensor->frame_rate.denominator = tpf->numerator;
0677 vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0);
0678 vs6624_write(sd, VS6624_FR_NUM_MSB,
0679 sensor->frame_rate.numerator >> 8);
0680 vs6624_write(sd, VS6624_FR_NUM_LSB,
0681 sensor->frame_rate.numerator & 0xFF);
0682 vs6624_write(sd, VS6624_FR_DEN,
0683 sensor->frame_rate.denominator & 0xFF);
0684 return 0;
0685 }
0686
0687 static int vs6624_s_stream(struct v4l2_subdev *sd, int enable)
0688 {
0689 if (enable)
0690 vs6624_write(sd, VS6624_USER_CMD, 0x2);
0691 else
0692 vs6624_write(sd, VS6624_USER_CMD, 0x4);
0693 udelay(100);
0694 return 0;
0695 }
0696
0697 #ifdef CONFIG_VIDEO_ADV_DEBUG
0698 static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
0699 {
0700 reg->val = vs6624_read(sd, reg->reg & 0xffff);
0701 reg->size = 1;
0702 return 0;
0703 }
0704
0705 static int vs6624_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
0706 {
0707 vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff);
0708 return 0;
0709 }
0710 #endif
0711
0712 static const struct v4l2_ctrl_ops vs6624_ctrl_ops = {
0713 .s_ctrl = vs6624_s_ctrl,
0714 };
0715
0716 static const struct v4l2_subdev_core_ops vs6624_core_ops = {
0717 #ifdef CONFIG_VIDEO_ADV_DEBUG
0718 .g_register = vs6624_g_register,
0719 .s_register = vs6624_s_register,
0720 #endif
0721 };
0722
0723 static const struct v4l2_subdev_video_ops vs6624_video_ops = {
0724 .s_frame_interval = vs6624_s_frame_interval,
0725 .g_frame_interval = vs6624_g_frame_interval,
0726 .s_stream = vs6624_s_stream,
0727 };
0728
0729 static const struct v4l2_subdev_pad_ops vs6624_pad_ops = {
0730 .enum_mbus_code = vs6624_enum_mbus_code,
0731 .get_fmt = vs6624_get_fmt,
0732 .set_fmt = vs6624_set_fmt,
0733 };
0734
0735 static const struct v4l2_subdev_ops vs6624_ops = {
0736 .core = &vs6624_core_ops,
0737 .video = &vs6624_video_ops,
0738 .pad = &vs6624_pad_ops,
0739 };
0740
0741 static int vs6624_probe(struct i2c_client *client,
0742 const struct i2c_device_id *id)
0743 {
0744 struct vs6624 *sensor;
0745 struct v4l2_subdev *sd;
0746 struct v4l2_ctrl_handler *hdl;
0747 const unsigned *ce;
0748 int ret;
0749
0750
0751 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
0752 return -EIO;
0753
0754 ce = client->dev.platform_data;
0755 if (ce == NULL)
0756 return -EINVAL;
0757
0758 ret = devm_gpio_request_one(&client->dev, *ce, GPIOF_OUT_INIT_HIGH,
0759 "VS6624 Chip Enable");
0760 if (ret) {
0761 v4l_err(client, "failed to request GPIO %d\n", *ce);
0762 return ret;
0763 }
0764
0765 msleep(100);
0766
0767 sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
0768 if (sensor == NULL)
0769 return -ENOMEM;
0770
0771 sd = &sensor->sd;
0772 v4l2_i2c_subdev_init(sd, client, &vs6624_ops);
0773
0774 vs6624_writeregs(sd, vs6624_p1);
0775 vs6624_write(sd, VS6624_MICRO_EN, 0x2);
0776 vs6624_write(sd, VS6624_DIO_EN, 0x1);
0777 usleep_range(10000, 11000);
0778 vs6624_writeregs(sd, vs6624_p2);
0779
0780 vs6624_writeregs(sd, vs6624_default);
0781 vs6624_write(sd, VS6624_HSYNC_SETUP, 0xF);
0782 vs6624_writeregs(sd, vs6624_run_setup);
0783
0784
0785 sensor->frame_rate.numerator = MAX_FRAME_RATE;
0786 sensor->frame_rate.denominator = 1;
0787 vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0);
0788 vs6624_write(sd, VS6624_FR_NUM_MSB,
0789 sensor->frame_rate.numerator >> 8);
0790 vs6624_write(sd, VS6624_FR_NUM_LSB,
0791 sensor->frame_rate.numerator & 0xFF);
0792 vs6624_write(sd, VS6624_FR_DEN,
0793 sensor->frame_rate.denominator & 0xFF);
0794
0795 sensor->fmt = vs6624_default_fmt;
0796 sensor->ce_pin = *ce;
0797
0798 v4l_info(client, "chip found @ 0x%02x (%s)\n",
0799 client->addr << 1, client->adapter->name);
0800
0801 hdl = &sensor->hdl;
0802 v4l2_ctrl_handler_init(hdl, 4);
0803 v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
0804 V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x87);
0805 v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
0806 V4L2_CID_SATURATION, 0, 0xFF, 1, 0x78);
0807 v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
0808 V4L2_CID_HFLIP, 0, 1, 1, 0);
0809 v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
0810 V4L2_CID_VFLIP, 0, 1, 1, 0);
0811
0812 sd->ctrl_handler = hdl;
0813 if (hdl->error) {
0814 int err = hdl->error;
0815
0816 v4l2_ctrl_handler_free(hdl);
0817 return err;
0818 }
0819
0820
0821 ret = v4l2_ctrl_handler_setup(hdl);
0822 if (ret)
0823 v4l2_ctrl_handler_free(hdl);
0824 return ret;
0825 }
0826
0827 static int vs6624_remove(struct i2c_client *client)
0828 {
0829 struct v4l2_subdev *sd = i2c_get_clientdata(client);
0830
0831 v4l2_device_unregister_subdev(sd);
0832 v4l2_ctrl_handler_free(sd->ctrl_handler);
0833 return 0;
0834 }
0835
0836 static const struct i2c_device_id vs6624_id[] = {
0837 {"vs6624", 0},
0838 {},
0839 };
0840
0841 MODULE_DEVICE_TABLE(i2c, vs6624_id);
0842
0843 static struct i2c_driver vs6624_driver = {
0844 .driver = {
0845 .name = "vs6624",
0846 },
0847 .probe = vs6624_probe,
0848 .remove = vs6624_remove,
0849 .id_table = vs6624_id,
0850 };
0851
0852 module_i2c_driver(vs6624_driver);
0853
0854 MODULE_DESCRIPTION("VS6624 sensor driver");
0855 MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
0856 MODULE_LICENSE("GPL v2");