pac7302.c revision 95c967c167785eb991cf6b22fb854dd8d61d0ff8
1/* 2 * Pixart PAC7302 library 3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li 4 * 5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> 6 * 7 * Separated from Pixart PAC7311 library by Márton Németh 8 * Camera button input handling by Márton Németh <nm127@freemail.hu> 9 * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu> 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26/* Some documentation about various registers as determined by trial and error. 27 28 Register page 1: 29 30 Address Description 31 0x78 Global control, bit 6 controls the LED (inverted) 32 33 Register page 3: 34 35 Address Description 36 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on 37 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? 38 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps 39 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps, 40 63 -> ~27 fps, the 2 msb's must always be 1 !! 41 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0: 42 1 -> ~30 fps, 2 -> ~20 fps 43 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time 44 0x0f Exposure bit 8, 0-448, 448 = no exposure at all 45 0x10 Master gain 0-31 46 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused 47 48 The registers are accessed in the following functions: 49 50 Page | Register | Function 51 -----+------------+--------------------------------------------------- 52 0 | 0x0f..0x20 | setcolors() 53 0 | 0xa2..0xab | setbrightcont() 54 0 | 0xc5 | setredbalance() 55 0 | 0xc6 | setwhitebalance() 56 0 | 0xc7 | setbluebalance() 57 0 | 0xdc | setbrightcont(), setcolors() 58 3 | 0x02 | setexposure() 59 3 | 0x10 | setgain() 60 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip() 61 3 | 0x21 | sethvflip() 62*/ 63 64#define MODULE_NAME "pac7302" 65 66#include <linux/input.h> 67#include <media/v4l2-chip-ident.h> 68#include "gspca.h" 69 70MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); 71MODULE_DESCRIPTION("Pixart PAC7302"); 72MODULE_LICENSE("GPL"); 73 74/* specific webcam descriptor for pac7302 */ 75struct sd { 76 struct gspca_dev gspca_dev; /* !! must be the first item */ 77 78 unsigned char brightness; 79 unsigned char contrast; 80 unsigned char colors; 81 unsigned char white_balance; 82 unsigned char red_balance; 83 unsigned char blue_balance; 84 unsigned char gain; 85 unsigned char autogain; 86 unsigned short exposure; 87 __u8 hflip; 88 __u8 vflip; 89 u8 flags; 90#define FL_HFLIP 0x01 /* mirrored by default */ 91#define FL_VFLIP 0x02 /* vertical flipped by default */ 92 93 u8 sof_read; 94 u8 autogain_ignore_frames; 95 96 atomic_t avg_lum; 97}; 98 99/* V4L2 controls supported by the driver */ 100static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); 101static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); 102static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); 103static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); 104static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); 105static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); 106static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val); 107static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val); 108static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val); 109static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val); 110static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val); 111static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val); 112static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); 113static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); 114static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); 115static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); 116static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); 117static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); 118static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); 119static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); 120static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); 121static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); 122 123static const struct ctrl sd_ctrls[] = { 124 { 125 { 126 .id = V4L2_CID_BRIGHTNESS, 127 .type = V4L2_CTRL_TYPE_INTEGER, 128 .name = "Brightness", 129 .minimum = 0, 130#define BRIGHTNESS_MAX 0x20 131 .maximum = BRIGHTNESS_MAX, 132 .step = 1, 133#define BRIGHTNESS_DEF 0x10 134 .default_value = BRIGHTNESS_DEF, 135 }, 136 .set = sd_setbrightness, 137 .get = sd_getbrightness, 138 }, 139 { 140 { 141 .id = V4L2_CID_CONTRAST, 142 .type = V4L2_CTRL_TYPE_INTEGER, 143 .name = "Contrast", 144 .minimum = 0, 145#define CONTRAST_MAX 255 146 .maximum = CONTRAST_MAX, 147 .step = 1, 148#define CONTRAST_DEF 127 149 .default_value = CONTRAST_DEF, 150 }, 151 .set = sd_setcontrast, 152 .get = sd_getcontrast, 153 }, 154 { 155 { 156 .id = V4L2_CID_SATURATION, 157 .type = V4L2_CTRL_TYPE_INTEGER, 158 .name = "Saturation", 159 .minimum = 0, 160#define COLOR_MAX 255 161 .maximum = COLOR_MAX, 162 .step = 1, 163#define COLOR_DEF 127 164 .default_value = COLOR_DEF, 165 }, 166 .set = sd_setcolors, 167 .get = sd_getcolors, 168 }, 169 { 170 { 171 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, 172 .type = V4L2_CTRL_TYPE_INTEGER, 173 .name = "White Balance", 174 .minimum = 0, 175 .maximum = 255, 176 .step = 1, 177#define WHITEBALANCE_DEF 4 178 .default_value = WHITEBALANCE_DEF, 179 }, 180 .set = sd_setwhitebalance, 181 .get = sd_getwhitebalance, 182 }, 183 { 184 { 185 .id = V4L2_CID_RED_BALANCE, 186 .type = V4L2_CTRL_TYPE_INTEGER, 187 .name = "Red", 188 .minimum = 0, 189 .maximum = 3, 190 .step = 1, 191#define REDBALANCE_DEF 1 192 .default_value = REDBALANCE_DEF, 193 }, 194 .set = sd_setredbalance, 195 .get = sd_getredbalance, 196 }, 197 { 198 { 199 .id = V4L2_CID_BLUE_BALANCE, 200 .type = V4L2_CTRL_TYPE_INTEGER, 201 .name = "Blue", 202 .minimum = 0, 203 .maximum = 3, 204 .step = 1, 205#define BLUEBALANCE_DEF 1 206 .default_value = BLUEBALANCE_DEF, 207 }, 208 .set = sd_setbluebalance, 209 .get = sd_getbluebalance, 210 }, 211 { 212 { 213 .id = V4L2_CID_GAIN, 214 .type = V4L2_CTRL_TYPE_INTEGER, 215 .name = "Gain", 216 .minimum = 0, 217#define GAIN_MAX 255 218 .maximum = GAIN_MAX, 219 .step = 1, 220#define GAIN_DEF 127 221#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */ 222 .default_value = GAIN_DEF, 223 }, 224 .set = sd_setgain, 225 .get = sd_getgain, 226 }, 227 { 228 { 229 .id = V4L2_CID_EXPOSURE, 230 .type = V4L2_CTRL_TYPE_INTEGER, 231 .name = "Exposure", 232 .minimum = 0, 233 .maximum = 1023, 234 .step = 1, 235#define EXPOSURE_DEF 66 /* 33 ms / 30 fps */ 236#define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */ 237 .default_value = EXPOSURE_DEF, 238 }, 239 .set = sd_setexposure, 240 .get = sd_getexposure, 241 }, 242 { 243 { 244 .id = V4L2_CID_AUTOGAIN, 245 .type = V4L2_CTRL_TYPE_BOOLEAN, 246 .name = "Auto Gain", 247 .minimum = 0, 248 .maximum = 1, 249 .step = 1, 250#define AUTOGAIN_DEF 1 251 .default_value = AUTOGAIN_DEF, 252 }, 253 .set = sd_setautogain, 254 .get = sd_getautogain, 255 }, 256 { 257 { 258 .id = V4L2_CID_HFLIP, 259 .type = V4L2_CTRL_TYPE_BOOLEAN, 260 .name = "Mirror", 261 .minimum = 0, 262 .maximum = 1, 263 .step = 1, 264#define HFLIP_DEF 0 265 .default_value = HFLIP_DEF, 266 }, 267 .set = sd_sethflip, 268 .get = sd_gethflip, 269 }, 270 { 271 { 272 .id = V4L2_CID_VFLIP, 273 .type = V4L2_CTRL_TYPE_BOOLEAN, 274 .name = "Vflip", 275 .minimum = 0, 276 .maximum = 1, 277 .step = 1, 278#define VFLIP_DEF 0 279 .default_value = VFLIP_DEF, 280 }, 281 .set = sd_setvflip, 282 .get = sd_getvflip, 283 }, 284}; 285 286static const struct v4l2_pix_format vga_mode[] = { 287 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, 288 .bytesperline = 640, 289 .sizeimage = 640 * 480 * 3 / 8 + 590, 290 .colorspace = V4L2_COLORSPACE_JPEG, 291 .priv = 0}, 292}; 293 294#define LOAD_PAGE3 255 295#define END_OF_SEQUENCE 0 296 297/* pac 7302 */ 298static const __u8 init_7302[] = { 299/* index,value */ 300 0xff, 0x01, /* page 1 */ 301 0x78, 0x00, /* deactivate */ 302 0xff, 0x01, 303 0x78, 0x40, /* led off */ 304}; 305static const __u8 start_7302[] = { 306/* index, len, [value]* */ 307 0xff, 1, 0x00, /* page 0 */ 308 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, 309 0x00, 0x00, 0x00, 0x00, 310 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00, 311 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7, 312 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11, 313 0x26, 2, 0xaa, 0xaa, 314 0x2e, 1, 0x31, 315 0x38, 1, 0x01, 316 0x3a, 3, 0x14, 0xff, 0x5a, 317 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, 318 0x00, 0x54, 0x11, 319 0x55, 1, 0x00, 320 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, 321 0x6b, 1, 0x00, 322 0x6e, 3, 0x08, 0x06, 0x00, 323 0x72, 3, 0x00, 0xff, 0x00, 324 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c, 325 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50, 326 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00, 327 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9, 328 0xd2, 0xeb, 329 0xaf, 1, 0x02, 330 0xb5, 2, 0x08, 0x08, 331 0xb8, 2, 0x08, 0x88, 332 0xc4, 4, 0xae, 0x01, 0x04, 0x01, 333 0xcc, 1, 0x00, 334 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9, 335 0xc1, 0xd7, 0xec, 336 0xdc, 1, 0x01, 337 0xff, 1, 0x01, /* page 1 */ 338 0x12, 3, 0x02, 0x00, 0x01, 339 0x3e, 2, 0x00, 0x00, 340 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2, 341 0x7c, 1, 0x00, 342 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20, 343 0x02, 0x00, 344 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04, 345 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 346 0x07, 0x00, 0x01, 0x07, 0x04, 0x01, 347 0xd8, 1, 0x01, 348 0xdb, 2, 0x00, 0x01, 349 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, 350 0xe6, 4, 0x00, 0x00, 0x00, 0x01, 351 0xeb, 1, 0x00, 352 0xff, 1, 0x02, /* page 2 */ 353 0x22, 1, 0x00, 354 0xff, 1, 0x03, /* page 3 */ 355 0, LOAD_PAGE3, /* load the page 3 */ 356 0x11, 1, 0x01, 357 0xff, 1, 0x02, /* page 2 */ 358 0x13, 1, 0x00, 359 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96, 360 0x27, 2, 0x14, 0x0c, 361 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, 362 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, 363 0x6e, 1, 0x08, 364 0xff, 1, 0x01, /* page 1 */ 365 0x78, 1, 0x00, 366 0, END_OF_SEQUENCE /* end of sequence */ 367}; 368 369#define SKIP 0xaa 370/* page 3 - the value SKIP says skip the index - see reg_w_page() */ 371static const __u8 page3_7302[] = { 372 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16, 373 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, 374 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 375 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, 376 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21, 377 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54, 378 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, 379 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 380 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, 381 SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, 382 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 383 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, 384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 385 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8, 386 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 387 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 388 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00, 389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 390 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00, 391 0x00 392}; 393 394static void reg_w_buf(struct gspca_dev *gspca_dev, 395 __u8 index, 396 const u8 *buffer, int len) 397{ 398 int ret; 399 400 if (gspca_dev->usb_err < 0) 401 return; 402 memcpy(gspca_dev->usb_buf, buffer, len); 403 ret = usb_control_msg(gspca_dev->dev, 404 usb_sndctrlpipe(gspca_dev->dev, 0), 405 0, /* request */ 406 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 407 0, /* value */ 408 index, gspca_dev->usb_buf, len, 409 500); 410 if (ret < 0) { 411 err("reg_w_buf failed index 0x%02x, error %d", 412 index, ret); 413 gspca_dev->usb_err = ret; 414 } 415} 416 417 418static void reg_w(struct gspca_dev *gspca_dev, 419 __u8 index, 420 __u8 value) 421{ 422 int ret; 423 424 if (gspca_dev->usb_err < 0) 425 return; 426 gspca_dev->usb_buf[0] = value; 427 ret = usb_control_msg(gspca_dev->dev, 428 usb_sndctrlpipe(gspca_dev->dev, 0), 429 0, /* request */ 430 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 431 0, index, gspca_dev->usb_buf, 1, 432 500); 433 if (ret < 0) { 434 err("reg_w() failed index 0x%02x, value 0x%02x, error %d", 435 index, value, ret); 436 gspca_dev->usb_err = ret; 437 } 438} 439 440static void reg_w_seq(struct gspca_dev *gspca_dev, 441 const __u8 *seq, int len) 442{ 443 while (--len >= 0) { 444 reg_w(gspca_dev, seq[0], seq[1]); 445 seq += 2; 446 } 447} 448 449/* load the beginning of a page */ 450static void reg_w_page(struct gspca_dev *gspca_dev, 451 const __u8 *page, int len) 452{ 453 int index; 454 int ret = 0; 455 456 if (gspca_dev->usb_err < 0) 457 return; 458 for (index = 0; index < len; index++) { 459 if (page[index] == SKIP) /* skip this index */ 460 continue; 461 gspca_dev->usb_buf[0] = page[index]; 462 ret = usb_control_msg(gspca_dev->dev, 463 usb_sndctrlpipe(gspca_dev->dev, 0), 464 0, /* request */ 465 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 466 0, index, gspca_dev->usb_buf, 1, 467 500); 468 if (ret < 0) { 469 err("reg_w_page() failed index 0x%02x, " 470 "value 0x%02x, error %d", 471 index, page[index], ret); 472 gspca_dev->usb_err = ret; 473 break; 474 } 475 } 476} 477 478/* output a variable sequence */ 479static void reg_w_var(struct gspca_dev *gspca_dev, 480 const __u8 *seq, 481 const __u8 *page3, unsigned int page3_len) 482{ 483 int index, len; 484 485 for (;;) { 486 index = *seq++; 487 len = *seq++; 488 switch (len) { 489 case END_OF_SEQUENCE: 490 return; 491 case LOAD_PAGE3: 492 reg_w_page(gspca_dev, page3, page3_len); 493 break; 494 default: 495 if (len > USB_BUF_SZ) { 496 PDEBUG(D_ERR|D_STREAM, 497 "Incorrect variable sequence"); 498 return; 499 } 500 while (len > 0) { 501 if (len < 8) { 502 reg_w_buf(gspca_dev, 503 index, seq, len); 504 seq += len; 505 break; 506 } 507 reg_w_buf(gspca_dev, index, seq, 8); 508 seq += 8; 509 index += 8; 510 len -= 8; 511 } 512 } 513 } 514 /* not reached */ 515} 516 517/* this function is called at probe time for pac7302 */ 518static int sd_config(struct gspca_dev *gspca_dev, 519 const struct usb_device_id *id) 520{ 521 struct sd *sd = (struct sd *) gspca_dev; 522 struct cam *cam; 523 524 cam = &gspca_dev->cam; 525 526 PDEBUG(D_CONF, "Find Sensor PAC7302"); 527 cam->cam_mode = vga_mode; /* only 640x480 */ 528 cam->nmodes = ARRAY_SIZE(vga_mode); 529 530 sd->brightness = BRIGHTNESS_DEF; 531 sd->contrast = CONTRAST_DEF; 532 sd->colors = COLOR_DEF; 533 sd->white_balance = WHITEBALANCE_DEF; 534 sd->red_balance = REDBALANCE_DEF; 535 sd->blue_balance = BLUEBALANCE_DEF; 536 sd->gain = GAIN_DEF; 537 sd->exposure = EXPOSURE_DEF; 538 sd->autogain = AUTOGAIN_DEF; 539 sd->hflip = HFLIP_DEF; 540 sd->vflip = VFLIP_DEF; 541 sd->flags = id->driver_info; 542 return 0; 543} 544 545/* This function is used by pac7302 only */ 546static void setbrightcont(struct gspca_dev *gspca_dev) 547{ 548 struct sd *sd = (struct sd *) gspca_dev; 549 int i, v; 550 static const __u8 max[10] = 551 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, 552 0xd4, 0xec}; 553 static const __u8 delta[10] = 554 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, 555 0x11, 0x0b}; 556 557 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ 558 for (i = 0; i < 10; i++) { 559 v = max[i]; 560 v += (sd->brightness - BRIGHTNESS_MAX) 561 * 150 / BRIGHTNESS_MAX; /* 200 ? */ 562 v -= delta[i] * sd->contrast / CONTRAST_MAX; 563 if (v < 0) 564 v = 0; 565 else if (v > 0xff) 566 v = 0xff; 567 reg_w(gspca_dev, 0xa2 + i, v); 568 } 569 reg_w(gspca_dev, 0xdc, 0x01); 570} 571 572/* This function is used by pac7302 only */ 573static void setcolors(struct gspca_dev *gspca_dev) 574{ 575 struct sd *sd = (struct sd *) gspca_dev; 576 int i, v; 577 static const int a[9] = 578 {217, -212, 0, -101, 170, -67, -38, -315, 355}; 579 static const int b[9] = 580 {19, 106, 0, 19, 106, 1, 19, 106, 1}; 581 582 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 583 reg_w(gspca_dev, 0x11, 0x01); 584 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ 585 for (i = 0; i < 9; i++) { 586 v = a[i] * sd->colors / COLOR_MAX + b[i]; 587 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); 588 reg_w(gspca_dev, 0x0f + 2 * i + 1, v); 589 } 590 reg_w(gspca_dev, 0xdc, 0x01); 591 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); 592} 593 594static void setwhitebalance(struct gspca_dev *gspca_dev) 595{ 596 struct sd *sd = (struct sd *) gspca_dev; 597 598 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ 599 reg_w(gspca_dev, 0xc6, sd->white_balance); 600 601 reg_w(gspca_dev, 0xdc, 0x01); 602 PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance); 603} 604 605static void setredbalance(struct gspca_dev *gspca_dev) 606{ 607 struct sd *sd = (struct sd *) gspca_dev; 608 609 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ 610 reg_w(gspca_dev, 0xc5, sd->red_balance); 611 612 reg_w(gspca_dev, 0xdc, 0x01); 613 PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance); 614} 615 616static void setbluebalance(struct gspca_dev *gspca_dev) 617{ 618 struct sd *sd = (struct sd *) gspca_dev; 619 620 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ 621 reg_w(gspca_dev, 0xc7, sd->blue_balance); 622 623 reg_w(gspca_dev, 0xdc, 0x01); 624 PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance); 625} 626 627static void setgain(struct gspca_dev *gspca_dev) 628{ 629 struct sd *sd = (struct sd *) gspca_dev; 630 631 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 632 reg_w(gspca_dev, 0x10, sd->gain >> 3); 633 634 /* load registers to sensor (Bit 0, auto clear) */ 635 reg_w(gspca_dev, 0x11, 0x01); 636} 637 638static void setexposure(struct gspca_dev *gspca_dev) 639{ 640 struct sd *sd = (struct sd *) gspca_dev; 641 __u8 clockdiv; 642 __u16 exposure; 643 644 /* register 2 of frame 3 contains the clock divider configuring the 645 no fps according to the formula: 90 / reg. sd->exposure is the 646 desired exposure time in 0.5 ms. */ 647 clockdiv = (90 * sd->exposure + 1999) / 2000; 648 649 /* Note clockdiv = 3 also works, but when running at 30 fps, depending 650 on the scene being recorded, the camera switches to another 651 quantization table for certain JPEG blocks, and we don't know how 652 to decompress these blocks. So we cap the framerate at 15 fps */ 653 if (clockdiv < 6) 654 clockdiv = 6; 655 else if (clockdiv > 63) 656 clockdiv = 63; 657 658 /* reg2 MUST be a multiple of 3, except when between 6 and 12? 659 Always round up, otherwise we cannot get the desired frametime 660 using the partial frame time exposure control */ 661 if (clockdiv < 6 || clockdiv > 12) 662 clockdiv = ((clockdiv + 2) / 3) * 3; 663 664 /* frame exposure time in ms = 1000 * clockdiv / 90 -> 665 exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */ 666 exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv); 667 /* 0 = use full frametime, 448 = no exposure, reverse it */ 668 exposure = 448 - exposure; 669 670 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 671 reg_w(gspca_dev, 0x02, clockdiv); 672 reg_w(gspca_dev, 0x0e, exposure & 0xff); 673 reg_w(gspca_dev, 0x0f, exposure >> 8); 674 675 /* load registers to sensor (Bit 0, auto clear) */ 676 reg_w(gspca_dev, 0x11, 0x01); 677} 678 679static void sethvflip(struct gspca_dev *gspca_dev) 680{ 681 struct sd *sd = (struct sd *) gspca_dev; 682 u8 data, hflip, vflip; 683 684 hflip = sd->hflip; 685 if (sd->flags & FL_HFLIP) 686 hflip = !hflip; 687 vflip = sd->vflip; 688 if (sd->flags & FL_VFLIP) 689 vflip = !vflip; 690 691 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 692 data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00); 693 reg_w(gspca_dev, 0x21, data); 694 695 /* load registers to sensor (Bit 0, auto clear) */ 696 reg_w(gspca_dev, 0x11, 0x01); 697} 698 699/* this function is called at probe and resume time for pac7302 */ 700static int sd_init(struct gspca_dev *gspca_dev) 701{ 702 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2); 703 return gspca_dev->usb_err; 704} 705 706static int sd_start(struct gspca_dev *gspca_dev) 707{ 708 struct sd *sd = (struct sd *) gspca_dev; 709 710 sd->sof_read = 0; 711 712 reg_w_var(gspca_dev, start_7302, 713 page3_7302, sizeof(page3_7302)); 714 setbrightcont(gspca_dev); 715 setcolors(gspca_dev); 716 setwhitebalance(gspca_dev); 717 setredbalance(gspca_dev); 718 setbluebalance(gspca_dev); 719 setgain(gspca_dev); 720 setexposure(gspca_dev); 721 sethvflip(gspca_dev); 722 723 /* only resolution 640x480 is supported for pac7302 */ 724 725 sd->sof_read = 0; 726 sd->autogain_ignore_frames = 0; 727 atomic_set(&sd->avg_lum, -1); 728 729 /* start stream */ 730 reg_w(gspca_dev, 0xff, 0x01); 731 reg_w(gspca_dev, 0x78, 0x01); 732 733 return gspca_dev->usb_err; 734} 735 736static void sd_stopN(struct gspca_dev *gspca_dev) 737{ 738 739 /* stop stream */ 740 reg_w(gspca_dev, 0xff, 0x01); 741 reg_w(gspca_dev, 0x78, 0x00); 742} 743 744/* called on streamoff with alt 0 and on disconnect for pac7302 */ 745static void sd_stop0(struct gspca_dev *gspca_dev) 746{ 747 if (!gspca_dev->present) 748 return; 749 reg_w(gspca_dev, 0xff, 0x01); 750 reg_w(gspca_dev, 0x78, 0x40); 751} 752 753/* Include pac common sof detection functions */ 754#include "pac_common.h" 755 756static void do_autogain(struct gspca_dev *gspca_dev) 757{ 758 struct sd *sd = (struct sd *) gspca_dev; 759 int avg_lum = atomic_read(&sd->avg_lum); 760 int desired_lum; 761 const int deadzone = 30; 762 763 if (avg_lum == -1) 764 return; 765 766 desired_lum = 270 + sd->brightness; 767 768 if (sd->autogain_ignore_frames > 0) 769 sd->autogain_ignore_frames--; 770 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, 771 deadzone, GAIN_KNEE, EXPOSURE_KNEE)) 772 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; 773} 774 775/* JPEG header, part 1 */ 776static const unsigned char pac_jpeg_header1[] = { 777 0xff, 0xd8, /* SOI: Start of Image */ 778 779 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ 780 0x00, 0x11, /* length = 17 bytes (including this length field) */ 781 0x08 /* Precision: 8 */ 782 /* 2 bytes is placed here: number of image lines */ 783 /* 2 bytes is placed here: samples per line */ 784}; 785 786/* JPEG header, continued */ 787static const unsigned char pac_jpeg_header2[] = { 788 0x03, /* Number of image components: 3 */ 789 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ 790 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ 791 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ 792 793 0xff, 0xda, /* SOS: Start Of Scan */ 794 0x00, 0x0c, /* length = 12 bytes (including this length field) */ 795 0x03, /* number of components: 3 */ 796 0x01, 0x00, /* selector 1, table 0x00 */ 797 0x02, 0x11, /* selector 2, table 0x11 */ 798 0x03, 0x11, /* selector 3, table 0x11 */ 799 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ 800 0x00 /* Successive approximation: 0 */ 801}; 802 803static void pac_start_frame(struct gspca_dev *gspca_dev, 804 __u16 lines, __u16 samples_per_line) 805{ 806 unsigned char tmpbuf[4]; 807 808 gspca_frame_add(gspca_dev, FIRST_PACKET, 809 pac_jpeg_header1, sizeof(pac_jpeg_header1)); 810 811 tmpbuf[0] = lines >> 8; 812 tmpbuf[1] = lines & 0xff; 813 tmpbuf[2] = samples_per_line >> 8; 814 tmpbuf[3] = samples_per_line & 0xff; 815 816 gspca_frame_add(gspca_dev, INTER_PACKET, 817 tmpbuf, sizeof(tmpbuf)); 818 gspca_frame_add(gspca_dev, INTER_PACKET, 819 pac_jpeg_header2, sizeof(pac_jpeg_header2)); 820} 821 822/* this function is run at interrupt level */ 823static void sd_pkt_scan(struct gspca_dev *gspca_dev, 824 u8 *data, /* isoc packet */ 825 int len) /* iso packet length */ 826{ 827 struct sd *sd = (struct sd *) gspca_dev; 828 u8 *image; 829 unsigned char *sof; 830 831 sof = pac_find_sof(&sd->sof_read, data, len); 832 if (sof) { 833 int n, lum_offset, footer_length; 834 835 /* 6 bytes after the FF D9 EOF marker a number of lumination 836 bytes are send corresponding to different parts of the 837 image, the 14th and 15th byte after the EOF seem to 838 correspond to the center of the image */ 839 lum_offset = 61 + sizeof pac_sof_marker; 840 footer_length = 74; 841 842 /* Finish decoding current frame */ 843 n = (sof - data) - (footer_length + sizeof pac_sof_marker); 844 if (n < 0) { 845 gspca_dev->image_len += n; 846 n = 0; 847 } else { 848 gspca_frame_add(gspca_dev, INTER_PACKET, data, n); 849 } 850 851 image = gspca_dev->image; 852 if (image != NULL 853 && image[gspca_dev->image_len - 2] == 0xff 854 && image[gspca_dev->image_len - 1] == 0xd9) 855 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 856 857 n = sof - data; 858 len -= n; 859 data = sof; 860 861 /* Get average lumination */ 862 if (gspca_dev->last_packet_type == LAST_PACKET && 863 n >= lum_offset) 864 atomic_set(&sd->avg_lum, data[-lum_offset] + 865 data[-lum_offset + 1]); 866 else 867 atomic_set(&sd->avg_lum, -1); 868 869 /* Start the new frame with the jpeg header */ 870 /* The PAC7302 has the image rotated 90 degrees */ 871 pac_start_frame(gspca_dev, 872 gspca_dev->width, gspca_dev->height); 873 } 874 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 875} 876 877static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 878{ 879 struct sd *sd = (struct sd *) gspca_dev; 880 881 sd->brightness = val; 882 if (gspca_dev->streaming) 883 setbrightcont(gspca_dev); 884 return gspca_dev->usb_err; 885} 886 887static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) 888{ 889 struct sd *sd = (struct sd *) gspca_dev; 890 891 *val = sd->brightness; 892 return 0; 893} 894 895static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) 896{ 897 struct sd *sd = (struct sd *) gspca_dev; 898 899 sd->contrast = val; 900 if (gspca_dev->streaming) 901 setbrightcont(gspca_dev); 902 return gspca_dev->usb_err; 903} 904 905static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) 906{ 907 struct sd *sd = (struct sd *) gspca_dev; 908 909 *val = sd->contrast; 910 return 0; 911} 912 913static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) 914{ 915 struct sd *sd = (struct sd *) gspca_dev; 916 917 sd->colors = val; 918 if (gspca_dev->streaming) 919 setcolors(gspca_dev); 920 return gspca_dev->usb_err; 921} 922 923static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) 924{ 925 struct sd *sd = (struct sd *) gspca_dev; 926 927 *val = sd->colors; 928 return 0; 929} 930 931static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val) 932{ 933 struct sd *sd = (struct sd *) gspca_dev; 934 935 sd->white_balance = val; 936 if (gspca_dev->streaming) 937 setwhitebalance(gspca_dev); 938 return gspca_dev->usb_err; 939} 940 941static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) 942{ 943 struct sd *sd = (struct sd *) gspca_dev; 944 945 *val = sd->white_balance; 946 return 0; 947} 948 949static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val) 950{ 951 struct sd *sd = (struct sd *) gspca_dev; 952 953 sd->red_balance = val; 954 if (gspca_dev->streaming) 955 setredbalance(gspca_dev); 956 return gspca_dev->usb_err; 957} 958 959static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) 960{ 961 struct sd *sd = (struct sd *) gspca_dev; 962 963 *val = sd->red_balance; 964 return 0; 965} 966 967static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val) 968{ 969 struct sd *sd = (struct sd *) gspca_dev; 970 971 sd->blue_balance = val; 972 if (gspca_dev->streaming) 973 setbluebalance(gspca_dev); 974 return gspca_dev->usb_err; 975} 976 977static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val) 978{ 979 struct sd *sd = (struct sd *) gspca_dev; 980 981 *val = sd->blue_balance; 982 return 0; 983} 984 985static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) 986{ 987 struct sd *sd = (struct sd *) gspca_dev; 988 989 sd->gain = val; 990 if (gspca_dev->streaming) 991 setgain(gspca_dev); 992 return gspca_dev->usb_err; 993} 994 995static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) 996{ 997 struct sd *sd = (struct sd *) gspca_dev; 998 999 *val = sd->gain; 1000 return 0; 1001} 1002 1003static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) 1004{ 1005 struct sd *sd = (struct sd *) gspca_dev; 1006 1007 sd->exposure = val; 1008 if (gspca_dev->streaming) 1009 setexposure(gspca_dev); 1010 return gspca_dev->usb_err; 1011} 1012 1013static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) 1014{ 1015 struct sd *sd = (struct sd *) gspca_dev; 1016 1017 *val = sd->exposure; 1018 return 0; 1019} 1020 1021static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) 1022{ 1023 struct sd *sd = (struct sd *) gspca_dev; 1024 1025 sd->autogain = val; 1026 /* when switching to autogain set defaults to make sure 1027 we are on a valid point of the autogain gain / 1028 exposure knee graph, and give this change time to 1029 take effect before doing autogain. */ 1030 if (sd->autogain) { 1031 sd->exposure = EXPOSURE_DEF; 1032 sd->gain = GAIN_DEF; 1033 if (gspca_dev->streaming) { 1034 sd->autogain_ignore_frames = 1035 PAC_AUTOGAIN_IGNORE_FRAMES; 1036 setexposure(gspca_dev); 1037 setgain(gspca_dev); 1038 } 1039 } 1040 1041 return gspca_dev->usb_err; 1042} 1043 1044static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) 1045{ 1046 struct sd *sd = (struct sd *) gspca_dev; 1047 1048 *val = sd->autogain; 1049 return 0; 1050} 1051 1052static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) 1053{ 1054 struct sd *sd = (struct sd *) gspca_dev; 1055 1056 sd->hflip = val; 1057 if (gspca_dev->streaming) 1058 sethvflip(gspca_dev); 1059 return gspca_dev->usb_err; 1060} 1061 1062static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) 1063{ 1064 struct sd *sd = (struct sd *) gspca_dev; 1065 1066 *val = sd->hflip; 1067 return 0; 1068} 1069 1070static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) 1071{ 1072 struct sd *sd = (struct sd *) gspca_dev; 1073 1074 sd->vflip = val; 1075 if (gspca_dev->streaming) 1076 sethvflip(gspca_dev); 1077 return gspca_dev->usb_err; 1078} 1079 1080static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) 1081{ 1082 struct sd *sd = (struct sd *) gspca_dev; 1083 1084 *val = sd->vflip; 1085 return 0; 1086} 1087 1088#ifdef CONFIG_VIDEO_ADV_DEBUG 1089static int sd_dbg_s_register(struct gspca_dev *gspca_dev, 1090 struct v4l2_dbg_register *reg) 1091{ 1092 __u8 index; 1093 __u8 value; 1094 1095 /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit 1096 long on the USB bus) 1097 */ 1098 if (reg->match.type == V4L2_CHIP_MATCH_HOST && 1099 reg->match.addr == 0 && 1100 (reg->reg < 0x000000ff) && 1101 (reg->val <= 0x000000ff) 1102 ) { 1103 /* Currently writing to page 0 is only supported. */ 1104 /* reg_w() only supports 8bit index */ 1105 index = reg->reg & 0x000000ff; 1106 value = reg->val & 0x000000ff; 1107 1108 /* Note that there shall be no access to other page 1109 by any other function between the page swith and 1110 the actual register write */ 1111 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ 1112 reg_w(gspca_dev, index, value); 1113 1114 reg_w(gspca_dev, 0xdc, 0x01); 1115 } 1116 return gspca_dev->usb_err; 1117} 1118 1119static int sd_chip_ident(struct gspca_dev *gspca_dev, 1120 struct v4l2_dbg_chip_ident *chip) 1121{ 1122 int ret = -EINVAL; 1123 1124 if (chip->match.type == V4L2_CHIP_MATCH_HOST && 1125 chip->match.addr == 0) { 1126 chip->revision = 0; 1127 chip->ident = V4L2_IDENT_UNKNOWN; 1128 ret = 0; 1129 } 1130 return ret; 1131} 1132#endif 1133 1134#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) 1135static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, 1136 u8 *data, /* interrupt packet data */ 1137 int len) /* interrput packet length */ 1138{ 1139 int ret = -EINVAL; 1140 u8 data0, data1; 1141 1142 if (len == 2) { 1143 data0 = data[0]; 1144 data1 = data[1]; 1145 if ((data0 == 0x00 && data1 == 0x11) || 1146 (data0 == 0x22 && data1 == 0x33) || 1147 (data0 == 0x44 && data1 == 0x55) || 1148 (data0 == 0x66 && data1 == 0x77) || 1149 (data0 == 0x88 && data1 == 0x99) || 1150 (data0 == 0xaa && data1 == 0xbb) || 1151 (data0 == 0xcc && data1 == 0xdd) || 1152 (data0 == 0xee && data1 == 0xff)) { 1153 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); 1154 input_sync(gspca_dev->input_dev); 1155 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); 1156 input_sync(gspca_dev->input_dev); 1157 ret = 0; 1158 } 1159 } 1160 1161 return ret; 1162} 1163#endif 1164 1165/* sub-driver description for pac7302 */ 1166static const struct sd_desc sd_desc = { 1167 .name = MODULE_NAME, 1168 .ctrls = sd_ctrls, 1169 .nctrls = ARRAY_SIZE(sd_ctrls), 1170 .config = sd_config, 1171 .init = sd_init, 1172 .start = sd_start, 1173 .stopN = sd_stopN, 1174 .stop0 = sd_stop0, 1175 .pkt_scan = sd_pkt_scan, 1176 .dq_callback = do_autogain, 1177#ifdef CONFIG_VIDEO_ADV_DEBUG 1178 .set_register = sd_dbg_s_register, 1179 .get_chip_ident = sd_chip_ident, 1180#endif 1181#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) 1182 .int_pkt_scan = sd_int_pkt_scan, 1183#endif 1184}; 1185 1186/* -- module initialisation -- */ 1187static const struct usb_device_id device_table[] = { 1188 {USB_DEVICE(0x06f8, 0x3009)}, 1189 {USB_DEVICE(0x093a, 0x2620)}, 1190 {USB_DEVICE(0x093a, 0x2621)}, 1191 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP}, 1192 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP}, 1193 {USB_DEVICE(0x093a, 0x2625)}, 1194 {USB_DEVICE(0x093a, 0x2626)}, 1195 {USB_DEVICE(0x093a, 0x2628)}, 1196 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP}, 1197 {USB_DEVICE(0x093a, 0x262a)}, 1198 {USB_DEVICE(0x093a, 0x262c)}, 1199 {} 1200}; 1201MODULE_DEVICE_TABLE(usb, device_table); 1202 1203/* -- device connect -- */ 1204static int sd_probe(struct usb_interface *intf, 1205 const struct usb_device_id *id) 1206{ 1207 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 1208 THIS_MODULE); 1209} 1210 1211static struct usb_driver sd_driver = { 1212 .name = MODULE_NAME, 1213 .id_table = device_table, 1214 .probe = sd_probe, 1215 .disconnect = gspca_disconnect, 1216#ifdef CONFIG_PM 1217 .suspend = gspca_suspend, 1218 .resume = gspca_resume, 1219#endif 1220}; 1221 1222/* -- module insert / remove -- */ 1223static int __init sd_mod_init(void) 1224{ 1225 return usb_register(&sd_driver); 1226} 1227static void __exit sd_mod_exit(void) 1228{ 1229 usb_deregister(&sd_driver); 1230} 1231 1232module_init(sd_mod_init); 1233module_exit(sd_mod_exit); 1234