1 /* 2 * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor 3 * 4 * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com) 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-chip-ident.h> 16 #include <media/mt9v011.h> 17 18 MODULE_DESCRIPTION("Micron mt9v011 sensor driver"); 19 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); 20 MODULE_LICENSE("GPL"); 21 22 static int debug; 23 module_param(debug, int, 0); 24 MODULE_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 51 /* supported controls */ 52 static struct v4l2_queryctrl mt9v011_qctrl[] = { 53 { 54 .id = V4L2_CID_GAIN, 55 .type = V4L2_CTRL_TYPE_INTEGER, 56 .name = "Gain", 57 .minimum = 0, 58 .maximum = (1 << 12) - 1 - 0x0020, 59 .step = 1, 60 .default_value = 0x0020, 61 .flags = 0, 62 }, { 63 .id = V4L2_CID_EXPOSURE, 64 .type = V4L2_CTRL_TYPE_INTEGER, 65 .name = "Exposure", 66 .minimum = 0, 67 .maximum = 2047, 68 .step = 1, 69 .default_value = 0x01fc, 70 .flags = 0, 71 }, { 72 .id = V4L2_CID_RED_BALANCE, 73 .type = V4L2_CTRL_TYPE_INTEGER, 74 .name = "Red Balance", 75 .minimum = -1 << 9, 76 .maximum = (1 << 9) - 1, 77 .step = 1, 78 .default_value = 0, 79 .flags = 0, 80 }, { 81 .id = V4L2_CID_BLUE_BALANCE, 82 .type = V4L2_CTRL_TYPE_INTEGER, 83 .name = "Blue Balance", 84 .minimum = -1 << 9, 85 .maximum = (1 << 9) - 1, 86 .step = 1, 87 .default_value = 0, 88 .flags = 0, 89 }, { 90 .id = V4L2_CID_HFLIP, 91 .type = V4L2_CTRL_TYPE_BOOLEAN, 92 .name = "Mirror", 93 .minimum = 0, 94 .maximum = 1, 95 .step = 1, 96 .default_value = 0, 97 .flags = 0, 98 }, { 99 .id = V4L2_CID_VFLIP, 100 .type = V4L2_CTRL_TYPE_BOOLEAN, 101 .name = "Vflip", 102 .minimum = 0, 103 .maximum = 1, 104 .step = 1, 105 .default_value = 0, 106 .flags = 0, 107 }, { 108 } 109 }; 110 111 struct mt9v011 { 112 struct v4l2_subdev sd; 113 unsigned width, height; 114 unsigned xtal; 115 unsigned hflip:1; 116 unsigned vflip:1; 117 118 u16 global_gain, exposure; 119 s16 red_bal, blue_bal; 120 }; 121 122 static inline struct mt9v011 *to_mt9v011(struct v4l2_subdev *sd) 123 { 124 return container_of(sd, struct mt9v011, sd); 125 } 126 127 static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr) 128 { 129 struct i2c_client *c = v4l2_get_subdevdata(sd); 130 __be16 buffer; 131 int rc, val; 132 133 rc = i2c_master_send(c, &addr, 1); 134 if (rc != 1) 135 v4l2_dbg(0, debug, sd, 136 "i2c i/o error: rc == %d (should be 1)\n", rc); 137 138 msleep(10); 139 140 rc = i2c_master_recv(c, (char *)&buffer, 2); 141 if (rc != 2) 142 v4l2_dbg(0, debug, sd, 143 "i2c i/o error: rc == %d (should be 2)\n", rc); 144 145 val = be16_to_cpu(buffer); 146 147 v4l2_dbg(2, debug, sd, "mt9v011: read 0x%02x = 0x%04x\n", addr, val); 148 149 return val; 150 } 151 152 static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr, 153 u16 value) 154 { 155 struct i2c_client *c = v4l2_get_subdevdata(sd); 156 unsigned char buffer[3]; 157 int rc; 158 159 buffer[0] = addr; 160 buffer[1] = value >> 8; 161 buffer[2] = value & 0xff; 162 163 v4l2_dbg(2, debug, sd, 164 "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value); 165 rc = i2c_master_send(c, buffer, 3); 166 if (rc != 3) 167 v4l2_dbg(0, debug, sd, 168 "i2c i/o error: rc == %d (should be 3)\n", rc); 169 } 170 171 172 struct i2c_reg_value { 173 unsigned char reg; 174 u16 value; 175 }; 176 177 /* 178 * Values used at the original driver 179 * Some values are marked as Reserved at the datasheet 180 */ 181 static const struct i2c_reg_value mt9v011_init_default[] = { 182 { R0D_MT9V011_RESET, 0x0001 }, 183 { R0D_MT9V011_RESET, 0x0000 }, 184 185 { R0C_MT9V011_SHUTTER_DELAY, 0x0000 }, 186 { R09_MT9V011_SHUTTER_WIDTH, 0x1fc }, 187 188 { R0A_MT9V011_CLK_SPEED, 0x0000 }, 189 { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, 190 191 { R07_MT9V011_OUT_CTRL, 0x0002 }, /* chip enable */ 192 }; 193 194 195 static u16 calc_mt9v011_gain(s16 lineargain) 196 { 197 198 u16 digitalgain = 0; 199 u16 analogmult = 0; 200 u16 analoginit = 0; 201 202 if (lineargain < 0) 203 lineargain = 0; 204 205 /* recommended minimum */ 206 lineargain += 0x0020; 207 208 if (lineargain > 2047) 209 lineargain = 2047; 210 211 if (lineargain > 1023) { 212 digitalgain = 3; 213 analogmult = 3; 214 analoginit = lineargain / 16; 215 } else if (lineargain > 511) { 216 digitalgain = 1; 217 analogmult = 3; 218 analoginit = lineargain / 8; 219 } else if (lineargain > 255) { 220 analogmult = 3; 221 analoginit = lineargain / 4; 222 } else if (lineargain > 127) { 223 analogmult = 1; 224 analoginit = lineargain / 2; 225 } else 226 analoginit = lineargain; 227 228 return analoginit + (analogmult << 7) + (digitalgain << 9); 229 230 } 231 232 static void set_balance(struct v4l2_subdev *sd) 233 { 234 struct mt9v011 *core = to_mt9v011(sd); 235 u16 green_gain, blue_gain, red_gain; 236 u16 exposure; 237 s16 bal; 238 239 exposure = core->exposure; 240 241 green_gain = calc_mt9v011_gain(core->global_gain); 242 243 bal = core->global_gain; 244 bal += (core->blue_bal * core->global_gain / (1 << 7)); 245 blue_gain = calc_mt9v011_gain(bal); 246 247 bal = core->global_gain; 248 bal += (core->red_bal * core->global_gain / (1 << 7)); 249 red_gain = calc_mt9v011_gain(bal); 250 251 mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green_gain); 252 mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN, green_gain); 253 mt9v011_write(sd, R2C_MT9V011_BLUE_GAIN, blue_gain); 254 mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); 255 mt9v011_write(sd, R09_MT9V011_SHUTTER_WIDTH, exposure); 256 } 257 258 static void calc_fps(struct v4l2_subdev *sd, u32 *numerator, u32 *denominator) 259 { 260 struct mt9v011 *core = to_mt9v011(sd); 261 unsigned height, width, hblank, vblank, speed; 262 unsigned row_time, t_time; 263 u64 frames_per_ms; 264 unsigned tmp; 265 266 height = mt9v011_read(sd, R03_MT9V011_HEIGHT); 267 width = mt9v011_read(sd, R04_MT9V011_WIDTH); 268 hblank = mt9v011_read(sd, R05_MT9V011_HBLANK); 269 vblank = mt9v011_read(sd, R06_MT9V011_VBLANK); 270 speed = mt9v011_read(sd, R0A_MT9V011_CLK_SPEED); 271 272 row_time = (width + 113 + hblank) * (speed + 2); 273 t_time = row_time * (height + vblank + 1); 274 275 frames_per_ms = core->xtal * 1000l; 276 do_div(frames_per_ms, t_time); 277 tmp = frames_per_ms; 278 279 v4l2_dbg(1, debug, sd, "Programmed to %u.%03u fps (%d pixel clcks)\n", 280 tmp / 1000, tmp % 1000, t_time); 281 282 if (numerator && denominator) { 283 *numerator = 1000; 284 *denominator = (u32)frames_per_ms; 285 } 286 } 287 288 static u16 calc_speed(struct v4l2_subdev *sd, u32 numerator, u32 denominator) 289 { 290 struct mt9v011 *core = to_mt9v011(sd); 291 unsigned height, width, hblank, vblank; 292 unsigned row_time, line_time; 293 u64 t_time, speed; 294 295 /* Avoid bogus calculus */ 296 if (!numerator || !denominator) 297 return 0; 298 299 height = mt9v011_read(sd, R03_MT9V011_HEIGHT); 300 width = mt9v011_read(sd, R04_MT9V011_WIDTH); 301 hblank = mt9v011_read(sd, R05_MT9V011_HBLANK); 302 vblank = mt9v011_read(sd, R06_MT9V011_VBLANK); 303 304 row_time = width + 113 + hblank; 305 line_time = height + vblank + 1; 306 307 t_time = core->xtal * ((u64)numerator); 308 /* round to the closest value */ 309 t_time += denominator / 2; 310 do_div(t_time, denominator); 311 312 speed = t_time; 313 do_div(speed, row_time * line_time); 314 315 /* Avoid having a negative value for speed */ 316 if (speed < 2) 317 speed = 0; 318 else 319 speed -= 2; 320 321 /* Avoid speed overflow */ 322 if (speed > 15) 323 return 15; 324 325 return (u16)speed; 326 } 327 328 static void set_res(struct v4l2_subdev *sd) 329 { 330 struct mt9v011 *core = to_mt9v011(sd); 331 unsigned vstart, hstart; 332 333 /* 334 * The mt9v011 doesn't have scaling. So, in order to select the desired 335 * resolution, we're cropping at the middle of the sensor. 336 * hblank and vblank should be adjusted, in order to warrant that 337 * we'll preserve the line timings for 30 fps, no matter what resolution 338 * is selected. 339 * NOTE: datasheet says that width (and height) should be filled with 340 * width-1. However, this doesn't work, since one pixel per line will 341 * be missing. 342 */ 343 344 hstart = 20 + (640 - core->width) / 2; 345 mt9v011_write(sd, R02_MT9V011_COLSTART, hstart); 346 mt9v011_write(sd, R04_MT9V011_WIDTH, core->width); 347 mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width); 348 349 vstart = 8 + (480 - core->height) / 2; 350 mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart); 351 mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height); 352 mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height); 353 354 calc_fps(sd, NULL, NULL); 355 }; 356 357 static void set_read_mode(struct v4l2_subdev *sd) 358 { 359 struct mt9v011 *core = to_mt9v011(sd); 360 unsigned mode = 0x1000; 361 362 if (core->hflip) 363 mode |= 0x4000; 364 365 if (core->vflip) 366 mode |= 0x8000; 367 368 mt9v011_write(sd, R20_MT9V011_READ_MODE, mode); 369 } 370 371 static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) 372 { 373 int i; 374 375 for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++) 376 mt9v011_write(sd, mt9v011_init_default[i].reg, 377 mt9v011_init_default[i].value); 378 379 set_balance(sd); 380 set_res(sd); 381 set_read_mode(sd); 382 383 return 0; 384 }; 385 386 static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 387 { 388 struct mt9v011 *core = to_mt9v011(sd); 389 390 v4l2_dbg(1, debug, sd, "g_ctrl called\n"); 391 392 switch (ctrl->id) { 393 case V4L2_CID_GAIN: 394 ctrl->value = core->global_gain; 395 return 0; 396 case V4L2_CID_EXPOSURE: 397 ctrl->value = core->exposure; 398 return 0; 399 case V4L2_CID_RED_BALANCE: 400 ctrl->value = core->red_bal; 401 return 0; 402 case V4L2_CID_BLUE_BALANCE: 403 ctrl->value = core->blue_bal; 404 return 0; 405 case V4L2_CID_HFLIP: 406 ctrl->value = core->hflip ? 1 : 0; 407 return 0; 408 case V4L2_CID_VFLIP: 409 ctrl->value = core->vflip ? 1 : 0; 410 return 0; 411 } 412 return -EINVAL; 413 } 414 415 static int mt9v011_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) 416 { 417 int i; 418 419 v4l2_dbg(1, debug, sd, "queryctrl called\n"); 420 421 for (i = 0; i < ARRAY_SIZE(mt9v011_qctrl); i++) 422 if (qc->id && qc->id == mt9v011_qctrl[i].id) { 423 memcpy(qc, &(mt9v011_qctrl[i]), 424 sizeof(*qc)); 425 return 0; 426 } 427 428 return -EINVAL; 429 } 430 431 432 static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 433 { 434 struct mt9v011 *core = to_mt9v011(sd); 435 u8 i, n; 436 n = ARRAY_SIZE(mt9v011_qctrl); 437 438 for (i = 0; i < n; i++) { 439 if (ctrl->id != mt9v011_qctrl[i].id) 440 continue; 441 if (ctrl->value < mt9v011_qctrl[i].minimum || 442 ctrl->value > mt9v011_qctrl[i].maximum) 443 return -ERANGE; 444 v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n", 445 ctrl->id, ctrl->value); 446 break; 447 } 448 449 switch (ctrl->id) { 450 case V4L2_CID_GAIN: 451 core->global_gain = ctrl->value; 452 break; 453 case V4L2_CID_EXPOSURE: 454 core->exposure = ctrl->value; 455 break; 456 case V4L2_CID_RED_BALANCE: 457 core->red_bal = ctrl->value; 458 break; 459 case V4L2_CID_BLUE_BALANCE: 460 core->blue_bal = ctrl->value; 461 break; 462 case V4L2_CID_HFLIP: 463 core->hflip = ctrl->value; 464 set_read_mode(sd); 465 return 0; 466 case V4L2_CID_VFLIP: 467 core->vflip = ctrl->value; 468 set_read_mode(sd); 469 return 0; 470 default: 471 return -EINVAL; 472 } 473 474 set_balance(sd); 475 476 return 0; 477 } 478 479 static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, 480 enum v4l2_mbus_pixelcode *code) 481 { 482 if (index > 0) 483 return -EINVAL; 484 485 *code = V4L2_MBUS_FMT_SGRBG8_1X8; 486 return 0; 487 } 488 489 static int mt9v011_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) 490 { 491 if (fmt->code != V4L2_MBUS_FMT_SGRBG8_1X8) 492 return -EINVAL; 493 494 v4l_bound_align_image(&fmt->width, 48, 639, 1, 495 &fmt->height, 32, 480, 1, 0); 496 fmt->field = V4L2_FIELD_NONE; 497 fmt->colorspace = V4L2_COLORSPACE_SRGB; 498 499 return 0; 500 } 501 502 static int mt9v011_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) 503 { 504 struct v4l2_captureparm *cp = &parms->parm.capture; 505 506 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 507 return -EINVAL; 508 509 memset(cp, 0, sizeof(struct v4l2_captureparm)); 510 cp->capability = V4L2_CAP_TIMEPERFRAME; 511 calc_fps(sd, 512 &cp->timeperframe.numerator, 513 &cp->timeperframe.denominator); 514 515 return 0; 516 } 517 518 static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) 519 { 520 struct v4l2_captureparm *cp = &parms->parm.capture; 521 struct v4l2_fract *tpf = &cp->timeperframe; 522 u16 speed; 523 524 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 525 return -EINVAL; 526 if (cp->extendedmode != 0) 527 return -EINVAL; 528 529 speed = calc_speed(sd, tpf->numerator, tpf->denominator); 530 531 mt9v011_write(sd, R0A_MT9V011_CLK_SPEED, speed); 532 v4l2_dbg(1, debug, sd, "Setting speed to %d\n", speed); 533 534 /* Recalculate and update fps info */ 535 calc_fps(sd, &tpf->numerator, &tpf->denominator); 536 537 return 0; 538 } 539 540 static int mt9v011_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) 541 { 542 struct mt9v011 *core = to_mt9v011(sd); 543 int rc; 544 545 rc = mt9v011_try_mbus_fmt(sd, fmt); 546 if (rc < 0) 547 return -EINVAL; 548 549 core->width = fmt->width; 550 core->height = fmt->height; 551 552 set_res(sd); 553 554 return 0; 555 } 556 557 #ifdef CONFIG_VIDEO_ADV_DEBUG 558 static int mt9v011_g_register(struct v4l2_subdev *sd, 559 struct v4l2_dbg_register *reg) 560 { 561 struct i2c_client *client = v4l2_get_subdevdata(sd); 562 563 if (!v4l2_chip_match_i2c_client(client, ®->match)) 564 return -EINVAL; 565 if (!capable(CAP_SYS_ADMIN)) 566 return -EPERM; 567 568 reg->val = mt9v011_read(sd, reg->reg & 0xff); 569 reg->size = 2; 570 571 return 0; 572 } 573 574 static int mt9v011_s_register(struct v4l2_subdev *sd, 575 struct v4l2_dbg_register *reg) 576 { 577 struct i2c_client *client = v4l2_get_subdevdata(sd); 578 579 if (!v4l2_chip_match_i2c_client(client, ®->match)) 580 return -EINVAL; 581 if (!capable(CAP_SYS_ADMIN)) 582 return -EPERM; 583 584 mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff); 585 586 return 0; 587 } 588 #endif 589 590 static int mt9v011_g_chip_ident(struct v4l2_subdev *sd, 591 struct v4l2_dbg_chip_ident *chip) 592 { 593 u16 version; 594 struct i2c_client *client = v4l2_get_subdevdata(sd); 595 596 version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); 597 598 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011, 599 version); 600 } 601 602 static const struct v4l2_subdev_core_ops mt9v011_core_ops = { 603 .queryctrl = mt9v011_queryctrl, 604 .g_ctrl = mt9v011_g_ctrl, 605 .s_ctrl = mt9v011_s_ctrl, 606 .reset = mt9v011_reset, 607 .g_chip_ident = mt9v011_g_chip_ident, 608 #ifdef CONFIG_VIDEO_ADV_DEBUG 609 .g_register = mt9v011_g_register, 610 .s_register = mt9v011_s_register, 611 #endif 612 }; 613 614 static const struct v4l2_subdev_video_ops mt9v011_video_ops = { 615 .enum_mbus_fmt = mt9v011_enum_mbus_fmt, 616 .try_mbus_fmt = mt9v011_try_mbus_fmt, 617 .s_mbus_fmt = mt9v011_s_mbus_fmt, 618 .g_parm = mt9v011_g_parm, 619 .s_parm = mt9v011_s_parm, 620 }; 621 622 static const struct v4l2_subdev_ops mt9v011_ops = { 623 .core = &mt9v011_core_ops, 624 .video = &mt9v011_video_ops, 625 }; 626 627 628 /**************************************************************************** 629 I2C Client & Driver 630 ****************************************************************************/ 631 632 static int mt9v011_probe(struct i2c_client *c, 633 const struct i2c_device_id *id) 634 { 635 u16 version; 636 struct mt9v011 *core; 637 struct v4l2_subdev *sd; 638 639 /* Check if the adapter supports the needed features */ 640 if (!i2c_check_functionality(c->adapter, 641 I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) 642 return -EIO; 643 644 core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL); 645 if (!core) 646 return -ENOMEM; 647 648 sd = &core->sd; 649 v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); 650 651 /* Check if the sensor is really a MT9V011 */ 652 version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); 653 if ((version != MT9V011_VERSION) && 654 (version != MT9V011_REV_B_VERSION)) { 655 v4l2_info(sd, "*** unknown micron chip detected (0x%04x).\n", 656 version); 657 kfree(core); 658 return -EINVAL; 659 } 660 661 core->global_gain = 0x0024; 662 core->exposure = 0x01fc; 663 core->width = 640; 664 core->height = 480; 665 core->xtal = 27000000; /* Hz */ 666 667 if (c->dev.platform_data) { 668 struct mt9v011_platform_data *pdata = c->dev.platform_data; 669 670 core->xtal = pdata->xtal; 671 v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n", 672 core->xtal / 1000000, (core->xtal / 1000) % 1000); 673 } 674 675 v4l_info(c, "chip found @ 0x%02x (%s - chip version 0x%04x)\n", 676 c->addr << 1, c->adapter->name, version); 677 678 return 0; 679 } 680 681 static int mt9v011_remove(struct i2c_client *c) 682 { 683 struct v4l2_subdev *sd = i2c_get_clientdata(c); 684 685 v4l2_dbg(1, debug, sd, 686 "mt9v011.c: removing mt9v011 adapter on address 0x%x\n", 687 c->addr << 1); 688 689 v4l2_device_unregister_subdev(sd); 690 kfree(to_mt9v011(sd)); 691 return 0; 692 } 693 694 /* ----------------------------------------------------------------------- */ 695 696 static const struct i2c_device_id mt9v011_id[] = { 697 { "mt9v011", 0 }, 698 { } 699 }; 700 MODULE_DEVICE_TABLE(i2c, mt9v011_id); 701 702 static struct i2c_driver mt9v011_driver = { 703 .driver = { 704 .owner = THIS_MODULE, 705 .name = "mt9v011", 706 }, 707 .probe = mt9v011_probe, 708 .remove = mt9v011_remove, 709 .id_table = mt9v011_id, 710 }; 711 712 module_i2c_driver(mt9v011_driver); 713