1 /* 2 * Driver for the po1030 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_po1030.h" 22 23 static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); 24 static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); 25 static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val); 26 static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val); 27 static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); 28 static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); 29 static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); 30 static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); 31 static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val); 32 static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val); 33 static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); 34 static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val); 35 static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); 36 static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val); 37 static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, 38 __s32 val); 39 static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, 40 __s32 *val); 41 static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev, 42 __s32 val); 43 static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev, 44 __s32 *val); 45 46 static struct v4l2_pix_format po1030_modes[] = { 47 { 48 640, 49 480, 50 V4L2_PIX_FMT_SBGGR8, 51 V4L2_FIELD_NONE, 52 .sizeimage = 640 * 480, 53 .bytesperline = 640, 54 .colorspace = V4L2_COLORSPACE_SRGB, 55 .priv = 2 56 } 57 }; 58 59 static const struct ctrl po1030_ctrls[] = { 60 #define GAIN_IDX 0 61 { 62 { 63 .id = V4L2_CID_GAIN, 64 .type = V4L2_CTRL_TYPE_INTEGER, 65 .name = "gain", 66 .minimum = 0x00, 67 .maximum = 0x4f, 68 .step = 0x1, 69 .default_value = PO1030_GLOBAL_GAIN_DEFAULT, 70 .flags = V4L2_CTRL_FLAG_SLIDER 71 }, 72 .set = po1030_set_gain, 73 .get = po1030_get_gain 74 }, 75 #define EXPOSURE_IDX 1 76 { 77 { 78 .id = V4L2_CID_EXPOSURE, 79 .type = V4L2_CTRL_TYPE_INTEGER, 80 .name = "exposure", 81 .minimum = 0x00, 82 .maximum = 0x02ff, 83 .step = 0x1, 84 .default_value = PO1030_EXPOSURE_DEFAULT, 85 .flags = V4L2_CTRL_FLAG_SLIDER 86 }, 87 .set = po1030_set_exposure, 88 .get = po1030_get_exposure 89 }, 90 #define RED_BALANCE_IDX 2 91 { 92 { 93 .id = V4L2_CID_RED_BALANCE, 94 .type = V4L2_CTRL_TYPE_INTEGER, 95 .name = "red balance", 96 .minimum = 0x00, 97 .maximum = 0xff, 98 .step = 0x1, 99 .default_value = PO1030_RED_GAIN_DEFAULT, 100 .flags = V4L2_CTRL_FLAG_SLIDER 101 }, 102 .set = po1030_set_red_balance, 103 .get = po1030_get_red_balance 104 }, 105 #define BLUE_BALANCE_IDX 3 106 { 107 { 108 .id = V4L2_CID_BLUE_BALANCE, 109 .type = V4L2_CTRL_TYPE_INTEGER, 110 .name = "blue balance", 111 .minimum = 0x00, 112 .maximum = 0xff, 113 .step = 0x1, 114 .default_value = PO1030_BLUE_GAIN_DEFAULT, 115 .flags = V4L2_CTRL_FLAG_SLIDER 116 }, 117 .set = po1030_set_blue_balance, 118 .get = po1030_get_blue_balance 119 }, 120 #define HFLIP_IDX 4 121 { 122 { 123 .id = V4L2_CID_HFLIP, 124 .type = V4L2_CTRL_TYPE_BOOLEAN, 125 .name = "horizontal flip", 126 .minimum = 0, 127 .maximum = 1, 128 .step = 1, 129 .default_value = 0, 130 }, 131 .set = po1030_set_hflip, 132 .get = po1030_get_hflip 133 }, 134 #define VFLIP_IDX 5 135 { 136 { 137 .id = V4L2_CID_VFLIP, 138 .type = V4L2_CTRL_TYPE_BOOLEAN, 139 .name = "vertical flip", 140 .minimum = 0, 141 .maximum = 1, 142 .step = 1, 143 .default_value = 0, 144 }, 145 .set = po1030_set_vflip, 146 .get = po1030_get_vflip 147 }, 148 #define AUTO_WHITE_BALANCE_IDX 6 149 { 150 { 151 .id = V4L2_CID_AUTO_WHITE_BALANCE, 152 .type = V4L2_CTRL_TYPE_BOOLEAN, 153 .name = "auto white balance", 154 .minimum = 0, 155 .maximum = 1, 156 .step = 1, 157 .default_value = 0, 158 }, 159 .set = po1030_set_auto_white_balance, 160 .get = po1030_get_auto_white_balance 161 }, 162 #define AUTO_EXPOSURE_IDX 7 163 { 164 { 165 .id = V4L2_CID_EXPOSURE_AUTO, 166 .type = V4L2_CTRL_TYPE_BOOLEAN, 167 .name = "auto exposure", 168 .minimum = 0, 169 .maximum = 1, 170 .step = 1, 171 .default_value = 0, 172 }, 173 .set = po1030_set_auto_exposure, 174 .get = po1030_get_auto_exposure 175 }, 176 #define GREEN_BALANCE_IDX 8 177 { 178 { 179 .id = M5602_V4L2_CID_GREEN_BALANCE, 180 .type = V4L2_CTRL_TYPE_INTEGER, 181 .name = "green balance", 182 .minimum = 0x00, 183 .maximum = 0xff, 184 .step = 0x1, 185 .default_value = PO1030_GREEN_GAIN_DEFAULT, 186 .flags = V4L2_CTRL_FLAG_SLIDER 187 }, 188 .set = po1030_set_green_balance, 189 .get = po1030_get_green_balance 190 }, 191 }; 192 193 static void po1030_dump_registers(struct sd *sd); 194 195 int po1030_probe(struct sd *sd) 196 { 197 u8 dev_id_h = 0, i; 198 s32 *sensor_settings; 199 200 if (force_sensor) { 201 if (force_sensor == PO1030_SENSOR) { 202 pr_info("Forcing a %s sensor\n", po1030.name); 203 goto sensor_found; 204 } 205 /* If we want to force another sensor, don't try to probe this 206 * one */ 207 return -ENODEV; 208 } 209 210 PDEBUG(D_PROBE, "Probing for a po1030 sensor"); 211 212 /* Run the pre-init to actually probe the unit */ 213 for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) { 214 u8 data = preinit_po1030[i][2]; 215 if (preinit_po1030[i][0] == SENSOR) 216 m5602_write_sensor(sd, 217 preinit_po1030[i][1], &data, 1); 218 else 219 m5602_write_bridge(sd, preinit_po1030[i][1], data); 220 } 221 222 if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1)) 223 return -ENODEV; 224 225 if (dev_id_h == 0x30) { 226 pr_info("Detected a po1030 sensor\n"); 227 goto sensor_found; 228 } 229 return -ENODEV; 230 231 sensor_found: 232 sensor_settings = kmalloc( 233 ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL); 234 if (!sensor_settings) 235 return -ENOMEM; 236 237 sd->gspca_dev.cam.cam_mode = po1030_modes; 238 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes); 239 sd->desc->ctrls = po1030_ctrls; 240 sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls); 241 242 for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++) 243 sensor_settings[i] = po1030_ctrls[i].qctrl.default_value; 244 sd->sensor_priv = sensor_settings; 245 246 return 0; 247 } 248 249 int po1030_init(struct sd *sd) 250 { 251 s32 *sensor_settings = sd->sensor_priv; 252 int i, err = 0; 253 254 /* Init the sensor */ 255 for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) { 256 u8 data[2] = {0x00, 0x00}; 257 258 switch (init_po1030[i][0]) { 259 case BRIDGE: 260 err = m5602_write_bridge(sd, 261 init_po1030[i][1], 262 init_po1030[i][2]); 263 break; 264 265 case SENSOR: 266 data[0] = init_po1030[i][2]; 267 err = m5602_write_sensor(sd, 268 init_po1030[i][1], data, 1); 269 break; 270 271 default: 272 pr_info("Invalid stream command, exiting init\n"); 273 return -EINVAL; 274 } 275 } 276 if (err < 0) 277 return err; 278 279 if (dump_sensor) 280 po1030_dump_registers(sd); 281 282 err = po1030_set_exposure(&sd->gspca_dev, 283 sensor_settings[EXPOSURE_IDX]); 284 if (err < 0) 285 return err; 286 287 err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); 288 if (err < 0) 289 return err; 290 291 err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); 292 if (err < 0) 293 return err; 294 295 err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); 296 if (err < 0) 297 return err; 298 299 err = po1030_set_red_balance(&sd->gspca_dev, 300 sensor_settings[RED_BALANCE_IDX]); 301 if (err < 0) 302 return err; 303 304 err = po1030_set_blue_balance(&sd->gspca_dev, 305 sensor_settings[BLUE_BALANCE_IDX]); 306 if (err < 0) 307 return err; 308 309 err = po1030_set_green_balance(&sd->gspca_dev, 310 sensor_settings[GREEN_BALANCE_IDX]); 311 if (err < 0) 312 return err; 313 314 err = po1030_set_auto_white_balance(&sd->gspca_dev, 315 sensor_settings[AUTO_WHITE_BALANCE_IDX]); 316 if (err < 0) 317 return err; 318 319 err = po1030_set_auto_exposure(&sd->gspca_dev, 320 sensor_settings[AUTO_EXPOSURE_IDX]); 321 return err; 322 } 323 324 int po1030_start(struct sd *sd) 325 { 326 struct cam *cam = &sd->gspca_dev.cam; 327 int i, err = 0; 328 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width; 329 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; 330 int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv; 331 u8 data; 332 333 switch (width) { 334 case 320: 335 data = PO1030_SUBSAMPLING; 336 err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1); 337 if (err < 0) 338 return err; 339 340 data = ((width + 3) >> 8) & 0xff; 341 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1); 342 if (err < 0) 343 return err; 344 345 data = (width + 3) & 0xff; 346 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1); 347 if (err < 0) 348 return err; 349 350 data = ((height + 1) >> 8) & 0xff; 351 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1); 352 if (err < 0) 353 return err; 354 355 data = (height + 1) & 0xff; 356 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1); 357 358 height += 6; 359 width -= 1; 360 break; 361 362 case 640: 363 data = 0; 364 err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1); 365 if (err < 0) 366 return err; 367 368 data = ((width + 7) >> 8) & 0xff; 369 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1); 370 if (err < 0) 371 return err; 372 373 data = (width + 7) & 0xff; 374 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1); 375 if (err < 0) 376 return err; 377 378 data = ((height + 3) >> 8) & 0xff; 379 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1); 380 if (err < 0) 381 return err; 382 383 data = (height + 3) & 0xff; 384 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1); 385 386 height += 12; 387 width -= 2; 388 break; 389 } 390 err = m5602_write_bridge(sd, M5602_XB_SENSOR_TYPE, 0x0c); 391 if (err < 0) 392 return err; 393 394 err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81); 395 if (err < 0) 396 return err; 397 398 err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82); 399 if (err < 0) 400 return err; 401 402 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0x01); 403 if (err < 0) 404 return err; 405 406 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 407 ((ver_offs >> 8) & 0xff)); 408 if (err < 0) 409 return err; 410 411 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff)); 412 if (err < 0) 413 return err; 414 415 for (i = 0; i < 2 && !err; i++) 416 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); 417 if (err < 0) 418 return err; 419 420 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff); 421 if (err < 0) 422 return err; 423 424 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff)); 425 if (err < 0) 426 return err; 427 428 for (i = 0; i < 2 && !err; i++) 429 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); 430 431 for (i = 0; i < 2 && !err; i++) 432 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); 433 434 for (i = 0; i < 2 && !err; i++) 435 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0); 436 if (err < 0) 437 return err; 438 439 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff); 440 if (err < 0) 441 return err; 442 443 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff)); 444 if (err < 0) 445 return err; 446 447 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); 448 return err; 449 } 450 451 static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) 452 { 453 struct sd *sd = (struct sd *) gspca_dev; 454 s32 *sensor_settings = sd->sensor_priv; 455 456 *val = sensor_settings[EXPOSURE_IDX]; 457 PDEBUG(D_V4L2, "Exposure read as %d", *val); 458 return 0; 459 } 460 461 static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) 462 { 463 struct sd *sd = (struct sd *) gspca_dev; 464 s32 *sensor_settings = sd->sensor_priv; 465 u8 i2c_data; 466 int err; 467 468 sensor_settings[EXPOSURE_IDX] = val; 469 PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff); 470 471 i2c_data = ((val & 0xff00) >> 8); 472 PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x", 473 i2c_data); 474 475 err = m5602_write_sensor(sd, PO1030_INTEGLINES_H, 476 &i2c_data, 1); 477 if (err < 0) 478 return err; 479 480 i2c_data = (val & 0xff); 481 PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x", 482 i2c_data); 483 err = m5602_write_sensor(sd, PO1030_INTEGLINES_M, 484 &i2c_data, 1); 485 486 return err; 487 } 488 489 static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) 490 { 491 struct sd *sd = (struct sd *) gspca_dev; 492 s32 *sensor_settings = sd->sensor_priv; 493 494 *val = sensor_settings[GAIN_IDX]; 495 PDEBUG(D_V4L2, "Read global gain %d", *val); 496 return 0; 497 } 498 499 static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) 500 { 501 struct sd *sd = (struct sd *) gspca_dev; 502 s32 *sensor_settings = sd->sensor_priv; 503 u8 i2c_data; 504 int err; 505 506 sensor_settings[GAIN_IDX] = val; 507 508 i2c_data = val & 0xff; 509 PDEBUG(D_V4L2, "Set global gain to %d", i2c_data); 510 err = m5602_write_sensor(sd, PO1030_GLOBALGAIN, 511 &i2c_data, 1); 512 return err; 513 } 514 515 static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) 516 { 517 struct sd *sd = (struct sd *) gspca_dev; 518 s32 *sensor_settings = sd->sensor_priv; 519 520 *val = sensor_settings[HFLIP_IDX]; 521 PDEBUG(D_V4L2, "Read hflip %d", *val); 522 523 return 0; 524 } 525 526 static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) 527 { 528 struct sd *sd = (struct sd *) gspca_dev; 529 s32 *sensor_settings = sd->sensor_priv; 530 u8 i2c_data; 531 int err; 532 533 sensor_settings[HFLIP_IDX] = val; 534 535 PDEBUG(D_V4L2, "Set hflip %d", val); 536 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1); 537 if (err < 0) 538 return err; 539 540 i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7); 541 542 err = m5602_write_sensor(sd, PO1030_CONTROL2, 543 &i2c_data, 1); 544 545 return err; 546 } 547 548 static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) 549 { 550 struct sd *sd = (struct sd *) gspca_dev; 551 s32 *sensor_settings = sd->sensor_priv; 552 553 *val = sensor_settings[VFLIP_IDX]; 554 PDEBUG(D_V4L2, "Read vflip %d", *val); 555 556 return 0; 557 } 558 559 static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) 560 { 561 struct sd *sd = (struct sd *) gspca_dev; 562 s32 *sensor_settings = sd->sensor_priv; 563 u8 i2c_data; 564 int err; 565 566 sensor_settings[VFLIP_IDX] = val; 567 568 PDEBUG(D_V4L2, "Set vflip %d", val); 569 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1); 570 if (err < 0) 571 return err; 572 573 i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6); 574 575 err = m5602_write_sensor(sd, PO1030_CONTROL2, 576 &i2c_data, 1); 577 578 return err; 579 } 580 581 static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) 582 { 583 struct sd *sd = (struct sd *) gspca_dev; 584 s32 *sensor_settings = sd->sensor_priv; 585 586 *val = sensor_settings[RED_BALANCE_IDX]; 587 PDEBUG(D_V4L2, "Read red gain %d", *val); 588 return 0; 589 } 590 591 static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) 592 { 593 struct sd *sd = (struct sd *) gspca_dev; 594 s32 *sensor_settings = sd->sensor_priv; 595 u8 i2c_data; 596 int err; 597 598 sensor_settings[RED_BALANCE_IDX] = val; 599 600 i2c_data = val & 0xff; 601 PDEBUG(D_V4L2, "Set red gain to %d", i2c_data); 602 err = m5602_write_sensor(sd, PO1030_RED_GAIN, 603 &i2c_data, 1); 604 return err; 605 } 606 607 static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) 608 { 609 struct sd *sd = (struct sd *) gspca_dev; 610 s32 *sensor_settings = sd->sensor_priv; 611 612 *val = sensor_settings[BLUE_BALANCE_IDX]; 613 PDEBUG(D_V4L2, "Read blue gain %d", *val); 614 615 return 0; 616 } 617 618 static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) 619 { 620 struct sd *sd = (struct sd *) gspca_dev; 621 s32 *sensor_settings = sd->sensor_priv; 622 u8 i2c_data; 623 int err; 624 625 sensor_settings[BLUE_BALANCE_IDX] = val; 626 627 i2c_data = val & 0xff; 628 PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data); 629 err = m5602_write_sensor(sd, PO1030_BLUE_GAIN, 630 &i2c_data, 1); 631 632 return err; 633 } 634 635 static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val) 636 { 637 struct sd *sd = (struct sd *) gspca_dev; 638 s32 *sensor_settings = sd->sensor_priv; 639 640 *val = sensor_settings[GREEN_BALANCE_IDX]; 641 PDEBUG(D_V4L2, "Read green gain %d", *val); 642 643 return 0; 644 } 645 646 static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val) 647 { 648 struct sd *sd = (struct sd *) gspca_dev; 649 s32 *sensor_settings = sd->sensor_priv; 650 u8 i2c_data; 651 int err; 652 653 sensor_settings[GREEN_BALANCE_IDX] = val; 654 i2c_data = val & 0xff; 655 PDEBUG(D_V4L2, "Set green gain to %d", i2c_data); 656 657 err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN, 658 &i2c_data, 1); 659 if (err < 0) 660 return err; 661 662 return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN, 663 &i2c_data, 1); 664 } 665 666 static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, 667 __s32 *val) 668 { 669 struct sd *sd = (struct sd *) gspca_dev; 670 s32 *sensor_settings = sd->sensor_priv; 671 672 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX]; 673 PDEBUG(D_V4L2, "Auto white balancing is %d", *val); 674 675 return 0; 676 } 677 678 static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, 679 __s32 val) 680 { 681 struct sd *sd = (struct sd *) gspca_dev; 682 s32 *sensor_settings = sd->sensor_priv; 683 u8 i2c_data; 684 int err; 685 686 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val; 687 688 err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); 689 if (err < 0) 690 return err; 691 692 PDEBUG(D_V4L2, "Set auto white balance to %d", val); 693 i2c_data = (i2c_data & 0xfe) | (val & 0x01); 694 err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); 695 return err; 696 } 697 698 static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev, 699 __s32 *val) 700 { 701 struct sd *sd = (struct sd *) gspca_dev; 702 s32 *sensor_settings = sd->sensor_priv; 703 704 *val = sensor_settings[AUTO_EXPOSURE_IDX]; 705 PDEBUG(D_V4L2, "Auto exposure is %d", *val); 706 return 0; 707 } 708 709 static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev, 710 __s32 val) 711 { 712 struct sd *sd = (struct sd *) gspca_dev; 713 s32 *sensor_settings = sd->sensor_priv; 714 u8 i2c_data; 715 int err; 716 717 sensor_settings[AUTO_EXPOSURE_IDX] = val; 718 err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); 719 if (err < 0) 720 return err; 721 722 PDEBUG(D_V4L2, "Set auto exposure to %d", val); 723 i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1); 724 return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); 725 } 726 727 void po1030_disconnect(struct sd *sd) 728 { 729 sd->sensor = NULL; 730 kfree(sd->sensor_priv); 731 } 732 733 static void po1030_dump_registers(struct sd *sd) 734 { 735 int address; 736 u8 value = 0; 737 738 pr_info("Dumping the po1030 sensor core registers\n"); 739 for (address = 0; address < 0x7f; address++) { 740 m5602_read_sensor(sd, address, &value, 1); 741 pr_info("register 0x%x contains 0x%x\n", address, value); 742 } 743 744 pr_info("po1030 register state dump complete\n"); 745 746 pr_info("Probing for which registers that are read/write\n"); 747 for (address = 0; address < 0xff; address++) { 748 u8 old_value, ctrl_value; 749 u8 test_value[2] = {0xff, 0xff}; 750 751 m5602_read_sensor(sd, address, &old_value, 1); 752 m5602_write_sensor(sd, address, test_value, 1); 753 m5602_read_sensor(sd, address, &ctrl_value, 1); 754 755 if (ctrl_value == test_value[0]) 756 pr_info("register 0x%x is writeable\n", address); 757 else 758 pr_info("register 0x%x is read only\n", address); 759 760 /* Restore original value */ 761 m5602_write_sensor(sd, address, &old_value, 1); 762 } 763 } 764