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