1/* 2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher 3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland 4 * Copyright (c) 2002, 2003 Tuukka Toivonen 5 * Copyright (c) 2008 Erik Andr��n 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 * P/N 861037: Sensor HDCS1000 ASIC STV0600 22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express 24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam 25 * P/N 861075-0040: Sensor HDCS1000 ASIC 26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB 27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web 28 */ 29 30/* 31 * The spec file for the PB-0100 suggests the following for best quality 32 * images after the sensor has been reset : 33 * 34 * PB_ADCGAINL = R60 = 0x03 (3 dec) : sets low reference of ADC 35 to produce good black level 36 * PB_PREADCTRL = R32 = 0x1400 (5120 dec) : Enables global gain changes 37 through R53 38 * PB_ADCMINGAIN = R52 = 0x10 (16 dec) : Sets the minimum gain for 39 auto-exposure 40 * PB_ADCGLOBALGAIN = R53 = 0x10 (16 dec) : Sets the global gain 41 * PB_EXPGAIN = R14 = 0x11 (17 dec) : Sets the auto-exposure value 42 * PB_UPDATEINT = R23 = 0x02 (2 dec) : Sets the speed on 43 auto-exposure routine 44 * PB_CFILLIN = R5 = 0x0E (14 dec) : Sets the frame rate 45 */ 46 47#include "stv06xx_pb0100.h" 48 49static const struct ctrl pb0100_ctrl[] = { 50#define GAIN_IDX 0 51 { 52 { 53 .id = V4L2_CID_GAIN, 54 .type = V4L2_CTRL_TYPE_INTEGER, 55 .name = "Gain", 56 .minimum = 0, 57 .maximum = 255, 58 .step = 1, 59 .default_value = 128 60 }, 61 .set = pb0100_set_gain, 62 .get = pb0100_get_gain 63 }, 64#define RED_BALANCE_IDX 1 65 { 66 { 67 .id = V4L2_CID_RED_BALANCE, 68 .type = V4L2_CTRL_TYPE_INTEGER, 69 .name = "Red Balance", 70 .minimum = -255, 71 .maximum = 255, 72 .step = 1, 73 .default_value = 0 74 }, 75 .set = pb0100_set_red_balance, 76 .get = pb0100_get_red_balance 77 }, 78#define BLUE_BALANCE_IDX 2 79 { 80 { 81 .id = V4L2_CID_BLUE_BALANCE, 82 .type = V4L2_CTRL_TYPE_INTEGER, 83 .name = "Blue Balance", 84 .minimum = -255, 85 .maximum = 255, 86 .step = 1, 87 .default_value = 0 88 }, 89 .set = pb0100_set_blue_balance, 90 .get = pb0100_get_blue_balance 91 }, 92#define EXPOSURE_IDX 3 93 { 94 { 95 .id = V4L2_CID_EXPOSURE, 96 .type = V4L2_CTRL_TYPE_INTEGER, 97 .name = "Exposure", 98 .minimum = 0, 99 .maximum = 511, 100 .step = 1, 101 .default_value = 12 102 }, 103 .set = pb0100_set_exposure, 104 .get = pb0100_get_exposure 105 }, 106#define AUTOGAIN_IDX 4 107 { 108 { 109 .id = V4L2_CID_AUTOGAIN, 110 .type = V4L2_CTRL_TYPE_BOOLEAN, 111 .name = "Automatic Gain and Exposure", 112 .minimum = 0, 113 .maximum = 1, 114 .step = 1, 115 .default_value = 1 116 }, 117 .set = pb0100_set_autogain, 118 .get = pb0100_get_autogain 119 }, 120#define AUTOGAIN_TARGET_IDX 5 121 { 122 { 123 .id = V4L2_CTRL_CLASS_USER + 0x1000, 124 .type = V4L2_CTRL_TYPE_INTEGER, 125 .name = "Automatic Gain Target", 126 .minimum = 0, 127 .maximum = 255, 128 .step = 1, 129 .default_value = 128 130 }, 131 .set = pb0100_set_autogain_target, 132 .get = pb0100_get_autogain_target 133 }, 134#define NATURAL_IDX 6 135 { 136 { 137 .id = V4L2_CTRL_CLASS_USER + 0x1001, 138 .type = V4L2_CTRL_TYPE_BOOLEAN, 139 .name = "Natural Light Source", 140 .minimum = 0, 141 .maximum = 1, 142 .step = 1, 143 .default_value = 1 144 }, 145 .set = pb0100_set_natural, 146 .get = pb0100_get_natural 147 } 148}; 149 150static struct v4l2_pix_format pb0100_mode[] = { 151/* low res / subsample modes disabled as they are only half res horizontal, 152 halving the vertical resolution does not seem to work */ 153 { 154 320, 155 240, 156 V4L2_PIX_FMT_SGRBG8, 157 V4L2_FIELD_NONE, 158 .sizeimage = 320 * 240, 159 .bytesperline = 320, 160 .colorspace = V4L2_COLORSPACE_SRGB, 161 .priv = PB0100_CROP_TO_VGA 162 }, 163 { 164 352, 165 288, 166 V4L2_PIX_FMT_SGRBG8, 167 V4L2_FIELD_NONE, 168 .sizeimage = 352 * 288, 169 .bytesperline = 352, 170 .colorspace = V4L2_COLORSPACE_SRGB, 171 .priv = 0 172 } 173}; 174 175static int pb0100_probe(struct sd *sd) 176{ 177 u16 sensor; 178 int i, err; 179 s32 *sensor_settings; 180 181 err = stv06xx_read_sensor(sd, PB_IDENT, &sensor); 182 183 if (err < 0) 184 return -ENODEV; 185 186 if ((sensor >> 8) == 0x64) { 187 sensor_settings = kmalloc( 188 ARRAY_SIZE(pb0100_ctrl) * sizeof(s32), 189 GFP_KERNEL); 190 if (!sensor_settings) 191 return -ENOMEM; 192 193 info("Photobit pb0100 sensor detected"); 194 195 sd->gspca_dev.cam.cam_mode = pb0100_mode; 196 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode); 197 sd->desc.ctrls = pb0100_ctrl; 198 sd->desc.nctrls = ARRAY_SIZE(pb0100_ctrl); 199 for (i = 0; i < sd->desc.nctrls; i++) 200 sensor_settings[i] = pb0100_ctrl[i].qctrl.default_value; 201 sd->sensor_priv = sensor_settings; 202 203 return 0; 204 } 205 206 return -ENODEV; 207} 208 209static int pb0100_start(struct sd *sd) 210{ 211 int err; 212 struct cam *cam = &sd->gspca_dev.cam; 213 s32 *sensor_settings = sd->sensor_priv; 214 u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv; 215 216 /* Setup sensor window */ 217 if (mode & PB0100_CROP_TO_VGA) { 218 stv06xx_write_sensor(sd, PB_RSTART, 30); 219 stv06xx_write_sensor(sd, PB_CSTART, 20); 220 stv06xx_write_sensor(sd, PB_RWSIZE, 240 - 1); 221 stv06xx_write_sensor(sd, PB_CWSIZE, 320 - 1); 222 } else { 223 stv06xx_write_sensor(sd, PB_RSTART, 8); 224 stv06xx_write_sensor(sd, PB_CSTART, 4); 225 stv06xx_write_sensor(sd, PB_RWSIZE, 288 - 1); 226 stv06xx_write_sensor(sd, PB_CWSIZE, 352 - 1); 227 } 228 229 if (mode & PB0100_SUBSAMPLE) { 230 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02); 231 stv06xx_write_bridge(sd, STV_X_CTRL, 0x06); 232 233 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10); 234 } else { 235 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01); 236 stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a); 237 /* larger -> slower */ 238 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20); 239 } 240 241 /* set_gain also sets red and blue balance */ 242 pb0100_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); 243 pb0100_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]); 244 pb0100_set_autogain_target(&sd->gspca_dev, 245 sensor_settings[AUTOGAIN_TARGET_IDX]); 246 pb0100_set_autogain(&sd->gspca_dev, sensor_settings[AUTOGAIN_IDX]); 247 248 err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)|BIT(1)); 249 PDEBUG(D_STREAM, "Started stream, status: %d", err); 250 251 return (err < 0) ? err : 0; 252} 253 254static int pb0100_stop(struct sd *sd) 255{ 256 int err; 257 258 err = stv06xx_write_sensor(sd, PB_ABORTFRAME, 1); 259 260 if (err < 0) 261 goto out; 262 263 /* Set bit 1 to zero */ 264 err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)); 265 266 PDEBUG(D_STREAM, "Halting stream"); 267out: 268 return (err < 0) ? err : 0; 269} 270 271static void pb0100_disconnect(struct sd *sd) 272{ 273 sd->sensor = NULL; 274 kfree(sd->sensor_priv); 275} 276 277static int pb0100_init(struct sd *sd) 278{ 279 stv06xx_write_bridge(sd, STV_REG00, 1); 280 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0); 281 282 /* Reset sensor */ 283 stv06xx_write_sensor(sd, PB_RESET, 1); 284 stv06xx_write_sensor(sd, PB_RESET, 0); 285 286 /* Disable chip */ 287 stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)); 288 289 /* Gain stuff...*/ 290 stv06xx_write_sensor(sd, PB_PREADCTRL, BIT(12)|BIT(10)|BIT(6)); 291 stv06xx_write_sensor(sd, PB_ADCGLOBALGAIN, 12); 292 293 /* Set up auto-exposure */ 294 /* ADC VREF_HI new setting for a transition 295 from the Expose1 to the Expose2 setting */ 296 stv06xx_write_sensor(sd, PB_R28, 12); 297 /* gain max for autoexposure */ 298 stv06xx_write_sensor(sd, PB_ADCMAXGAIN, 180); 299 /* gain min for autoexposure */ 300 stv06xx_write_sensor(sd, PB_ADCMINGAIN, 12); 301 /* Maximum frame integration time (programmed into R8) 302 allowed for auto-exposure routine */ 303 stv06xx_write_sensor(sd, PB_R54, 3); 304 /* Minimum frame integration time (programmed into R8) 305 allowed for auto-exposure routine */ 306 stv06xx_write_sensor(sd, PB_R55, 0); 307 stv06xx_write_sensor(sd, PB_UPDATEINT, 1); 308 /* R15 Expose0 (maximum that auto-exposure may use) */ 309 stv06xx_write_sensor(sd, PB_R15, 800); 310 /* R17 Expose2 (minimum that auto-exposure may use) */ 311 stv06xx_write_sensor(sd, PB_R17, 10); 312 313 stv06xx_write_sensor(sd, PB_EXPGAIN, 0); 314 315 /* 0x14 */ 316 stv06xx_write_sensor(sd, PB_VOFFSET, 0); 317 /* 0x0D */ 318 stv06xx_write_sensor(sd, PB_ADCGAINH, 11); 319 /* Set black level (important!) */ 320 stv06xx_write_sensor(sd, PB_ADCGAINL, 0); 321 322 /* ??? */ 323 stv06xx_write_bridge(sd, STV_REG00, 0x11); 324 stv06xx_write_bridge(sd, STV_REG03, 0x45); 325 stv06xx_write_bridge(sd, STV_REG04, 0x07); 326 327 /* ISO-Size (0x27b: 635... why? - HDCS uses 847) */ 328 stv06xx_write_bridge(sd, STV_ISO_SIZE_L, 847); 329 330 /* Scan/timing for the sensor */ 331 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1)); 332 stv06xx_write_sensor(sd, PB_CFILLIN, 14); 333 stv06xx_write_sensor(sd, PB_VBL, 0); 334 stv06xx_write_sensor(sd, PB_FINTTIME, 0); 335 stv06xx_write_sensor(sd, PB_RINTTIME, 123); 336 337 stv06xx_write_bridge(sd, STV_REG01, 0xc2); 338 stv06xx_write_bridge(sd, STV_REG02, 0xb0); 339 return 0; 340} 341 342static int pb0100_dump(struct sd *sd) 343{ 344 return 0; 345} 346 347static int pb0100_get_gain(struct gspca_dev *gspca_dev, __s32 *val) 348{ 349 struct sd *sd = (struct sd *) gspca_dev; 350 s32 *sensor_settings = sd->sensor_priv; 351 352 *val = sensor_settings[GAIN_IDX]; 353 354 return 0; 355} 356 357static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val) 358{ 359 int err; 360 struct sd *sd = (struct sd *) gspca_dev; 361 s32 *sensor_settings = sd->sensor_priv; 362 363 if (sensor_settings[AUTOGAIN_IDX]) 364 return -EBUSY; 365 366 sensor_settings[GAIN_IDX] = val; 367 err = stv06xx_write_sensor(sd, PB_G1GAIN, val); 368 if (!err) 369 err = stv06xx_write_sensor(sd, PB_G2GAIN, val); 370 PDEBUG(D_V4L2, "Set green gain to %d, status: %d", val, err); 371 372 if (!err) 373 err = pb0100_set_red_balance(gspca_dev, 374 sensor_settings[RED_BALANCE_IDX]); 375 if (!err) 376 err = pb0100_set_blue_balance(gspca_dev, 377 sensor_settings[BLUE_BALANCE_IDX]); 378 379 return err; 380} 381 382static int pb0100_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) 383{ 384 struct sd *sd = (struct sd *) gspca_dev; 385 s32 *sensor_settings = sd->sensor_priv; 386 387 *val = sensor_settings[RED_BALANCE_IDX]; 388 389 return 0; 390} 391 392static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) 393{ 394 int err; 395 struct sd *sd = (struct sd *) gspca_dev; 396 s32 *sensor_settings = sd->sensor_priv; 397 398 if (sensor_settings[AUTOGAIN_IDX]) 399 return -EBUSY; 400 401 sensor_settings[RED_BALANCE_IDX] = val; 402 val += sensor_settings[GAIN_IDX]; 403 if (val < 0) 404 val = 0; 405 else if (val > 255) 406 val = 255; 407 408 err = stv06xx_write_sensor(sd, PB_RGAIN, val); 409 PDEBUG(D_V4L2, "Set red gain to %d, status: %d", val, err); 410 411 return err; 412} 413 414static int pb0100_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) 415{ 416 struct sd *sd = (struct sd *) gspca_dev; 417 s32 *sensor_settings = sd->sensor_priv; 418 419 *val = sensor_settings[BLUE_BALANCE_IDX]; 420 421 return 0; 422} 423 424static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) 425{ 426 int err; 427 struct sd *sd = (struct sd *) gspca_dev; 428 s32 *sensor_settings = sd->sensor_priv; 429 430 if (sensor_settings[AUTOGAIN_IDX]) 431 return -EBUSY; 432 433 sensor_settings[BLUE_BALANCE_IDX] = val; 434 val += sensor_settings[GAIN_IDX]; 435 if (val < 0) 436 val = 0; 437 else if (val > 255) 438 val = 255; 439 440 err = stv06xx_write_sensor(sd, PB_BGAIN, val); 441 PDEBUG(D_V4L2, "Set blue gain to %d, status: %d", val, err); 442 443 return err; 444} 445 446static int pb0100_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) 447{ 448 struct sd *sd = (struct sd *) gspca_dev; 449 s32 *sensor_settings = sd->sensor_priv; 450 451 *val = sensor_settings[EXPOSURE_IDX]; 452 453 return 0; 454} 455 456static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val) 457{ 458 int err; 459 struct sd *sd = (struct sd *) gspca_dev; 460 s32 *sensor_settings = sd->sensor_priv; 461 462 if (sensor_settings[AUTOGAIN_IDX]) 463 return -EBUSY; 464 465 sensor_settings[EXPOSURE_IDX] = val; 466 err = stv06xx_write_sensor(sd, PB_RINTTIME, val); 467 PDEBUG(D_V4L2, "Set exposure to %d, status: %d", val, err); 468 469 return err; 470} 471 472static int pb0100_get_autogain(struct gspca_dev *gspca_dev, __s32 *val) 473{ 474 struct sd *sd = (struct sd *) gspca_dev; 475 s32 *sensor_settings = sd->sensor_priv; 476 477 *val = sensor_settings[AUTOGAIN_IDX]; 478 479 return 0; 480} 481 482static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val) 483{ 484 int err; 485 struct sd *sd = (struct sd *) gspca_dev; 486 s32 *sensor_settings = sd->sensor_priv; 487 488 sensor_settings[AUTOGAIN_IDX] = val; 489 if (sensor_settings[AUTOGAIN_IDX]) { 490 if (sensor_settings[NATURAL_IDX]) 491 val = BIT(6)|BIT(4)|BIT(0); 492 else 493 val = BIT(4)|BIT(0); 494 } else 495 val = 0; 496 497 err = stv06xx_write_sensor(sd, PB_EXPGAIN, val); 498 PDEBUG(D_V4L2, "Set autogain to %d (natural: %d), status: %d", 499 sensor_settings[AUTOGAIN_IDX], sensor_settings[NATURAL_IDX], 500 err); 501 502 return err; 503} 504 505static int pb0100_get_autogain_target(struct gspca_dev *gspca_dev, __s32 *val) 506{ 507 struct sd *sd = (struct sd *) gspca_dev; 508 s32 *sensor_settings = sd->sensor_priv; 509 510 *val = sensor_settings[AUTOGAIN_TARGET_IDX]; 511 512 return 0; 513} 514 515static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val) 516{ 517 int err, totalpixels, brightpixels, darkpixels; 518 struct sd *sd = (struct sd *) gspca_dev; 519 s32 *sensor_settings = sd->sensor_priv; 520 521 sensor_settings[AUTOGAIN_TARGET_IDX] = val; 522 523 /* Number of pixels counted by the sensor when subsampling the pixels. 524 * Slightly larger than the real value to avoid oscillation */ 525 totalpixels = gspca_dev->width * gspca_dev->height; 526 totalpixels = totalpixels/(8*8) + totalpixels/(64*64); 527 528 brightpixels = (totalpixels * val) >> 8; 529 darkpixels = totalpixels - brightpixels; 530 err = stv06xx_write_sensor(sd, PB_R21, brightpixels); 531 if (!err) 532 err = stv06xx_write_sensor(sd, PB_R22, darkpixels); 533 534 PDEBUG(D_V4L2, "Set autogain target to %d, status: %d", val, err); 535 536 return err; 537} 538 539static int pb0100_get_natural(struct gspca_dev *gspca_dev, __s32 *val) 540{ 541 struct sd *sd = (struct sd *) gspca_dev; 542 s32 *sensor_settings = sd->sensor_priv; 543 544 *val = sensor_settings[NATURAL_IDX]; 545 546 return 0; 547} 548 549static int pb0100_set_natural(struct gspca_dev *gspca_dev, __s32 val) 550{ 551 struct sd *sd = (struct sd *) gspca_dev; 552 s32 *sensor_settings = sd->sensor_priv; 553 554 sensor_settings[NATURAL_IDX] = val; 555 556 return pb0100_set_autogain(gspca_dev, sensor_settings[AUTOGAIN_IDX]); 557} 558