1 /* 2 * Driver for the mt9m111 sensor 3 * 4 * Copyright (C) 2008 Erik Andrén 5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. 6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> 7 * 8 * Portions of code to USB interface and ALi driver software, 9 * Copyright (c) 2006 Willem Duinker 10 * v4l2 interface modeled after the V4L2 driver 11 * for SN9C10x PC Camera Controllers 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License as 15 * published by the Free Software Foundation, version 2. 16 * 17 */ 18 19 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 20 21 #include "m5602_mt9m111.h" 22 23 static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); 24 static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); 25 static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); 26 static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); 27 static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); 28 static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); 29 static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, 30 __s32 val); 31 static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev, 32 __s32 *val); 33 static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val); 34 static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val); 35 static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); 36 static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); 37 static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); 38 static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); 39 40 static struct v4l2_pix_format mt9m111_modes[] = { 41 { 42 640, 43 480, 44 V4L2_PIX_FMT_SBGGR8, 45 V4L2_FIELD_NONE, 46 .sizeimage = 640 * 480, 47 .bytesperline = 640, 48 .colorspace = V4L2_COLORSPACE_SRGB, 49 .priv = 0 50 } 51 }; 52 53 static const struct ctrl mt9m111_ctrls[] = { 54 #define VFLIP_IDX 0 55 { 56 { 57 .id = V4L2_CID_VFLIP, 58 .type = V4L2_CTRL_TYPE_BOOLEAN, 59 .name = "vertical flip", 60 .minimum = 0, 61 .maximum = 1, 62 .step = 1, 63 .default_value = 0 64 }, 65 .set = mt9m111_set_vflip, 66 .get = mt9m111_get_vflip 67 }, 68 #define HFLIP_IDX 1 69 { 70 { 71 .id = V4L2_CID_HFLIP, 72 .type = V4L2_CTRL_TYPE_BOOLEAN, 73 .name = "horizontal flip", 74 .minimum = 0, 75 .maximum = 1, 76 .step = 1, 77 .default_value = 0 78 }, 79 .set = mt9m111_set_hflip, 80 .get = mt9m111_get_hflip 81 }, 82 #define GAIN_IDX 2 83 { 84 { 85 .id = V4L2_CID_GAIN, 86 .type = V4L2_CTRL_TYPE_INTEGER, 87 .name = "gain", 88 .minimum = 0, 89 .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, 90 .step = 1, 91 .default_value = MT9M111_DEFAULT_GAIN, 92 .flags = V4L2_CTRL_FLAG_SLIDER 93 }, 94 .set = mt9m111_set_gain, 95 .get = mt9m111_get_gain 96 }, 97 #define AUTO_WHITE_BALANCE_IDX 3 98 { 99 { 100 .id = V4L2_CID_AUTO_WHITE_BALANCE, 101 .type = V4L2_CTRL_TYPE_BOOLEAN, 102 .name = "auto white balance", 103 .minimum = 0, 104 .maximum = 1, 105 .step = 1, 106 .default_value = 0, 107 }, 108 .set = mt9m111_set_auto_white_balance, 109 .get = mt9m111_get_auto_white_balance 110 }, 111 #define GREEN_BALANCE_IDX 4 112 { 113 { 114 .id = M5602_V4L2_CID_GREEN_BALANCE, 115 .type = V4L2_CTRL_TYPE_INTEGER, 116 .name = "green balance", 117 .minimum = 0x00, 118 .maximum = 0x7ff, 119 .step = 0x1, 120 .default_value = MT9M111_GREEN_GAIN_DEFAULT, 121 .flags = V4L2_CTRL_FLAG_SLIDER 122 }, 123 .set = mt9m111_set_green_balance, 124 .get = mt9m111_get_green_balance 125 }, 126 #define BLUE_BALANCE_IDX 5 127 { 128 { 129 .id = V4L2_CID_BLUE_BALANCE, 130 .type = V4L2_CTRL_TYPE_INTEGER, 131 .name = "blue balance", 132 .minimum = 0x00, 133 .maximum = 0x7ff, 134 .step = 0x1, 135 .default_value = MT9M111_BLUE_GAIN_DEFAULT, 136 .flags = V4L2_CTRL_FLAG_SLIDER 137 }, 138 .set = mt9m111_set_blue_balance, 139 .get = mt9m111_get_blue_balance 140 }, 141 #define RED_BALANCE_IDX 5 142 { 143 { 144 .id = V4L2_CID_RED_BALANCE, 145 .type = V4L2_CTRL_TYPE_INTEGER, 146 .name = "red balance", 147 .minimum = 0x00, 148 .maximum = 0x7ff, 149 .step = 0x1, 150 .default_value = MT9M111_RED_GAIN_DEFAULT, 151 .flags = V4L2_CTRL_FLAG_SLIDER 152 }, 153 .set = mt9m111_set_red_balance, 154 .get = mt9m111_get_red_balance 155 }, 156 }; 157 158 static void mt9m111_dump_registers(struct sd *sd); 159 160 int mt9m111_probe(struct sd *sd) 161 { 162 u8 data[2] = {0x00, 0x00}; 163 int i; 164 s32 *sensor_settings; 165 166 if (force_sensor) { 167 if (force_sensor == MT9M111_SENSOR) { 168 pr_info("Forcing a %s sensor\n", mt9m111.name); 169 goto sensor_found; 170 } 171 /* If we want to force another sensor, don't try to probe this 172 * one */ 173 return -ENODEV; 174 } 175 176 PDEBUG(D_PROBE, "Probing for a mt9m111 sensor"); 177 178 /* Do the preinit */ 179 for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) { 180 if (preinit_mt9m111[i][0] == BRIDGE) { 181 m5602_write_bridge(sd, 182 preinit_mt9m111[i][1], 183 preinit_mt9m111[i][2]); 184 } else { 185 data[0] = preinit_mt9m111[i][2]; 186 data[1] = preinit_mt9m111[i][3]; 187 m5602_write_sensor(sd, 188 preinit_mt9m111[i][1], data, 2); 189 } 190 } 191 192 if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2)) 193 return -ENODEV; 194 195 if ((data[0] == 0x14) && (data[1] == 0x3a)) { 196 pr_info("Detected a mt9m111 sensor\n"); 197 goto sensor_found; 198 } 199 200 return -ENODEV; 201 202 sensor_found: 203 sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32), 204 GFP_KERNEL); 205 if (!sensor_settings) 206 return -ENOMEM; 207 208 sd->gspca_dev.cam.cam_mode = mt9m111_modes; 209 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes); 210 sd->desc->ctrls = mt9m111_ctrls; 211 sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls); 212 213 for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++) 214 sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value; 215 sd->sensor_priv = sensor_settings; 216 217 return 0; 218 } 219 220 int mt9m111_init(struct sd *sd) 221 { 222 int i, err = 0; 223 s32 *sensor_settings = sd->sensor_priv; 224 225 /* Init the sensor */ 226 for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) { 227 u8 data[2]; 228 229 if (init_mt9m111[i][0] == BRIDGE) { 230 err = m5602_write_bridge(sd, 231 init_mt9m111[i][1], 232 init_mt9m111[i][2]); 233 } else { 234 data[0] = init_mt9m111[i][2]; 235 data[1] = init_mt9m111[i][3]; 236 err = m5602_write_sensor(sd, 237 init_mt9m111[i][1], data, 2); 238 } 239 } 240 241 if (dump_sensor) 242 mt9m111_dump_registers(sd); 243 244 err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); 245 if (err < 0) 246 return err; 247 248 err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); 249 if (err < 0) 250 return err; 251 252 err = mt9m111_set_green_balance(&sd->gspca_dev, 253 sensor_settings[GREEN_BALANCE_IDX]); 254 if (err < 0) 255 return err; 256 257 err = mt9m111_set_blue_balance(&sd->gspca_dev, 258 sensor_settings[BLUE_BALANCE_IDX]); 259 if (err < 0) 260 return err; 261 262 err = mt9m111_set_red_balance(&sd->gspca_dev, 263 sensor_settings[RED_BALANCE_IDX]); 264 if (err < 0) 265 return err; 266 267 return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); 268 } 269 270 int mt9m111_start(struct sd *sd) 271 { 272 int i, err = 0; 273 u8 data[2]; 274 struct cam *cam = &sd->gspca_dev.cam; 275 s32 *sensor_settings = sd->sensor_priv; 276 277 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1; 278 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; 279 280 for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) { 281 if (start_mt9m111[i][0] == BRIDGE) { 282 err = m5602_write_bridge(sd, 283 start_mt9m111[i][1], 284 start_mt9m111[i][2]); 285 } else { 286 data[0] = start_mt9m111[i][2]; 287 data[1] = start_mt9m111[i][3]; 288 err = m5602_write_sensor(sd, 289 start_mt9m111[i][1], data, 2); 290 } 291 } 292 if (err < 0) 293 return err; 294 295 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff); 296 if (err < 0) 297 return err; 298 299 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff)); 300 if (err < 0) 301 return err; 302 303 for (i = 0; i < 2 && !err; i++) 304 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); 305 if (err < 0) 306 return err; 307 308 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); 309 if (err < 0) 310 return err; 311 312 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2); 313 if (err < 0) 314 return err; 315 316 for (i = 0; i < 2 && !err; i++) 317 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0); 318 if (err < 0) 319 return err; 320 321 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 322 (width >> 8) & 0xff); 323 if (err < 0) 324 return err; 325 326 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff); 327 if (err < 0) 328 return err; 329 330 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); 331 if (err < 0) 332 return err; 333 334 switch (width) { 335 case 640: 336 PDEBUG(D_V4L2, "Configuring camera for VGA mode"); 337 data[0] = MT9M111_RMB_OVER_SIZED; 338 data[1] = MT9M111_RMB_ROW_SKIP_2X | 339 MT9M111_RMB_COLUMN_SKIP_2X | 340 (sensor_settings[VFLIP_IDX] << 0) | 341 (sensor_settings[HFLIP_IDX] << 1); 342 343 err = m5602_write_sensor(sd, 344 MT9M111_SC_R_MODE_CONTEXT_B, data, 2); 345 break; 346 347 case 320: 348 PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); 349 data[0] = MT9M111_RMB_OVER_SIZED; 350 data[1] = MT9M111_RMB_ROW_SKIP_4X | 351 MT9M111_RMB_COLUMN_SKIP_4X | 352 (sensor_settings[VFLIP_IDX] << 0) | 353 (sensor_settings[HFLIP_IDX] << 1); 354 err = m5602_write_sensor(sd, 355 MT9M111_SC_R_MODE_CONTEXT_B, data, 2); 356 break; 357 } 358 return err; 359 } 360 361 void mt9m111_disconnect(struct sd *sd) 362 { 363 sd->sensor = NULL; 364 kfree(sd->sensor_priv); 365 } 366 367 static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) 368 { 369 struct sd *sd = (struct sd *) gspca_dev; 370 s32 *sensor_settings = sd->sensor_priv; 371 372 *val = sensor_settings[VFLIP_IDX]; 373 PDEBUG(D_V4L2, "Read vertical flip %d", *val); 374 375 return 0; 376 } 377 378 static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) 379 { 380 int err; 381 u8 data[2] = {0x00, 0x00}; 382 struct sd *sd = (struct sd *) gspca_dev; 383 s32 *sensor_settings = sd->sensor_priv; 384 385 PDEBUG(D_V4L2, "Set vertical flip to %d", val); 386 387 sensor_settings[VFLIP_IDX] = val; 388 389 /* The mt9m111 is flipped by default */ 390 val = !val; 391 392 /* Set the correct page map */ 393 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); 394 if (err < 0) 395 return err; 396 397 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); 398 if (err < 0) 399 return err; 400 401 data[1] = (data[1] & 0xfe) | val; 402 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, 403 data, 2); 404 return err; 405 } 406 407 static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) 408 { 409 struct sd *sd = (struct sd *) gspca_dev; 410 s32 *sensor_settings = sd->sensor_priv; 411 412 *val = sensor_settings[HFLIP_IDX]; 413 PDEBUG(D_V4L2, "Read horizontal flip %d", *val); 414 415 return 0; 416 } 417 418 static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) 419 { 420 int err; 421 u8 data[2] = {0x00, 0x00}; 422 struct sd *sd = (struct sd *) gspca_dev; 423 s32 *sensor_settings = sd->sensor_priv; 424 425 PDEBUG(D_V4L2, "Set horizontal flip to %d", val); 426 427 sensor_settings[HFLIP_IDX] = val; 428 429 /* The mt9m111 is flipped by default */ 430 val = !val; 431 432 /* Set the correct page map */ 433 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); 434 if (err < 0) 435 return err; 436 437 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); 438 if (err < 0) 439 return err; 440 441 data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02); 442 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, 443 data, 2); 444 return err; 445 } 446 447 static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) 448 { 449 struct sd *sd = (struct sd *) gspca_dev; 450 s32 *sensor_settings = sd->sensor_priv; 451 452 *val = sensor_settings[GAIN_IDX]; 453 PDEBUG(D_V4L2, "Read gain %d", *val); 454 455 return 0; 456 } 457 458 static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, 459 __s32 val) 460 { 461 struct sd *sd = (struct sd *) gspca_dev; 462 s32 *sensor_settings = sd->sensor_priv; 463 int err; 464 u8 data[2]; 465 466 err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2); 467 if (err < 0) 468 return err; 469 470 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01; 471 data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1)); 472 473 err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2); 474 475 PDEBUG(D_V4L2, "Set auto white balance %d", val); 476 return err; 477 } 478 479 static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev, 480 __s32 *val) { 481 struct sd *sd = (struct sd *) gspca_dev; 482 s32 *sensor_settings = sd->sensor_priv; 483 484 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX]; 485 PDEBUG(D_V4L2, "Read auto white balance %d", *val); 486 return 0; 487 } 488 489 static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) 490 { 491 int err, tmp; 492 u8 data[2] = {0x00, 0x00}; 493 struct sd *sd = (struct sd *) gspca_dev; 494 s32 *sensor_settings = sd->sensor_priv; 495 496 sensor_settings[GAIN_IDX] = val; 497 498 /* Set the correct page map */ 499 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); 500 if (err < 0) 501 return err; 502 503 if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2) 504 return -EINVAL; 505 506 if ((val >= INITIAL_MAX_GAIN * 2 * 2) && 507 (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2)) 508 tmp = (1 << 10) | (val << 9) | 509 (val << 8) | (val / 8); 510 else if ((val >= INITIAL_MAX_GAIN * 2) && 511 (val < INITIAL_MAX_GAIN * 2 * 2)) 512 tmp = (1 << 9) | (1 << 8) | (val / 4); 513 else if ((val >= INITIAL_MAX_GAIN) && 514 (val < INITIAL_MAX_GAIN * 2)) 515 tmp = (1 << 8) | (val / 2); 516 else 517 tmp = val; 518 519 data[1] = (tmp & 0xff); 520 data[0] = (tmp & 0xff00) >> 8; 521 PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp, 522 data[1], data[0]); 523 524 err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN, 525 data, 2); 526 527 return err; 528 } 529 530 static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val) 531 { 532 int err; 533 u8 data[2]; 534 struct sd *sd = (struct sd *) gspca_dev; 535 s32 *sensor_settings = sd->sensor_priv; 536 537 sensor_settings[GREEN_BALANCE_IDX] = val; 538 data[1] = (val & 0xff); 539 data[0] = (val & 0xff00) >> 8; 540 541 PDEBUG(D_V4L2, "Set green balance %d", val); 542 err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN, 543 data, 2); 544 if (err < 0) 545 return err; 546 547 return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN, 548 data, 2); 549 } 550 551 static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val) 552 { 553 struct sd *sd = (struct sd *) gspca_dev; 554 s32 *sensor_settings = sd->sensor_priv; 555 556 *val = sensor_settings[GREEN_BALANCE_IDX]; 557 PDEBUG(D_V4L2, "Read green balance %d", *val); 558 return 0; 559 } 560 561 static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) 562 { 563 u8 data[2]; 564 struct sd *sd = (struct sd *) gspca_dev; 565 s32 *sensor_settings = sd->sensor_priv; 566 567 sensor_settings[BLUE_BALANCE_IDX] = val; 568 data[1] = (val & 0xff); 569 data[0] = (val & 0xff00) >> 8; 570 571 PDEBUG(D_V4L2, "Set blue balance %d", val); 572 573 return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN, 574 data, 2); 575 } 576 577 static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) 578 { 579 struct sd *sd = (struct sd *) gspca_dev; 580 s32 *sensor_settings = sd->sensor_priv; 581 582 *val = sensor_settings[BLUE_BALANCE_IDX]; 583 PDEBUG(D_V4L2, "Read blue balance %d", *val); 584 return 0; 585 } 586 587 static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) 588 { 589 u8 data[2]; 590 struct sd *sd = (struct sd *) gspca_dev; 591 s32 *sensor_settings = sd->sensor_priv; 592 593 sensor_settings[RED_BALANCE_IDX] = val; 594 data[1] = (val & 0xff); 595 data[0] = (val & 0xff00) >> 8; 596 597 PDEBUG(D_V4L2, "Set red balance %d", val); 598 599 return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN, 600 data, 2); 601 } 602 603 static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) 604 { 605 struct sd *sd = (struct sd *) gspca_dev; 606 s32 *sensor_settings = sd->sensor_priv; 607 608 *val = sensor_settings[RED_BALANCE_IDX]; 609 PDEBUG(D_V4L2, "Read red balance %d", *val); 610 return 0; 611 } 612 613 static void mt9m111_dump_registers(struct sd *sd) 614 { 615 u8 address, value[2] = {0x00, 0x00}; 616 617 pr_info("Dumping the mt9m111 register state\n"); 618 619 pr_info("Dumping the mt9m111 sensor core registers\n"); 620 value[1] = MT9M111_SENSOR_CORE; 621 m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); 622 for (address = 0; address < 0xff; address++) { 623 m5602_read_sensor(sd, address, value, 2); 624 pr_info("register 0x%x contains 0x%x%x\n", 625 address, value[0], value[1]); 626 } 627 628 pr_info("Dumping the mt9m111 color pipeline registers\n"); 629 value[1] = MT9M111_COLORPIPE; 630 m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); 631 for (address = 0; address < 0xff; address++) { 632 m5602_read_sensor(sd, address, value, 2); 633 pr_info("register 0x%x contains 0x%x%x\n", 634 address, value[0], value[1]); 635 } 636 637 pr_info("Dumping the mt9m111 camera control registers\n"); 638 value[1] = MT9M111_CAMERA_CONTROL; 639 m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); 640 for (address = 0; address < 0xff; address++) { 641 m5602_read_sensor(sd, address, value, 2); 642 pr_info("register 0x%x contains 0x%x%x\n", 643 address, value[0], value[1]); 644 } 645 646 pr_info("mt9m111 register state dump complete\n"); 647 } 648