1 /* 2 * Driver for the s5k4aa 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_s5k4aa.h" 22 23 static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); 24 static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); 25 static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); 26 static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val); 27 static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); 28 static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); 29 static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); 30 static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); 31 static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val); 32 static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val); 33 static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); 34 static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val); 35 36 static 37 const 38 struct dmi_system_id s5k4aa_vflip_dmi_table[] = { 39 { 40 .ident = "BRUNEINIT", 41 .matches = { 42 DMI_MATCH(DMI_SYS_VENDOR, "BRUNENIT"), 43 DMI_MATCH(DMI_PRODUCT_NAME, "BRUNENIT"), 44 DMI_MATCH(DMI_BOARD_VERSION, "00030D0000000001") 45 } 46 }, { 47 .ident = "Fujitsu-Siemens Amilo Xa 2528", 48 .matches = { 49 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 50 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528") 51 } 52 }, { 53 .ident = "Fujitsu-Siemens Amilo Xi 2428", 54 .matches = { 55 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 56 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428") 57 } 58 }, { 59 .ident = "Fujitsu-Siemens Amilo Xi 2528", 60 .matches = { 61 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 62 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2528") 63 } 64 }, { 65 .ident = "Fujitsu-Siemens Amilo Xi 2550", 66 .matches = { 67 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 68 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550") 69 } 70 }, { 71 .ident = "Fujitsu-Siemens Amilo Pa 2548", 72 .matches = { 73 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 74 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548") 75 } 76 }, { 77 .ident = "MSI GX700", 78 .matches = { 79 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), 80 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), 81 DMI_MATCH(DMI_BIOS_DATE, "12/02/2008") 82 } 83 }, { 84 .ident = "MSI GX700", 85 .matches = { 86 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), 87 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), 88 DMI_MATCH(DMI_BIOS_DATE, "07/26/2007") 89 } 90 }, { 91 .ident = "MSI GX700", 92 .matches = { 93 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), 94 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), 95 DMI_MATCH(DMI_BIOS_DATE, "07/19/2007") 96 } 97 }, { 98 .ident = "MSI GX700/GX705/EX700", 99 .matches = { 100 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), 101 DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700") 102 } 103 }, { 104 .ident = "MSI L735", 105 .matches = { 106 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), 107 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X") 108 } 109 }, { 110 .ident = "Lenovo Y300", 111 .matches = { 112 DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"), 113 DMI_MATCH(DMI_PRODUCT_NAME, "Y300") 114 } 115 }, 116 { } 117 }; 118 119 static struct v4l2_pix_format s5k4aa_modes[] = { 120 { 121 640, 122 480, 123 V4L2_PIX_FMT_SBGGR8, 124 V4L2_FIELD_NONE, 125 .sizeimage = 126 640 * 480, 127 .bytesperline = 640, 128 .colorspace = V4L2_COLORSPACE_SRGB, 129 .priv = 0 130 }, 131 { 132 1280, 133 1024, 134 V4L2_PIX_FMT_SBGGR8, 135 V4L2_FIELD_NONE, 136 .sizeimage = 137 1280 * 1024, 138 .bytesperline = 1280, 139 .colorspace = V4L2_COLORSPACE_SRGB, 140 .priv = 0 141 } 142 }; 143 144 static const struct ctrl s5k4aa_ctrls[] = { 145 #define VFLIP_IDX 0 146 { 147 { 148 .id = V4L2_CID_VFLIP, 149 .type = V4L2_CTRL_TYPE_BOOLEAN, 150 .name = "vertical flip", 151 .minimum = 0, 152 .maximum = 1, 153 .step = 1, 154 .default_value = 0 155 }, 156 .set = s5k4aa_set_vflip, 157 .get = s5k4aa_get_vflip 158 }, 159 #define HFLIP_IDX 1 160 { 161 { 162 .id = V4L2_CID_HFLIP, 163 .type = V4L2_CTRL_TYPE_BOOLEAN, 164 .name = "horizontal flip", 165 .minimum = 0, 166 .maximum = 1, 167 .step = 1, 168 .default_value = 0 169 }, 170 .set = s5k4aa_set_hflip, 171 .get = s5k4aa_get_hflip 172 }, 173 #define GAIN_IDX 2 174 { 175 { 176 .id = V4L2_CID_GAIN, 177 .type = V4L2_CTRL_TYPE_INTEGER, 178 .name = "Gain", 179 .minimum = 0, 180 .maximum = 127, 181 .step = 1, 182 .default_value = S5K4AA_DEFAULT_GAIN, 183 .flags = V4L2_CTRL_FLAG_SLIDER 184 }, 185 .set = s5k4aa_set_gain, 186 .get = s5k4aa_get_gain 187 }, 188 #define EXPOSURE_IDX 3 189 { 190 { 191 .id = V4L2_CID_EXPOSURE, 192 .type = V4L2_CTRL_TYPE_INTEGER, 193 .name = "Exposure", 194 .minimum = 13, 195 .maximum = 0xfff, 196 .step = 1, 197 .default_value = 0x100, 198 .flags = V4L2_CTRL_FLAG_SLIDER 199 }, 200 .set = s5k4aa_set_exposure, 201 .get = s5k4aa_get_exposure 202 }, 203 #define NOISE_SUPP_IDX 4 204 { 205 { 206 .id = V4L2_CID_PRIVATE_BASE, 207 .type = V4L2_CTRL_TYPE_BOOLEAN, 208 .name = "Noise suppression (smoothing)", 209 .minimum = 0, 210 .maximum = 1, 211 .step = 1, 212 .default_value = 1, 213 }, 214 .set = s5k4aa_set_noise, 215 .get = s5k4aa_get_noise 216 }, 217 #define BRIGHTNESS_IDX 5 218 { 219 { 220 .id = V4L2_CID_BRIGHTNESS, 221 .type = V4L2_CTRL_TYPE_INTEGER, 222 .name = "Brightness", 223 .minimum = 0, 224 .maximum = 0x1f, 225 .step = 1, 226 .default_value = S5K4AA_DEFAULT_BRIGHTNESS, 227 }, 228 .set = s5k4aa_set_brightness, 229 .get = s5k4aa_get_brightness 230 }, 231 232 }; 233 234 static void s5k4aa_dump_registers(struct sd *sd); 235 236 int s5k4aa_probe(struct sd *sd) 237 { 238 u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 239 const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75}; 240 int i, err = 0; 241 s32 *sensor_settings; 242 243 if (force_sensor) { 244 if (force_sensor == S5K4AA_SENSOR) { 245 pr_info("Forcing a %s sensor\n", s5k4aa.name); 246 goto sensor_found; 247 } 248 /* If we want to force another sensor, don't try to probe this 249 * one */ 250 return -ENODEV; 251 } 252 253 PDEBUG(D_PROBE, "Probing for a s5k4aa sensor"); 254 255 /* Preinit the sensor */ 256 for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) { 257 u8 data[2] = {0x00, 0x00}; 258 259 switch (preinit_s5k4aa[i][0]) { 260 case BRIDGE: 261 err = m5602_write_bridge(sd, 262 preinit_s5k4aa[i][1], 263 preinit_s5k4aa[i][2]); 264 break; 265 266 case SENSOR: 267 data[0] = preinit_s5k4aa[i][2]; 268 err = m5602_write_sensor(sd, 269 preinit_s5k4aa[i][1], 270 data, 1); 271 break; 272 273 case SENSOR_LONG: 274 data[0] = preinit_s5k4aa[i][2]; 275 data[1] = preinit_s5k4aa[i][3]; 276 err = m5602_write_sensor(sd, 277 preinit_s5k4aa[i][1], 278 data, 2); 279 break; 280 default: 281 pr_info("Invalid stream command, exiting init\n"); 282 return -EINVAL; 283 } 284 } 285 286 /* Test some registers, but we don't know their exact meaning yet */ 287 if (m5602_read_sensor(sd, 0x00, prod_id, 2)) 288 return -ENODEV; 289 if (m5602_read_sensor(sd, 0x02, prod_id+2, 2)) 290 return -ENODEV; 291 if (m5602_read_sensor(sd, 0x04, prod_id+4, 2)) 292 return -ENODEV; 293 294 if (memcmp(prod_id, expected_prod_id, sizeof(prod_id))) 295 return -ENODEV; 296 else 297 pr_info("Detected a s5k4aa sensor\n"); 298 299 sensor_found: 300 sensor_settings = kmalloc( 301 ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL); 302 if (!sensor_settings) 303 return -ENOMEM; 304 305 sd->gspca_dev.cam.cam_mode = s5k4aa_modes; 306 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes); 307 sd->desc->ctrls = s5k4aa_ctrls; 308 sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls); 309 310 for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++) 311 sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value; 312 sd->sensor_priv = sensor_settings; 313 314 return 0; 315 } 316 317 int s5k4aa_start(struct sd *sd) 318 { 319 int i, err = 0; 320 u8 data[2]; 321 struct cam *cam = &sd->gspca_dev.cam; 322 s32 *sensor_settings = sd->sensor_priv; 323 324 switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) { 325 case 1280: 326 PDEBUG(D_V4L2, "Configuring camera for SXGA mode"); 327 328 for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) { 329 switch (SXGA_s5k4aa[i][0]) { 330 case BRIDGE: 331 err = m5602_write_bridge(sd, 332 SXGA_s5k4aa[i][1], 333 SXGA_s5k4aa[i][2]); 334 break; 335 336 case SENSOR: 337 data[0] = SXGA_s5k4aa[i][2]; 338 err = m5602_write_sensor(sd, 339 SXGA_s5k4aa[i][1], 340 data, 1); 341 break; 342 343 case SENSOR_LONG: 344 data[0] = SXGA_s5k4aa[i][2]; 345 data[1] = SXGA_s5k4aa[i][3]; 346 err = m5602_write_sensor(sd, 347 SXGA_s5k4aa[i][1], 348 data, 2); 349 break; 350 351 default: 352 pr_err("Invalid stream command, exiting init\n"); 353 return -EINVAL; 354 } 355 } 356 err = s5k4aa_set_noise(&sd->gspca_dev, 0); 357 if (err < 0) 358 return err; 359 break; 360 361 case 640: 362 PDEBUG(D_V4L2, "Configuring camera for VGA mode"); 363 364 for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) { 365 switch (VGA_s5k4aa[i][0]) { 366 case BRIDGE: 367 err = m5602_write_bridge(sd, 368 VGA_s5k4aa[i][1], 369 VGA_s5k4aa[i][2]); 370 break; 371 372 case SENSOR: 373 data[0] = VGA_s5k4aa[i][2]; 374 err = m5602_write_sensor(sd, 375 VGA_s5k4aa[i][1], 376 data, 1); 377 break; 378 379 case SENSOR_LONG: 380 data[0] = VGA_s5k4aa[i][2]; 381 data[1] = VGA_s5k4aa[i][3]; 382 err = m5602_write_sensor(sd, 383 VGA_s5k4aa[i][1], 384 data, 2); 385 break; 386 387 default: 388 pr_err("Invalid stream command, exiting init\n"); 389 return -EINVAL; 390 } 391 } 392 err = s5k4aa_set_noise(&sd->gspca_dev, 1); 393 if (err < 0) 394 return err; 395 break; 396 } 397 if (err < 0) 398 return err; 399 400 err = s5k4aa_set_exposure(&sd->gspca_dev, 401 sensor_settings[EXPOSURE_IDX]); 402 if (err < 0) 403 return err; 404 405 err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); 406 if (err < 0) 407 return err; 408 409 err = s5k4aa_set_brightness(&sd->gspca_dev, 410 sensor_settings[BRIGHTNESS_IDX]); 411 if (err < 0) 412 return err; 413 414 err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]); 415 if (err < 0) 416 return err; 417 418 err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); 419 if (err < 0) 420 return err; 421 422 return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); 423 } 424 425 int s5k4aa_init(struct sd *sd) 426 { 427 int i, err = 0; 428 429 for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) { 430 u8 data[2] = {0x00, 0x00}; 431 432 switch (init_s5k4aa[i][0]) { 433 case BRIDGE: 434 err = m5602_write_bridge(sd, 435 init_s5k4aa[i][1], 436 init_s5k4aa[i][2]); 437 break; 438 439 case SENSOR: 440 data[0] = init_s5k4aa[i][2]; 441 err = m5602_write_sensor(sd, 442 init_s5k4aa[i][1], data, 1); 443 break; 444 445 case SENSOR_LONG: 446 data[0] = init_s5k4aa[i][2]; 447 data[1] = init_s5k4aa[i][3]; 448 err = m5602_write_sensor(sd, 449 init_s5k4aa[i][1], data, 2); 450 break; 451 default: 452 pr_info("Invalid stream command, exiting init\n"); 453 return -EINVAL; 454 } 455 } 456 457 if (dump_sensor) 458 s5k4aa_dump_registers(sd); 459 460 return err; 461 } 462 463 static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) 464 { 465 struct sd *sd = (struct sd *) gspca_dev; 466 s32 *sensor_settings = sd->sensor_priv; 467 468 *val = sensor_settings[EXPOSURE_IDX]; 469 PDEBUG(D_V4L2, "Read exposure %d", *val); 470 471 return 0; 472 } 473 474 static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) 475 { 476 struct sd *sd = (struct sd *) gspca_dev; 477 s32 *sensor_settings = sd->sensor_priv; 478 u8 data = S5K4AA_PAGE_MAP_2; 479 int err; 480 481 sensor_settings[EXPOSURE_IDX] = val; 482 PDEBUG(D_V4L2, "Set exposure to %d", val); 483 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 484 if (err < 0) 485 return err; 486 data = (val >> 8) & 0xff; 487 err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); 488 if (err < 0) 489 return err; 490 data = val & 0xff; 491 err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); 492 493 return err; 494 } 495 496 static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) 497 { 498 struct sd *sd = (struct sd *) gspca_dev; 499 s32 *sensor_settings = sd->sensor_priv; 500 501 *val = sensor_settings[VFLIP_IDX]; 502 PDEBUG(D_V4L2, "Read vertical flip %d", *val); 503 504 return 0; 505 } 506 507 static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) 508 { 509 struct sd *sd = (struct sd *) gspca_dev; 510 s32 *sensor_settings = sd->sensor_priv; 511 u8 data = S5K4AA_PAGE_MAP_2; 512 int err; 513 514 sensor_settings[VFLIP_IDX] = val; 515 516 PDEBUG(D_V4L2, "Set vertical flip to %d", val); 517 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 518 if (err < 0) 519 return err; 520 521 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); 522 if (err < 0) 523 return err; 524 525 if (dmi_check_system(s5k4aa_vflip_dmi_table)) 526 val = !val; 527 528 data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7)); 529 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); 530 if (err < 0) 531 return err; 532 533 err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); 534 if (err < 0) 535 return err; 536 if (val) 537 data &= 0xfe; 538 else 539 data |= 0x01; 540 err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); 541 return err; 542 } 543 544 static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) 545 { 546 struct sd *sd = (struct sd *) gspca_dev; 547 s32 *sensor_settings = sd->sensor_priv; 548 549 *val = sensor_settings[HFLIP_IDX]; 550 PDEBUG(D_V4L2, "Read horizontal flip %d", *val); 551 552 return 0; 553 } 554 555 static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) 556 { 557 struct sd *sd = (struct sd *) gspca_dev; 558 s32 *sensor_settings = sd->sensor_priv; 559 u8 data = S5K4AA_PAGE_MAP_2; 560 int err; 561 562 sensor_settings[HFLIP_IDX] = val; 563 564 PDEBUG(D_V4L2, "Set horizontal flip to %d", val); 565 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 566 if (err < 0) 567 return err; 568 569 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); 570 if (err < 0) 571 return err; 572 573 if (dmi_check_system(s5k4aa_vflip_dmi_table)) 574 val = !val; 575 576 data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6)); 577 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); 578 if (err < 0) 579 return err; 580 581 err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); 582 if (err < 0) 583 return err; 584 if (val) 585 data &= 0xfe; 586 else 587 data |= 0x01; 588 err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); 589 return err; 590 } 591 592 static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) 593 { 594 struct sd *sd = (struct sd *) gspca_dev; 595 s32 *sensor_settings = sd->sensor_priv; 596 597 *val = sensor_settings[GAIN_IDX]; 598 PDEBUG(D_V4L2, "Read gain %d", *val); 599 return 0; 600 } 601 602 static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) 603 { 604 struct sd *sd = (struct sd *) gspca_dev; 605 s32 *sensor_settings = sd->sensor_priv; 606 u8 data = S5K4AA_PAGE_MAP_2; 607 int err; 608 609 sensor_settings[GAIN_IDX] = val; 610 611 PDEBUG(D_V4L2, "Set gain to %d", val); 612 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 613 if (err < 0) 614 return err; 615 616 data = val & 0xff; 617 err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1); 618 619 return err; 620 } 621 622 static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) 623 { 624 struct sd *sd = (struct sd *) gspca_dev; 625 s32 *sensor_settings = sd->sensor_priv; 626 627 *val = sensor_settings[BRIGHTNESS_IDX]; 628 PDEBUG(D_V4L2, "Read brightness %d", *val); 629 return 0; 630 } 631 632 static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val) 633 { 634 struct sd *sd = (struct sd *) gspca_dev; 635 s32 *sensor_settings = sd->sensor_priv; 636 u8 data = S5K4AA_PAGE_MAP_2; 637 int err; 638 639 sensor_settings[BRIGHTNESS_IDX] = val; 640 641 PDEBUG(D_V4L2, "Set brightness to %d", val); 642 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 643 if (err < 0) 644 return err; 645 646 data = val & 0xff; 647 return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1); 648 } 649 650 static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val) 651 { 652 struct sd *sd = (struct sd *) gspca_dev; 653 s32 *sensor_settings = sd->sensor_priv; 654 655 *val = sensor_settings[NOISE_SUPP_IDX]; 656 PDEBUG(D_V4L2, "Read noise %d", *val); 657 return 0; 658 } 659 660 static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val) 661 { 662 struct sd *sd = (struct sd *) gspca_dev; 663 s32 *sensor_settings = sd->sensor_priv; 664 u8 data = S5K4AA_PAGE_MAP_2; 665 int err; 666 667 sensor_settings[NOISE_SUPP_IDX] = val; 668 669 PDEBUG(D_V4L2, "Set noise to %d", val); 670 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 671 if (err < 0) 672 return err; 673 674 data = val & 0x01; 675 return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1); 676 } 677 678 void s5k4aa_disconnect(struct sd *sd) 679 { 680 sd->sensor = NULL; 681 kfree(sd->sensor_priv); 682 } 683 684 static void s5k4aa_dump_registers(struct sd *sd) 685 { 686 int address; 687 u8 page, old_page; 688 m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); 689 for (page = 0; page < 16; page++) { 690 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); 691 pr_info("Dumping the s5k4aa register state for page 0x%x\n", 692 page); 693 for (address = 0; address <= 0xff; address++) { 694 u8 value = 0; 695 m5602_read_sensor(sd, address, &value, 1); 696 pr_info("register 0x%x contains 0x%x\n", 697 address, value); 698 } 699 } 700 pr_info("s5k4aa register state dump complete\n"); 701 702 for (page = 0; page < 16; page++) { 703 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); 704 pr_info("Probing for which registers that are read/write for page 0x%x\n", 705 page); 706 for (address = 0; address <= 0xff; address++) { 707 u8 old_value, ctrl_value, test_value = 0xff; 708 709 m5602_read_sensor(sd, address, &old_value, 1); 710 m5602_write_sensor(sd, address, &test_value, 1); 711 m5602_read_sensor(sd, address, &ctrl_value, 1); 712 713 if (ctrl_value == test_value) 714 pr_info("register 0x%x is writeable\n", 715 address); 716 else 717 pr_info("register 0x%x is read only\n", 718 address); 719 720 /* Restore original value */ 721 m5602_write_sensor(sd, address, &old_value, 1); 722 } 723 } 724 pr_info("Read/write register probing complete\n"); 725 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); 726 } 727