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 * Copyright (c) 2008 Chia-I Wu 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 * P/N 861037: Sensor HDCS1000 ASIC STV0600 23 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 24 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express 25 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam 26 * P/N 861075-0040: Sensor HDCS1000 ASIC 27 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB 28 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web 29 */ 30 31#include "stv06xx_hdcs.h" 32 33static const struct ctrl hdcs1x00_ctrl[] = { 34 { 35 { 36 .id = V4L2_CID_EXPOSURE, 37 .type = V4L2_CTRL_TYPE_INTEGER, 38 .name = "exposure", 39 .minimum = 0x00, 40 .maximum = 0xff, 41 .step = 0x1, 42 .default_value = HDCS_DEFAULT_EXPOSURE, 43 .flags = V4L2_CTRL_FLAG_SLIDER 44 }, 45 .set = hdcs_set_exposure, 46 .get = hdcs_get_exposure 47 }, { 48 { 49 .id = V4L2_CID_GAIN, 50 .type = V4L2_CTRL_TYPE_INTEGER, 51 .name = "gain", 52 .minimum = 0x00, 53 .maximum = 0xff, 54 .step = 0x1, 55 .default_value = HDCS_DEFAULT_GAIN, 56 .flags = V4L2_CTRL_FLAG_SLIDER 57 }, 58 .set = hdcs_set_gain, 59 .get = hdcs_get_gain 60 } 61}; 62 63static struct v4l2_pix_format hdcs1x00_mode[] = { 64 { 65 HDCS_1X00_DEF_WIDTH, 66 HDCS_1X00_DEF_HEIGHT, 67 V4L2_PIX_FMT_SGRBG8, 68 V4L2_FIELD_NONE, 69 .sizeimage = 70 HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT, 71 .bytesperline = HDCS_1X00_DEF_WIDTH, 72 .colorspace = V4L2_COLORSPACE_SRGB, 73 .priv = 1 74 } 75}; 76 77static const struct ctrl hdcs1020_ctrl[] = { 78 { 79 { 80 .id = V4L2_CID_EXPOSURE, 81 .type = V4L2_CTRL_TYPE_INTEGER, 82 .name = "exposure", 83 .minimum = 0x00, 84 .maximum = 0xffff, 85 .step = 0x1, 86 .default_value = HDCS_DEFAULT_EXPOSURE, 87 .flags = V4L2_CTRL_FLAG_SLIDER 88 }, 89 .set = hdcs_set_exposure, 90 .get = hdcs_get_exposure 91 }, { 92 { 93 .id = V4L2_CID_GAIN, 94 .type = V4L2_CTRL_TYPE_INTEGER, 95 .name = "gain", 96 .minimum = 0x00, 97 .maximum = 0xff, 98 .step = 0x1, 99 .default_value = HDCS_DEFAULT_GAIN, 100 .flags = V4L2_CTRL_FLAG_SLIDER 101 }, 102 .set = hdcs_set_gain, 103 .get = hdcs_get_gain 104 } 105}; 106 107static struct v4l2_pix_format hdcs1020_mode[] = { 108 { 109 HDCS_1020_DEF_WIDTH, 110 HDCS_1020_DEF_HEIGHT, 111 V4L2_PIX_FMT_SGRBG8, 112 V4L2_FIELD_NONE, 113 .sizeimage = 114 HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT, 115 .bytesperline = HDCS_1020_DEF_WIDTH, 116 .colorspace = V4L2_COLORSPACE_SRGB, 117 .priv = 1 118 } 119}; 120 121enum hdcs_power_state { 122 HDCS_STATE_SLEEP, 123 HDCS_STATE_IDLE, 124 HDCS_STATE_RUN 125}; 126 127/* no lock? */ 128struct hdcs { 129 enum hdcs_power_state state; 130 int w, h; 131 132 /* visible area of the sensor array */ 133 struct { 134 int left, top; 135 int width, height; 136 int border; 137 } array; 138 139 struct { 140 /* Column timing overhead */ 141 u8 cto; 142 /* Column processing overhead */ 143 u8 cpo; 144 /* Row sample period constant */ 145 u16 rs; 146 /* Exposure reset duration */ 147 u16 er; 148 } exp; 149 150 int psmp; 151 u8 exp_cache, gain_cache; 152}; 153 154static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len) 155{ 156 u8 regs[I2C_MAX_BYTES * 2]; 157 int i; 158 159 if (unlikely((len <= 0) || (len >= I2C_MAX_BYTES) || 160 (reg + len > 0xff))) 161 return -EINVAL; 162 163 for (i = 0; i < len; i++) { 164 regs[2 * i] = reg; 165 regs[2 * i + 1] = vals[i]; 166 /* All addresses are shifted left one bit as bit 0 toggles r/w */ 167 reg += 2; 168 } 169 170 return stv06xx_write_sensor_bytes(sd, regs, len); 171} 172 173static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state) 174{ 175 struct hdcs *hdcs = sd->sensor_priv; 176 u8 val; 177 int ret; 178 179 if (hdcs->state == state) 180 return 0; 181 182 /* we need to go idle before running or sleeping */ 183 if (hdcs->state != HDCS_STATE_IDLE) { 184 ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0); 185 if (ret) 186 return ret; 187 } 188 189 hdcs->state = HDCS_STATE_IDLE; 190 191 if (state == HDCS_STATE_IDLE) 192 return 0; 193 194 switch (state) { 195 case HDCS_STATE_SLEEP: 196 val = HDCS_SLEEP_MODE; 197 break; 198 199 case HDCS_STATE_RUN: 200 val = HDCS_RUN_ENABLE; 201 break; 202 203 default: 204 return -EINVAL; 205 } 206 207 ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val); 208 209 /* Update the state if the write succeeded */ 210 if (!ret) 211 hdcs->state = state; 212 213 return ret; 214} 215 216static int hdcs_reset(struct sd *sd) 217{ 218 struct hdcs *hdcs = sd->sensor_priv; 219 int err; 220 221 err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 1); 222 if (err < 0) 223 return err; 224 225 err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0); 226 if (err < 0) 227 hdcs->state = HDCS_STATE_IDLE; 228 229 return err; 230} 231 232static int hdcs_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) 233{ 234 struct sd *sd = (struct sd *) gspca_dev; 235 struct hdcs *hdcs = sd->sensor_priv; 236 237 *val = hdcs->exp_cache; 238 239 return 0; 240} 241 242static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val) 243{ 244 struct sd *sd = (struct sd *) gspca_dev; 245 struct hdcs *hdcs = sd->sensor_priv; 246 int rowexp, srowexp; 247 int max_srowexp; 248 /* Column time period */ 249 int ct; 250 /* Column processing period */ 251 int cp; 252 /* Row processing period */ 253 int rp; 254 /* Minimum number of column timing periods 255 within the column processing period */ 256 int mnct; 257 int cycles, err; 258 u8 exp[14]; 259 260 val &= 0xff; 261 hdcs->exp_cache = val; 262 263 cycles = val * HDCS_CLK_FREQ_MHZ * 257; 264 265 ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2); 266 cp = hdcs->exp.cto + (hdcs->w * ct / 2); 267 268 /* the cycles one row takes */ 269 rp = hdcs->exp.rs + cp; 270 271 rowexp = cycles / rp; 272 273 /* the remaining cycles */ 274 cycles -= rowexp * rp; 275 276 /* calculate sub-row exposure */ 277 if (IS_1020(sd)) { 278 /* see HDCS-1020 datasheet 3.5.6.4, p. 63 */ 279 srowexp = hdcs->w - (cycles + hdcs->exp.er + 13) / ct; 280 281 mnct = (hdcs->exp.er + 12 + ct - 1) / ct; 282 max_srowexp = hdcs->w - mnct; 283 } else { 284 /* see HDCS-1000 datasheet 3.4.5.5, p. 61 */ 285 srowexp = cp - hdcs->exp.er - 6 - cycles; 286 287 mnct = (hdcs->exp.er + 5 + ct - 1) / ct; 288 max_srowexp = cp - mnct * ct - 1; 289 } 290 291 if (srowexp < 0) 292 srowexp = 0; 293 else if (srowexp > max_srowexp) 294 srowexp = max_srowexp; 295 296 if (IS_1020(sd)) { 297 exp[0] = HDCS20_CONTROL; 298 exp[1] = 0x00; /* Stop streaming */ 299 exp[2] = HDCS_ROWEXPL; 300 exp[3] = rowexp & 0xff; 301 exp[4] = HDCS_ROWEXPH; 302 exp[5] = rowexp >> 8; 303 exp[6] = HDCS20_SROWEXP; 304 exp[7] = (srowexp >> 2) & 0xff; 305 exp[8] = HDCS20_ERROR; 306 exp[9] = 0x10; /* Clear exposure error flag*/ 307 exp[10] = HDCS20_CONTROL; 308 exp[11] = 0x04; /* Restart streaming */ 309 err = stv06xx_write_sensor_bytes(sd, exp, 6); 310 } else { 311 exp[0] = HDCS00_CONTROL; 312 exp[1] = 0x00; /* Stop streaming */ 313 exp[2] = HDCS_ROWEXPL; 314 exp[3] = rowexp & 0xff; 315 exp[4] = HDCS_ROWEXPH; 316 exp[5] = rowexp >> 8; 317 exp[6] = HDCS00_SROWEXPL; 318 exp[7] = srowexp & 0xff; 319 exp[8] = HDCS00_SROWEXPH; 320 exp[9] = srowexp >> 8; 321 exp[10] = HDCS_STATUS; 322 exp[11] = 0x10; /* Clear exposure error flag*/ 323 exp[12] = HDCS00_CONTROL; 324 exp[13] = 0x04; /* Restart streaming */ 325 err = stv06xx_write_sensor_bytes(sd, exp, 7); 326 if (err < 0) 327 return err; 328 } 329 PDEBUG(D_V4L2, "Writing exposure %d, rowexp %d, srowexp %d", 330 val, rowexp, srowexp); 331 return err; 332} 333 334static int hdcs_set_gains(struct sd *sd, u8 g) 335{ 336 struct hdcs *hdcs = sd->sensor_priv; 337 int err; 338 u8 gains[4]; 339 340 hdcs->gain_cache = g; 341 342 /* the voltage gain Av = (1 + 19 * val / 127) * (1 + bit7) */ 343 if (g > 127) 344 g = 0x80 | (g / 2); 345 346 gains[0] = g; 347 gains[1] = g; 348 gains[2] = g; 349 gains[3] = g; 350 351 err = hdcs_reg_write_seq(sd, HDCS_ERECPGA, gains, 4); 352 return err; 353} 354 355static int hdcs_get_gain(struct gspca_dev *gspca_dev, __s32 *val) 356{ 357 struct sd *sd = (struct sd *) gspca_dev; 358 struct hdcs *hdcs = sd->sensor_priv; 359 360 *val = hdcs->gain_cache; 361 362 return 0; 363} 364 365static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val) 366{ 367 PDEBUG(D_V4L2, "Writing gain %d", val); 368 return hdcs_set_gains((struct sd *) gspca_dev, 369 val & 0xff); 370} 371 372static int hdcs_set_size(struct sd *sd, 373 unsigned int width, unsigned int height) 374{ 375 struct hdcs *hdcs = sd->sensor_priv; 376 u8 win[4]; 377 unsigned int x, y; 378 int err; 379 380 /* must be multiple of 4 */ 381 width = (width + 3) & ~0x3; 382 height = (height + 3) & ~0x3; 383 384 if (width > hdcs->array.width) 385 width = hdcs->array.width; 386 387 if (IS_1020(sd)) { 388 /* the borders are also invalid */ 389 if (height + 2 * hdcs->array.border + HDCS_1020_BOTTOM_Y_SKIP 390 > hdcs->array.height) 391 height = hdcs->array.height - 2 * hdcs->array.border - 392 HDCS_1020_BOTTOM_Y_SKIP; 393 394 y = (hdcs->array.height - HDCS_1020_BOTTOM_Y_SKIP - height) / 2 395 + hdcs->array.top; 396 } else { 397 if (height > hdcs->array.height) 398 height = hdcs->array.height; 399 400 y = hdcs->array.top + (hdcs->array.height - height) / 2; 401 } 402 403 x = hdcs->array.left + (hdcs->array.width - width) / 2; 404 405 win[0] = y / 4; 406 win[1] = x / 4; 407 win[2] = (y + height) / 4 - 1; 408 win[3] = (x + width) / 4 - 1; 409 410 err = hdcs_reg_write_seq(sd, HDCS_FWROW, win, 4); 411 if (err < 0) 412 return err; 413 414 /* Update the current width and height */ 415 hdcs->w = width; 416 hdcs->h = height; 417 return err; 418} 419 420static int hdcs_probe_1x00(struct sd *sd) 421{ 422 struct hdcs *hdcs; 423 u16 sensor; 424 int ret; 425 426 ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor); 427 if (ret < 0 || sensor != 0x08) 428 return -ENODEV; 429 430 info("HDCS-1000/1100 sensor detected"); 431 432 sd->gspca_dev.cam.cam_mode = hdcs1x00_mode; 433 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode); 434 sd->desc.ctrls = hdcs1x00_ctrl; 435 sd->desc.nctrls = ARRAY_SIZE(hdcs1x00_ctrl); 436 437 hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL); 438 if (!hdcs) 439 return -ENOMEM; 440 441 hdcs->array.left = 8; 442 hdcs->array.top = 8; 443 hdcs->array.width = HDCS_1X00_DEF_WIDTH; 444 hdcs->array.height = HDCS_1X00_DEF_HEIGHT; 445 hdcs->array.border = 4; 446 447 hdcs->exp.cto = 4; 448 hdcs->exp.cpo = 2; 449 hdcs->exp.rs = 186; 450 hdcs->exp.er = 100; 451 452 /* 453 * Frame rate on HDCS-1000 with STV600 depends on PSMP: 454 * 4 = doesn't work at all 455 * 5 = 7.8 fps, 456 * 6 = 6.9 fps, 457 * 8 = 6.3 fps, 458 * 10 = 5.5 fps, 459 * 15 = 4.4 fps, 460 * 31 = 2.8 fps 461 * 462 * Frame rate on HDCS-1000 with STV602 depends on PSMP: 463 * 15 = doesn't work at all 464 * 18 = doesn't work at all 465 * 19 = 7.3 fps 466 * 20 = 7.4 fps 467 * 21 = 7.4 fps 468 * 22 = 7.4 fps 469 * 24 = 6.3 fps 470 * 30 = 5.4 fps 471 */ 472 hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5; 473 474 sd->sensor_priv = hdcs; 475 476 return 0; 477} 478 479static int hdcs_probe_1020(struct sd *sd) 480{ 481 struct hdcs *hdcs; 482 u16 sensor; 483 int ret; 484 485 ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor); 486 if (ret < 0 || sensor != 0x10) 487 return -ENODEV; 488 489 info("HDCS-1020 sensor detected"); 490 491 sd->gspca_dev.cam.cam_mode = hdcs1020_mode; 492 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode); 493 sd->desc.ctrls = hdcs1020_ctrl; 494 sd->desc.nctrls = ARRAY_SIZE(hdcs1020_ctrl); 495 496 hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL); 497 if (!hdcs) 498 return -ENOMEM; 499 500 /* 501 * From Andrey's test image: looks like HDCS-1020 upper-left 502 * visible pixel is at 24,8 (y maybe even smaller?) and lower-right 503 * visible pixel at 375,299 (x maybe even larger?) 504 */ 505 hdcs->array.left = 24; 506 hdcs->array.top = 4; 507 hdcs->array.width = HDCS_1020_DEF_WIDTH; 508 hdcs->array.height = 304; 509 hdcs->array.border = 4; 510 511 hdcs->psmp = 6; 512 513 hdcs->exp.cto = 3; 514 hdcs->exp.cpo = 3; 515 hdcs->exp.rs = 155; 516 hdcs->exp.er = 96; 517 518 sd->sensor_priv = hdcs; 519 520 return 0; 521} 522 523static int hdcs_start(struct sd *sd) 524{ 525 PDEBUG(D_STREAM, "Starting stream"); 526 527 return hdcs_set_state(sd, HDCS_STATE_RUN); 528} 529 530static int hdcs_stop(struct sd *sd) 531{ 532 PDEBUG(D_STREAM, "Halting stream"); 533 534 return hdcs_set_state(sd, HDCS_STATE_SLEEP); 535} 536 537static void hdcs_disconnect(struct sd *sd) 538{ 539 PDEBUG(D_PROBE, "Disconnecting the sensor"); 540 kfree(sd->sensor_priv); 541} 542 543static int hdcs_init(struct sd *sd) 544{ 545 struct hdcs *hdcs = sd->sensor_priv; 546 int i, err = 0; 547 548 /* Set the STV0602AA in STV0600 emulation mode */ 549 if (sd->bridge == BRIDGE_STV602) 550 stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1); 551 552 /* Execute the bridge init */ 553 for (i = 0; i < ARRAY_SIZE(stv_bridge_init) && !err; i++) { 554 err = stv06xx_write_bridge(sd, stv_bridge_init[i][0], 555 stv_bridge_init[i][1]); 556 } 557 if (err < 0) 558 return err; 559 560 /* sensor soft reset */ 561 hdcs_reset(sd); 562 563 /* Execute the sensor init */ 564 for (i = 0; i < ARRAY_SIZE(stv_sensor_init) && !err; i++) { 565 err = stv06xx_write_sensor(sd, stv_sensor_init[i][0], 566 stv_sensor_init[i][1]); 567 } 568 if (err < 0) 569 return err; 570 571 /* Enable continous frame capture, bit 2: stop when frame complete */ 572 err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3)); 573 if (err < 0) 574 return err; 575 576 /* Set PGA sample duration 577 (was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */ 578 if (IS_1020(sd)) 579 err = stv06xx_write_sensor(sd, HDCS_TCTRL, 580 (HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp); 581 else 582 err = stv06xx_write_sensor(sd, HDCS_TCTRL, 583 (HDCS_ADC_START_SIG_DUR << 5) | hdcs->psmp); 584 if (err < 0) 585 return err; 586 587 err = hdcs_set_gains(sd, HDCS_DEFAULT_GAIN); 588 if (err < 0) 589 return err; 590 591 err = hdcs_set_size(sd, hdcs->array.width, hdcs->array.height); 592 if (err < 0) 593 return err; 594 595 err = hdcs_set_exposure(&sd->gspca_dev, HDCS_DEFAULT_EXPOSURE); 596 return err; 597} 598 599static int hdcs_dump(struct sd *sd) 600{ 601 u16 reg, val; 602 603 info("Dumping sensor registers:"); 604 605 for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) { 606 stv06xx_read_sensor(sd, reg, &val); 607 info("reg 0x%02x = 0x%02x", reg, val); 608 } 609 return 0; 610} 611