Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.11-rc6 608 lines 15 kB view raw
1/* 2 * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor 3 * 4 * Copyright (c) 2009 Mauro Carvalho Chehab 5 * This code is placed under the terms of the GNU General Public License v2 6 */ 7 8#include <linux/i2c.h> 9#include <linux/slab.h> 10#include <linux/videodev2.h> 11#include <linux/delay.h> 12#include <linux/module.h> 13#include <asm/div64.h> 14#include <media/v4l2-device.h> 15#include <media/v4l2-ctrls.h> 16#include <media/i2c/mt9v011.h> 17 18MODULE_DESCRIPTION("Micron mt9v011 sensor driver"); 19MODULE_AUTHOR("Mauro Carvalho Chehab"); 20MODULE_LICENSE("GPL"); 21 22static int debug; 23module_param(debug, int, 0); 24MODULE_PARM_DESC(debug, "Debug level (0-2)"); 25 26#define R00_MT9V011_CHIP_VERSION 0x00 27#define R01_MT9V011_ROWSTART 0x01 28#define R02_MT9V011_COLSTART 0x02 29#define R03_MT9V011_HEIGHT 0x03 30#define R04_MT9V011_WIDTH 0x04 31#define R05_MT9V011_HBLANK 0x05 32#define R06_MT9V011_VBLANK 0x06 33#define R07_MT9V011_OUT_CTRL 0x07 34#define R09_MT9V011_SHUTTER_WIDTH 0x09 35#define R0A_MT9V011_CLK_SPEED 0x0a 36#define R0B_MT9V011_RESTART 0x0b 37#define R0C_MT9V011_SHUTTER_DELAY 0x0c 38#define R0D_MT9V011_RESET 0x0d 39#define R1E_MT9V011_DIGITAL_ZOOM 0x1e 40#define R20_MT9V011_READ_MODE 0x20 41#define R2B_MT9V011_GREEN_1_GAIN 0x2b 42#define R2C_MT9V011_BLUE_GAIN 0x2c 43#define R2D_MT9V011_RED_GAIN 0x2d 44#define R2E_MT9V011_GREEN_2_GAIN 0x2e 45#define R35_MT9V011_GLOBAL_GAIN 0x35 46#define RF1_MT9V011_CHIP_ENABLE 0xf1 47 48#define MT9V011_VERSION 0x8232 49#define MT9V011_REV_B_VERSION 0x8243 50 51struct mt9v011 { 52 struct v4l2_subdev sd; 53#ifdef CONFIG_MEDIA_CONTROLLER 54 struct media_pad pad; 55#endif 56 struct v4l2_ctrl_handler ctrls; 57 unsigned width, height; 58 unsigned xtal; 59 unsigned hflip:1; 60 unsigned vflip:1; 61 62 u16 global_gain, exposure; 63 s16 red_bal, blue_bal; 64}; 65 66static inline struct mt9v011 *to_mt9v011(struct v4l2_subdev *sd) 67{ 68 return container_of(sd, struct mt9v011, sd); 69} 70 71static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr) 72{ 73 struct i2c_client *c = v4l2_get_subdevdata(sd); 74 __be16 buffer; 75 int rc, val; 76 77 rc = i2c_master_send(c, &addr, 1); 78 if (rc != 1) 79 v4l2_dbg(0, debug, sd, 80 "i2c i/o error: rc == %d (should be 1)\n", rc); 81 82 msleep(10); 83 84 rc = i2c_master_recv(c, (char *)&buffer, 2); 85 if (rc != 2) 86 v4l2_dbg(0, debug, sd, 87 "i2c i/o error: rc == %d (should be 2)\n", rc); 88 89 val = be16_to_cpu(buffer); 90 91 v4l2_dbg(2, debug, sd, "mt9v011: read 0x%02x = 0x%04x\n", addr, val); 92 93 return val; 94} 95 96static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr, 97 u16 value) 98{ 99 struct i2c_client *c = v4l2_get_subdevdata(sd); 100 unsigned char buffer[3]; 101 int rc; 102 103 buffer[0] = addr; 104 buffer[1] = value >> 8; 105 buffer[2] = value & 0xff; 106 107 v4l2_dbg(2, debug, sd, 108 "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value); 109 rc = i2c_master_send(c, buffer, 3); 110 if (rc != 3) 111 v4l2_dbg(0, debug, sd, 112 "i2c i/o error: rc == %d (should be 3)\n", rc); 113} 114 115 116struct i2c_reg_value { 117 unsigned char reg; 118 u16 value; 119}; 120 121/* 122 * Values used at the original driver 123 * Some values are marked as Reserved at the datasheet 124 */ 125static const struct i2c_reg_value mt9v011_init_default[] = { 126 { R0D_MT9V011_RESET, 0x0001 }, 127 { R0D_MT9V011_RESET, 0x0000 }, 128 129 { R0C_MT9V011_SHUTTER_DELAY, 0x0000 }, 130 { R09_MT9V011_SHUTTER_WIDTH, 0x1fc }, 131 132 { R0A_MT9V011_CLK_SPEED, 0x0000 }, 133 { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, 134 135 { R07_MT9V011_OUT_CTRL, 0x0002 }, /* chip enable */ 136}; 137 138 139static u16 calc_mt9v011_gain(s16 lineargain) 140{ 141 142 u16 digitalgain = 0; 143 u16 analogmult = 0; 144 u16 analoginit = 0; 145 146 if (lineargain < 0) 147 lineargain = 0; 148 149 /* recommended minimum */ 150 lineargain += 0x0020; 151 152 if (lineargain > 2047) 153 lineargain = 2047; 154 155 if (lineargain > 1023) { 156 digitalgain = 3; 157 analogmult = 3; 158 analoginit = lineargain / 16; 159 } else if (lineargain > 511) { 160 digitalgain = 1; 161 analogmult = 3; 162 analoginit = lineargain / 8; 163 } else if (lineargain > 255) { 164 analogmult = 3; 165 analoginit = lineargain / 4; 166 } else if (lineargain > 127) { 167 analogmult = 1; 168 analoginit = lineargain / 2; 169 } else 170 analoginit = lineargain; 171 172 return analoginit + (analogmult << 7) + (digitalgain << 9); 173 174} 175 176static void set_balance(struct v4l2_subdev *sd) 177{ 178 struct mt9v011 *core = to_mt9v011(sd); 179 u16 green_gain, blue_gain, red_gain; 180 u16 exposure; 181 s16 bal; 182 183 exposure = core->exposure; 184 185 green_gain = calc_mt9v011_gain(core->global_gain); 186 187 bal = core->global_gain; 188 bal += (core->blue_bal * core->global_gain / (1 << 7)); 189 blue_gain = calc_mt9v011_gain(bal); 190 191 bal = core->global_gain; 192 bal += (core->red_bal * core->global_gain / (1 << 7)); 193 red_gain = calc_mt9v011_gain(bal); 194 195 mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green_gain); 196 mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN, green_gain); 197 mt9v011_write(sd, R2C_MT9V011_BLUE_GAIN, blue_gain); 198 mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); 199 mt9v011_write(sd, R09_MT9V011_SHUTTER_WIDTH, exposure); 200} 201 202static void calc_fps(struct v4l2_subdev *sd, u32 *numerator, u32 *denominator) 203{ 204 struct mt9v011 *core = to_mt9v011(sd); 205 unsigned height, width, hblank, vblank, speed; 206 unsigned row_time, t_time; 207 u64 frames_per_ms; 208 unsigned tmp; 209 210 height = mt9v011_read(sd, R03_MT9V011_HEIGHT); 211 width = mt9v011_read(sd, R04_MT9V011_WIDTH); 212 hblank = mt9v011_read(sd, R05_MT9V011_HBLANK); 213 vblank = mt9v011_read(sd, R06_MT9V011_VBLANK); 214 speed = mt9v011_read(sd, R0A_MT9V011_CLK_SPEED); 215 216 row_time = (width + 113 + hblank) * (speed + 2); 217 t_time = row_time * (height + vblank + 1); 218 219 frames_per_ms = core->xtal * 1000l; 220 do_div(frames_per_ms, t_time); 221 tmp = frames_per_ms; 222 223 v4l2_dbg(1, debug, sd, "Programmed to %u.%03u fps (%d pixel clcks)\n", 224 tmp / 1000, tmp % 1000, t_time); 225 226 if (numerator && denominator) { 227 *numerator = 1000; 228 *denominator = (u32)frames_per_ms; 229 } 230} 231 232static u16 calc_speed(struct v4l2_subdev *sd, u32 numerator, u32 denominator) 233{ 234 struct mt9v011 *core = to_mt9v011(sd); 235 unsigned height, width, hblank, vblank; 236 unsigned row_time, line_time; 237 u64 t_time, speed; 238 239 /* Avoid bogus calculus */ 240 if (!numerator || !denominator) 241 return 0; 242 243 height = mt9v011_read(sd, R03_MT9V011_HEIGHT); 244 width = mt9v011_read(sd, R04_MT9V011_WIDTH); 245 hblank = mt9v011_read(sd, R05_MT9V011_HBLANK); 246 vblank = mt9v011_read(sd, R06_MT9V011_VBLANK); 247 248 row_time = width + 113 + hblank; 249 line_time = height + vblank + 1; 250 251 t_time = core->xtal * ((u64)numerator); 252 /* round to the closest value */ 253 t_time += denominator / 2; 254 do_div(t_time, denominator); 255 256 speed = t_time; 257 do_div(speed, row_time * line_time); 258 259 /* Avoid having a negative value for speed */ 260 if (speed < 2) 261 speed = 0; 262 else 263 speed -= 2; 264 265 /* Avoid speed overflow */ 266 if (speed > 15) 267 return 15; 268 269 return (u16)speed; 270} 271 272static void set_res(struct v4l2_subdev *sd) 273{ 274 struct mt9v011 *core = to_mt9v011(sd); 275 unsigned vstart, hstart; 276 277 /* 278 * The mt9v011 doesn't have scaling. So, in order to select the desired 279 * resolution, we're cropping at the middle of the sensor. 280 * hblank and vblank should be adjusted, in order to warrant that 281 * we'll preserve the line timings for 30 fps, no matter what resolution 282 * is selected. 283 * NOTE: datasheet says that width (and height) should be filled with 284 * width-1. However, this doesn't work, since one pixel per line will 285 * be missing. 286 */ 287 288 hstart = 20 + (640 - core->width) / 2; 289 mt9v011_write(sd, R02_MT9V011_COLSTART, hstart); 290 mt9v011_write(sd, R04_MT9V011_WIDTH, core->width); 291 mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width); 292 293 vstart = 8 + (480 - core->height) / 2; 294 mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart); 295 mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height); 296 mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height); 297 298 calc_fps(sd, NULL, NULL); 299}; 300 301static void set_read_mode(struct v4l2_subdev *sd) 302{ 303 struct mt9v011 *core = to_mt9v011(sd); 304 unsigned mode = 0x1000; 305 306 if (core->hflip) 307 mode |= 0x4000; 308 309 if (core->vflip) 310 mode |= 0x8000; 311 312 mt9v011_write(sd, R20_MT9V011_READ_MODE, mode); 313} 314 315static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) 316{ 317 int i; 318 319 for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++) 320 mt9v011_write(sd, mt9v011_init_default[i].reg, 321 mt9v011_init_default[i].value); 322 323 set_balance(sd); 324 set_res(sd); 325 set_read_mode(sd); 326 327 return 0; 328} 329 330static int mt9v011_enum_mbus_code(struct v4l2_subdev *sd, 331 struct v4l2_subdev_pad_config *cfg, 332 struct v4l2_subdev_mbus_code_enum *code) 333{ 334 if (code->pad || code->index > 0) 335 return -EINVAL; 336 337 code->code = MEDIA_BUS_FMT_SGRBG8_1X8; 338 return 0; 339} 340 341static int mt9v011_set_fmt(struct v4l2_subdev *sd, 342 struct v4l2_subdev_pad_config *cfg, 343 struct v4l2_subdev_format *format) 344{ 345 struct v4l2_mbus_framefmt *fmt = &format->format; 346 struct mt9v011 *core = to_mt9v011(sd); 347 348 if (format->pad || fmt->code != MEDIA_BUS_FMT_SGRBG8_1X8) 349 return -EINVAL; 350 351 v4l_bound_align_image(&fmt->width, 48, 639, 1, 352 &fmt->height, 32, 480, 1, 0); 353 fmt->field = V4L2_FIELD_NONE; 354 fmt->colorspace = V4L2_COLORSPACE_SRGB; 355 356 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { 357 core->width = fmt->width; 358 core->height = fmt->height; 359 360 set_res(sd); 361 } else { 362 cfg->try_fmt = *fmt; 363 } 364 365 return 0; 366} 367 368static int mt9v011_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) 369{ 370 struct v4l2_captureparm *cp = &parms->parm.capture; 371 372 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 373 return -EINVAL; 374 375 memset(cp, 0, sizeof(struct v4l2_captureparm)); 376 cp->capability = V4L2_CAP_TIMEPERFRAME; 377 calc_fps(sd, 378 &cp->timeperframe.numerator, 379 &cp->timeperframe.denominator); 380 381 return 0; 382} 383 384static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) 385{ 386 struct v4l2_captureparm *cp = &parms->parm.capture; 387 struct v4l2_fract *tpf = &cp->timeperframe; 388 u16 speed; 389 390 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 391 return -EINVAL; 392 if (cp->extendedmode != 0) 393 return -EINVAL; 394 395 speed = calc_speed(sd, tpf->numerator, tpf->denominator); 396 397 mt9v011_write(sd, R0A_MT9V011_CLK_SPEED, speed); 398 v4l2_dbg(1, debug, sd, "Setting speed to %d\n", speed); 399 400 /* Recalculate and update fps info */ 401 calc_fps(sd, &tpf->numerator, &tpf->denominator); 402 403 return 0; 404} 405 406#ifdef CONFIG_VIDEO_ADV_DEBUG 407static int mt9v011_g_register(struct v4l2_subdev *sd, 408 struct v4l2_dbg_register *reg) 409{ 410 reg->val = mt9v011_read(sd, reg->reg & 0xff); 411 reg->size = 2; 412 413 return 0; 414} 415 416static int mt9v011_s_register(struct v4l2_subdev *sd, 417 const struct v4l2_dbg_register *reg) 418{ 419 mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff); 420 421 return 0; 422} 423#endif 424 425static int mt9v011_s_ctrl(struct v4l2_ctrl *ctrl) 426{ 427 struct mt9v011 *core = 428 container_of(ctrl->handler, struct mt9v011, ctrls); 429 struct v4l2_subdev *sd = &core->sd; 430 431 switch (ctrl->id) { 432 case V4L2_CID_GAIN: 433 core->global_gain = ctrl->val; 434 break; 435 case V4L2_CID_EXPOSURE: 436 core->exposure = ctrl->val; 437 break; 438 case V4L2_CID_RED_BALANCE: 439 core->red_bal = ctrl->val; 440 break; 441 case V4L2_CID_BLUE_BALANCE: 442 core->blue_bal = ctrl->val; 443 break; 444 case V4L2_CID_HFLIP: 445 core->hflip = ctrl->val; 446 set_read_mode(sd); 447 return 0; 448 case V4L2_CID_VFLIP: 449 core->vflip = ctrl->val; 450 set_read_mode(sd); 451 return 0; 452 default: 453 return -EINVAL; 454 } 455 456 set_balance(sd); 457 return 0; 458} 459 460static const struct v4l2_ctrl_ops mt9v011_ctrl_ops = { 461 .s_ctrl = mt9v011_s_ctrl, 462}; 463 464static const struct v4l2_subdev_core_ops mt9v011_core_ops = { 465 .reset = mt9v011_reset, 466#ifdef CONFIG_VIDEO_ADV_DEBUG 467 .g_register = mt9v011_g_register, 468 .s_register = mt9v011_s_register, 469#endif 470}; 471 472static const struct v4l2_subdev_video_ops mt9v011_video_ops = { 473 .g_parm = mt9v011_g_parm, 474 .s_parm = mt9v011_s_parm, 475}; 476 477static const struct v4l2_subdev_pad_ops mt9v011_pad_ops = { 478 .enum_mbus_code = mt9v011_enum_mbus_code, 479 .set_fmt = mt9v011_set_fmt, 480}; 481 482static const struct v4l2_subdev_ops mt9v011_ops = { 483 .core = &mt9v011_core_ops, 484 .video = &mt9v011_video_ops, 485 .pad = &mt9v011_pad_ops, 486}; 487 488 489/**************************************************************************** 490 I2C Client & Driver 491 ****************************************************************************/ 492 493static int mt9v011_probe(struct i2c_client *c, 494 const struct i2c_device_id *id) 495{ 496 u16 version; 497 struct mt9v011 *core; 498 struct v4l2_subdev *sd; 499#ifdef CONFIG_MEDIA_CONTROLLER 500 int ret; 501#endif 502 503 /* Check if the adapter supports the needed features */ 504 if (!i2c_check_functionality(c->adapter, 505 I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) 506 return -EIO; 507 508 core = devm_kzalloc(&c->dev, sizeof(struct mt9v011), GFP_KERNEL); 509 if (!core) 510 return -ENOMEM; 511 512 sd = &core->sd; 513 v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); 514 515#ifdef CONFIG_MEDIA_CONTROLLER 516 core->pad.flags = MEDIA_PAD_FL_SOURCE; 517 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; 518 519 ret = media_entity_pads_init(&sd->entity, 1, &core->pad); 520 if (ret < 0) 521 return ret; 522#endif 523 524 /* Check if the sensor is really a MT9V011 */ 525 version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); 526 if ((version != MT9V011_VERSION) && 527 (version != MT9V011_REV_B_VERSION)) { 528 v4l2_info(sd, "*** unknown micron chip detected (0x%04x).\n", 529 version); 530 return -EINVAL; 531 } 532 533 v4l2_ctrl_handler_init(&core->ctrls, 5); 534 v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops, 535 V4L2_CID_GAIN, 0, (1 << 12) - 1 - 0x20, 1, 0x20); 536 v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops, 537 V4L2_CID_EXPOSURE, 0, 2047, 1, 0x01fc); 538 v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops, 539 V4L2_CID_RED_BALANCE, -(1 << 9), (1 << 9) - 1, 1, 0); 540 v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops, 541 V4L2_CID_BLUE_BALANCE, -(1 << 9), (1 << 9) - 1, 1, 0); 542 v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops, 543 V4L2_CID_HFLIP, 0, 1, 1, 0); 544 v4l2_ctrl_new_std(&core->ctrls, &mt9v011_ctrl_ops, 545 V4L2_CID_VFLIP, 0, 1, 1, 0); 546 547 if (core->ctrls.error) { 548 int ret = core->ctrls.error; 549 550 v4l2_err(sd, "control initialization error %d\n", ret); 551 v4l2_ctrl_handler_free(&core->ctrls); 552 return ret; 553 } 554 core->sd.ctrl_handler = &core->ctrls; 555 556 core->global_gain = 0x0024; 557 core->exposure = 0x01fc; 558 core->width = 640; 559 core->height = 480; 560 core->xtal = 27000000; /* Hz */ 561 562 if (c->dev.platform_data) { 563 struct mt9v011_platform_data *pdata = c->dev.platform_data; 564 565 core->xtal = pdata->xtal; 566 v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n", 567 core->xtal / 1000000, (core->xtal / 1000) % 1000); 568 } 569 570 v4l_info(c, "chip found @ 0x%02x (%s - chip version 0x%04x)\n", 571 c->addr << 1, c->adapter->name, version); 572 573 return 0; 574} 575 576static int mt9v011_remove(struct i2c_client *c) 577{ 578 struct v4l2_subdev *sd = i2c_get_clientdata(c); 579 struct mt9v011 *core = to_mt9v011(sd); 580 581 v4l2_dbg(1, debug, sd, 582 "mt9v011.c: removing mt9v011 adapter on address 0x%x\n", 583 c->addr << 1); 584 585 v4l2_device_unregister_subdev(sd); 586 v4l2_ctrl_handler_free(&core->ctrls); 587 588 return 0; 589} 590 591/* ----------------------------------------------------------------------- */ 592 593static const struct i2c_device_id mt9v011_id[] = { 594 { "mt9v011", 0 }, 595 { } 596}; 597MODULE_DEVICE_TABLE(i2c, mt9v011_id); 598 599static struct i2c_driver mt9v011_driver = { 600 .driver = { 601 .name = "mt9v011", 602 }, 603 .probe = mt9v011_probe, 604 .remove = mt9v011_remove, 605 .id_table = mt9v011_id, 606}; 607 608module_i2c_driver(mt9v011_driver);