pac7302.c revision 1408b8472910e894b290205b4baed5b14b8f45af
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 <nm127@freemail.hu> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23 24/* Some documentation about various registers as determined by trial and error. 25 When the register addresses differ between the 7202 and the 7311 the 2 26 different addresses are written as 7302addr/7311addr, when one of the 2 27 addresses is a - sign that register description is not valid for the 28 matching IC. 29 30 Register page 1: 31 32 Address Description 33 -/0x08 Unknown compressor related, must always be 8 except when not 34 in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 ! 35 -/0x1b Auto white balance related, bit 0 is AWB enable (inverted) 36 bits 345 seem to toggle per color gains on/off (inverted) 37 0x78 Global control, bit 6 controls the LED (inverted) 38 -/0x80 JPEG compression ratio ? Best not touched 39 40 Register page 3/4: 41 42 Address Description 43 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on 44 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? 45 -/0x0f Master gain 1-245, low value = high gain 46 0x10/- Master gain 0-31 47 -/0x10 Another gain 0-15, limited influence (1-2x gain I guess) 48 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused 49 -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to 50 completely disable the analog amplification block. Set to 0x68 51 for max gain, 0x14 for minimal gain. 52*/ 53 54#define MODULE_NAME "pac7302" 55 56#include "gspca.h" 57 58MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); 59MODULE_DESCRIPTION("Pixart PAC7302"); 60MODULE_LICENSE("GPL"); 61 62/* specific webcam descriptor for pac7302 */ 63struct sd { 64 struct gspca_dev gspca_dev; /* !! must be the first item */ 65 66 unsigned char brightness; 67 unsigned char contrast; 68 unsigned char colors; 69 unsigned char gain; 70 unsigned char exposure; 71 unsigned char autogain; 72 __u8 hflip; 73 __u8 vflip; 74 75 u8 sof_read; 76 u8 autogain_ignore_frames; 77 78 atomic_t avg_lum; 79}; 80 81/* V4L2 controls supported by the driver */ 82static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); 83static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); 84static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); 85static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); 86static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); 87static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); 88static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); 89static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); 90static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); 91static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); 92static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); 93static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); 94static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); 95static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); 96static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); 97static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); 98 99static struct ctrl sd_ctrls[] = { 100/* This control is pac7302 only */ 101 { 102 { 103 .id = V4L2_CID_BRIGHTNESS, 104 .type = V4L2_CTRL_TYPE_INTEGER, 105 .name = "Brightness", 106 .minimum = 0, 107#define BRIGHTNESS_MAX 0x20 108 .maximum = BRIGHTNESS_MAX, 109 .step = 1, 110#define BRIGHTNESS_DEF 0x10 111 .default_value = BRIGHTNESS_DEF, 112 }, 113 .set = sd_setbrightness, 114 .get = sd_getbrightness, 115 }, 116/* This control is for both the 7302 and the 7311 */ 117 { 118 { 119 .id = V4L2_CID_CONTRAST, 120 .type = V4L2_CTRL_TYPE_INTEGER, 121 .name = "Contrast", 122 .minimum = 0, 123#define CONTRAST_MAX 255 124 .maximum = CONTRAST_MAX, 125 .step = 1, 126#define CONTRAST_DEF 127 127 .default_value = CONTRAST_DEF, 128 }, 129 .set = sd_setcontrast, 130 .get = sd_getcontrast, 131 }, 132/* This control is pac7302 only */ 133 { 134 { 135 .id = V4L2_CID_SATURATION, 136 .type = V4L2_CTRL_TYPE_INTEGER, 137 .name = "Saturation", 138 .minimum = 0, 139#define COLOR_MAX 255 140 .maximum = COLOR_MAX, 141 .step = 1, 142#define COLOR_DEF 127 143 .default_value = COLOR_DEF, 144 }, 145 .set = sd_setcolors, 146 .get = sd_getcolors, 147 }, 148/* All controls below are for both the 7302 and the 7311 */ 149 { 150 { 151 .id = V4L2_CID_GAIN, 152 .type = V4L2_CTRL_TYPE_INTEGER, 153 .name = "Gain", 154 .minimum = 0, 155#define GAIN_MAX 255 156 .maximum = GAIN_MAX, 157 .step = 1, 158#define GAIN_DEF 127 159#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */ 160 .default_value = GAIN_DEF, 161 }, 162 .set = sd_setgain, 163 .get = sd_getgain, 164 }, 165 { 166 { 167 .id = V4L2_CID_EXPOSURE, 168 .type = V4L2_CTRL_TYPE_INTEGER, 169 .name = "Exposure", 170 .minimum = 0, 171#define EXPOSURE_MAX 255 172 .maximum = EXPOSURE_MAX, 173 .step = 1, 174#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */ 175#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */ 176 .default_value = EXPOSURE_DEF, 177 }, 178 .set = sd_setexposure, 179 .get = sd_getexposure, 180 }, 181 { 182 { 183 .id = V4L2_CID_AUTOGAIN, 184 .type = V4L2_CTRL_TYPE_BOOLEAN, 185 .name = "Auto Gain", 186 .minimum = 0, 187 .maximum = 1, 188 .step = 1, 189#define AUTOGAIN_DEF 1 190 .default_value = AUTOGAIN_DEF, 191 }, 192 .set = sd_setautogain, 193 .get = sd_getautogain, 194 }, 195 { 196 { 197 .id = V4L2_CID_HFLIP, 198 .type = V4L2_CTRL_TYPE_BOOLEAN, 199 .name = "Mirror", 200 .minimum = 0, 201 .maximum = 1, 202 .step = 1, 203#define HFLIP_DEF 0 204 .default_value = HFLIP_DEF, 205 }, 206 .set = sd_sethflip, 207 .get = sd_gethflip, 208 }, 209 { 210 { 211 .id = V4L2_CID_VFLIP, 212 .type = V4L2_CTRL_TYPE_BOOLEAN, 213 .name = "Vflip", 214 .minimum = 0, 215 .maximum = 1, 216 .step = 1, 217#define VFLIP_DEF 0 218 .default_value = VFLIP_DEF, 219 }, 220 .set = sd_setvflip, 221 .get = sd_getvflip, 222 }, 223}; 224 225static const struct v4l2_pix_format vga_mode[] = { 226 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, 227 .bytesperline = 640, 228 .sizeimage = 640 * 480 * 3 / 8 + 590, 229 .colorspace = V4L2_COLORSPACE_JPEG, 230 .priv = 0}, 231}; 232 233#define LOAD_PAGE3 255 234#define LOAD_PAGE4 254 235#define END_OF_SEQUENCE 0 236 237/* pac 7302 */ 238static const __u8 init_7302[] = { 239/* index,value */ 240 0xff, 0x01, /* page 1 */ 241 0x78, 0x00, /* deactivate */ 242 0xff, 0x01, 243 0x78, 0x40, /* led off */ 244}; 245static const __u8 start_7302[] = { 246/* index, len, [value]* */ 247 0xff, 1, 0x00, /* page 0 */ 248 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, 249 0x00, 0x00, 0x00, 0x00, 250 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00, 251 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7, 252 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11, 253 0x26, 2, 0xaa, 0xaa, 254 0x2e, 1, 0x31, 255 0x38, 1, 0x01, 256 0x3a, 3, 0x14, 0xff, 0x5a, 257 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, 258 0x00, 0x54, 0x11, 259 0x55, 1, 0x00, 260 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, 261 0x6b, 1, 0x00, 262 0x6e, 3, 0x08, 0x06, 0x00, 263 0x72, 3, 0x00, 0xff, 0x00, 264 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c, 265 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50, 266 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00, 267 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9, 268 0xd2, 0xeb, 269 0xaf, 1, 0x02, 270 0xb5, 2, 0x08, 0x08, 271 0xb8, 2, 0x08, 0x88, 272 0xc4, 4, 0xae, 0x01, 0x04, 0x01, 273 0xcc, 1, 0x00, 274 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9, 275 0xc1, 0xd7, 0xec, 276 0xdc, 1, 0x01, 277 0xff, 1, 0x01, /* page 1 */ 278 0x12, 3, 0x02, 0x00, 0x01, 279 0x3e, 2, 0x00, 0x00, 280 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2, 281 0x7c, 1, 0x00, 282 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20, 283 0x02, 0x00, 284 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04, 285 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 286 0x07, 0x00, 0x01, 0x07, 0x04, 0x01, 287 0xd8, 1, 0x01, 288 0xdb, 2, 0x00, 0x01, 289 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, 290 0xe6, 4, 0x00, 0x00, 0x00, 0x01, 291 0xeb, 1, 0x00, 292 0xff, 1, 0x02, /* page 2 */ 293 0x22, 1, 0x00, 294 0xff, 1, 0x03, /* page 3 */ 295 0, LOAD_PAGE3, /* load the page 3 */ 296 0x11, 1, 0x01, 297 0xff, 1, 0x02, /* page 2 */ 298 0x13, 1, 0x00, 299 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96, 300 0x27, 2, 0x14, 0x0c, 301 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, 302 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, 303 0x6e, 1, 0x08, 304 0xff, 1, 0x01, /* page 1 */ 305 0x78, 1, 0x00, 306 0, END_OF_SEQUENCE /* end of sequence */ 307}; 308 309#define SKIP 0xaa 310/* page 3 - the value SKIP says skip the index - see reg_w_page() */ 311static const __u8 page3_7302[] = { 312 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16, 313 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, 314 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 315 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, 316 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21, 317 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54, 318 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, 319 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 320 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, 321 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, 322 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 323 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, 324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 325 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8, 326 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 327 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 328 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00, 329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 330 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00, 331 0x00 332}; 333 334static void reg_w_buf(struct gspca_dev *gspca_dev, 335 __u8 index, 336 const char *buffer, int len) 337{ 338 memcpy(gspca_dev->usb_buf, buffer, len); 339 usb_control_msg(gspca_dev->dev, 340 usb_sndctrlpipe(gspca_dev->dev, 0), 341 1, /* request */ 342 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 343 0, /* value */ 344 index, gspca_dev->usb_buf, len, 345 500); 346} 347 348 349static void reg_w(struct gspca_dev *gspca_dev, 350 __u8 index, 351 __u8 value) 352{ 353 gspca_dev->usb_buf[0] = value; 354 usb_control_msg(gspca_dev->dev, 355 usb_sndctrlpipe(gspca_dev->dev, 0), 356 0, /* request */ 357 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 358 0, index, gspca_dev->usb_buf, 1, 359 500); 360} 361 362static void reg_w_seq(struct gspca_dev *gspca_dev, 363 const __u8 *seq, int len) 364{ 365 while (--len >= 0) { 366 reg_w(gspca_dev, seq[0], seq[1]); 367 seq += 2; 368 } 369} 370 371/* load the beginning of a page */ 372static void reg_w_page(struct gspca_dev *gspca_dev, 373 const __u8 *page, int len) 374{ 375 int index; 376 377 for (index = 0; index < len; index++) { 378 if (page[index] == SKIP) /* skip this index */ 379 continue; 380 gspca_dev->usb_buf[0] = page[index]; 381 usb_control_msg(gspca_dev->dev, 382 usb_sndctrlpipe(gspca_dev->dev, 0), 383 0, /* request */ 384 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 385 0, index, gspca_dev->usb_buf, 1, 386 500); 387 } 388} 389 390/* output a variable sequence */ 391static void reg_w_var(struct gspca_dev *gspca_dev, 392 const __u8 *seq, 393 const __u8 *page3, unsigned int page3_len, 394 const __u8 *page4, unsigned int page4_len) 395{ 396 int index, len; 397 398 for (;;) { 399 index = *seq++; 400 len = *seq++; 401 switch (len) { 402 case END_OF_SEQUENCE: 403 return; 404 case LOAD_PAGE4: 405 reg_w_page(gspca_dev, page4, page4_len); 406 break; 407 case LOAD_PAGE3: 408 reg_w_page(gspca_dev, page3, page3_len); 409 break; 410 default: 411 if (len > USB_BUF_SZ) { 412 PDEBUG(D_ERR|D_STREAM, 413 "Incorrect variable sequence"); 414 return; 415 } 416 while (len > 0) { 417 if (len < 8) { 418 reg_w_buf(gspca_dev, index, seq, len); 419 seq += len; 420 break; 421 } 422 reg_w_buf(gspca_dev, index, seq, 8); 423 seq += 8; 424 index += 8; 425 len -= 8; 426 } 427 } 428 } 429 /* not reached */ 430} 431 432/* this function is called at probe time for pac7302 */ 433static int sd_config(struct gspca_dev *gspca_dev, 434 const struct usb_device_id *id) 435{ 436 struct sd *sd = (struct sd *) gspca_dev; 437 struct cam *cam; 438 439 cam = &gspca_dev->cam; 440 441 PDEBUG(D_CONF, "Find Sensor PAC7302"); 442 cam->cam_mode = vga_mode; /* only 640x480 */ 443 cam->nmodes = ARRAY_SIZE(vga_mode); 444 445 sd->brightness = BRIGHTNESS_DEF; 446 sd->contrast = CONTRAST_DEF; 447 sd->colors = COLOR_DEF; 448 sd->gain = GAIN_DEF; 449 sd->exposure = EXPOSURE_DEF; 450 sd->autogain = AUTOGAIN_DEF; 451 sd->hflip = HFLIP_DEF; 452 sd->vflip = VFLIP_DEF; 453 return 0; 454} 455 456/* This function is used by pac7302 only */ 457static void setbrightcont(struct gspca_dev *gspca_dev) 458{ 459 struct sd *sd = (struct sd *) gspca_dev; 460 int i, v; 461 static const __u8 max[10] = 462 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, 463 0xd4, 0xec}; 464 static const __u8 delta[10] = 465 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, 466 0x11, 0x0b}; 467 468 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ 469 for (i = 0; i < 10; i++) { 470 v = max[i]; 471 v += (sd->brightness - BRIGHTNESS_MAX) 472 * 150 / BRIGHTNESS_MAX; /* 200 ? */ 473 v -= delta[i] * sd->contrast / CONTRAST_MAX; 474 if (v < 0) 475 v = 0; 476 else if (v > 0xff) 477 v = 0xff; 478 reg_w(gspca_dev, 0xa2 + i, v); 479 } 480 reg_w(gspca_dev, 0xdc, 0x01); 481} 482 483/* This function is used by pac7302 only */ 484static void setcolors(struct gspca_dev *gspca_dev) 485{ 486 struct sd *sd = (struct sd *) gspca_dev; 487 int i, v; 488 static const int a[9] = 489 {217, -212, 0, -101, 170, -67, -38, -315, 355}; 490 static const int b[9] = 491 {19, 106, 0, 19, 106, 1, 19, 106, 1}; 492 493 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 494 reg_w(gspca_dev, 0x11, 0x01); 495 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ 496 for (i = 0; i < 9; i++) { 497 v = a[i] * sd->colors / COLOR_MAX + b[i]; 498 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); 499 reg_w(gspca_dev, 0x0f + 2 * i + 1, v); 500 } 501 reg_w(gspca_dev, 0xdc, 0x01); 502 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); 503} 504 505static void setgain(struct gspca_dev *gspca_dev) 506{ 507 struct sd *sd = (struct sd *) gspca_dev; 508 509 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 510 reg_w(gspca_dev, 0x10, sd->gain >> 3); 511 512 /* load registers to sensor (Bit 0, auto clear) */ 513 reg_w(gspca_dev, 0x11, 0x01); 514} 515 516static void setexposure(struct gspca_dev *gspca_dev) 517{ 518 struct sd *sd = (struct sd *) gspca_dev; 519 __u8 reg; 520 521 /* register 2 of frame 3/4 contains the clock divider configuring the 522 no fps according to the formula: 60 / reg. sd->exposure is the 523 desired exposure time in ms. */ 524 reg = 120 * sd->exposure / 1000; 525 if (reg < 2) 526 reg = 2; 527 else if (reg > 63) 528 reg = 63; 529 530 /* On the pac7302 reg2 MUST be a multiple of 3, so round it to 531 the nearest multiple of 3, except when between 6 and 12? */ 532 if (reg < 6 || reg > 12) 533 reg = ((reg + 1) / 3) * 3; 534 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 535 reg_w(gspca_dev, 0x02, reg); 536 537 /* load registers to sensor (Bit 0, auto clear) */ 538 reg_w(gspca_dev, 0x11, 0x01); 539} 540 541static void sethvflip(struct gspca_dev *gspca_dev) 542{ 543 struct sd *sd = (struct sd *) gspca_dev; 544 __u8 data; 545 546 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 547 data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00); 548 reg_w(gspca_dev, 0x21, data); 549 /* load registers to sensor (Bit 0, auto clear) */ 550 reg_w(gspca_dev, 0x11, 0x01); 551} 552 553/* this function is called at probe and resume time for pac7302 */ 554static int sd_init(struct gspca_dev *gspca_dev) 555{ 556 reg_w_seq(gspca_dev, init_7302, sizeof init_7302); 557 558 return 0; 559} 560 561static int sd_start(struct gspca_dev *gspca_dev) 562{ 563 struct sd *sd = (struct sd *) gspca_dev; 564 565 sd->sof_read = 0; 566 567 reg_w_var(gspca_dev, start_7302, 568 page3_7302, sizeof(page3_7302), 569 NULL, 0); 570 setbrightcont(gspca_dev); 571 setcolors(gspca_dev); 572 setgain(gspca_dev); 573 setexposure(gspca_dev); 574 sethvflip(gspca_dev); 575 576 /* only resolution 640x480 is supported for pac7302 */ 577 578 sd->sof_read = 0; 579 sd->autogain_ignore_frames = 0; 580 atomic_set(&sd->avg_lum, -1); 581 582 /* start stream */ 583 reg_w(gspca_dev, 0xff, 0x01); 584 reg_w(gspca_dev, 0x78, 0x01); 585 586 return 0; 587} 588 589static void sd_stopN(struct gspca_dev *gspca_dev) 590{ 591 reg_w(gspca_dev, 0xff, 0x01); 592 reg_w(gspca_dev, 0x78, 0x00); 593 reg_w(gspca_dev, 0x78, 0x00); 594} 595 596/* called on streamoff with alt 0 and on disconnect for pac7302 */ 597static void sd_stop0(struct gspca_dev *gspca_dev) 598{ 599 if (!gspca_dev->present) 600 return; 601 reg_w(gspca_dev, 0xff, 0x01); 602 reg_w(gspca_dev, 0x78, 0x40); 603} 604 605/* Include pac common sof detection functions */ 606#include "pac_common.h" 607 608static void do_autogain(struct gspca_dev *gspca_dev) 609{ 610 struct sd *sd = (struct sd *) gspca_dev; 611 int avg_lum = atomic_read(&sd->avg_lum); 612 int desired_lum, deadzone; 613 614 if (avg_lum == -1) 615 return; 616 617 desired_lum = 270 + sd->brightness * 4; 618 /* Hack hack, with the 7202 the first exposure step is 619 pretty large, so if we're about to make the first 620 exposure increase make the deadzone large to avoid 621 oscilating */ 622 if (desired_lum > avg_lum && sd->gain == GAIN_DEF && 623 sd->exposure > EXPOSURE_DEF && 624 sd->exposure < 42) 625 deadzone = 90; 626 else 627 deadzone = 30; 628 629 if (sd->autogain_ignore_frames > 0) 630 sd->autogain_ignore_frames--; 631 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, 632 deadzone, GAIN_KNEE, EXPOSURE_KNEE)) 633 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; 634} 635 636/* JPEG header, part 1 */ 637static const unsigned char pac_jpeg_header1[] = { 638 0xff, 0xd8, /* SOI: Start of Image */ 639 640 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ 641 0x00, 0x11, /* length = 17 bytes (including this length field) */ 642 0x08 /* Precision: 8 */ 643 /* 2 bytes is placed here: number of image lines */ 644 /* 2 bytes is placed here: samples per line */ 645}; 646 647/* JPEG header, continued */ 648static const unsigned char pac_jpeg_header2[] = { 649 0x03, /* Number of image components: 3 */ 650 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ 651 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ 652 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ 653 654 0xff, 0xda, /* SOS: Start Of Scan */ 655 0x00, 0x0c, /* length = 12 bytes (including this length field) */ 656 0x03, /* number of components: 3 */ 657 0x01, 0x00, /* selector 1, table 0x00 */ 658 0x02, 0x11, /* selector 2, table 0x11 */ 659 0x03, 0x11, /* selector 3, table 0x11 */ 660 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ 661 0x00 /* Successive approximation: 0 */ 662}; 663 664static void pac_start_frame(struct gspca_dev *gspca_dev, 665 struct gspca_frame *frame, 666 __u16 lines, __u16 samples_per_line) 667{ 668 unsigned char tmpbuf[4]; 669 670 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, 671 pac_jpeg_header1, sizeof(pac_jpeg_header1)); 672 673 tmpbuf[0] = lines >> 8; 674 tmpbuf[1] = lines & 0xff; 675 tmpbuf[2] = samples_per_line >> 8; 676 tmpbuf[3] = samples_per_line & 0xff; 677 678 gspca_frame_add(gspca_dev, INTER_PACKET, frame, 679 tmpbuf, sizeof(tmpbuf)); 680 gspca_frame_add(gspca_dev, INTER_PACKET, frame, 681 pac_jpeg_header2, sizeof(pac_jpeg_header2)); 682} 683 684/* this function is run at interrupt level */ 685static void sd_pkt_scan(struct gspca_dev *gspca_dev, 686 struct gspca_frame *frame, /* target */ 687 __u8 *data, /* isoc packet */ 688 int len) /* iso packet length */ 689{ 690 struct sd *sd = (struct sd *) gspca_dev; 691 unsigned char *sof; 692 693 sof = pac_find_sof(&sd->sof_read, data, len); 694 if (sof) { 695 int n, lum_offset, footer_length; 696 697 /* 6 bytes after the FF D9 EOF marker a number of lumination 698 bytes are send corresponding to different parts of the 699 image, the 14th and 15th byte after the EOF seem to 700 correspond to the center of the image */ 701 lum_offset = 61 + sizeof pac_sof_marker; 702 footer_length = 74; 703 704 /* Finish decoding current frame */ 705 n = (sof - data) - (footer_length + sizeof pac_sof_marker); 706 if (n < 0) { 707 frame->data_end += n; 708 n = 0; 709 } 710 frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame, 711 data, n); 712 if (gspca_dev->last_packet_type != DISCARD_PACKET && 713 frame->data_end[-2] == 0xff && 714 frame->data_end[-1] == 0xd9) 715 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, 716 NULL, 0); 717 718 n = sof - data; 719 len -= n; 720 data = sof; 721 722 /* Get average lumination */ 723 if (gspca_dev->last_packet_type == LAST_PACKET && 724 n >= lum_offset) 725 atomic_set(&sd->avg_lum, data[-lum_offset] + 726 data[-lum_offset + 1]); 727 else 728 atomic_set(&sd->avg_lum, -1); 729 730 /* Start the new frame with the jpeg header */ 731 /* The PAC7302 has the image rotated 90 degrees */ 732 pac_start_frame(gspca_dev, frame, 733 gspca_dev->width, gspca_dev->height); 734 } 735 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); 736} 737 738static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 739{ 740 struct sd *sd = (struct sd *) gspca_dev; 741 742 sd->brightness = val; 743 if (gspca_dev->streaming) 744 setbrightcont(gspca_dev); 745 return 0; 746} 747 748static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) 749{ 750 struct sd *sd = (struct sd *) gspca_dev; 751 752 *val = sd->brightness; 753 return 0; 754} 755 756static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) 757{ 758 struct sd *sd = (struct sd *) gspca_dev; 759 760 sd->contrast = val; 761 if (gspca_dev->streaming) { 762 setbrightcont(gspca_dev); 763 } 764 return 0; 765} 766 767static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) 768{ 769 struct sd *sd = (struct sd *) gspca_dev; 770 771 *val = sd->contrast; 772 return 0; 773} 774 775static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) 776{ 777 struct sd *sd = (struct sd *) gspca_dev; 778 779 sd->colors = val; 780 if (gspca_dev->streaming) 781 setcolors(gspca_dev); 782 return 0; 783} 784 785static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) 786{ 787 struct sd *sd = (struct sd *) gspca_dev; 788 789 *val = sd->colors; 790 return 0; 791} 792 793static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) 794{ 795 struct sd *sd = (struct sd *) gspca_dev; 796 797 sd->gain = val; 798 if (gspca_dev->streaming) 799 setgain(gspca_dev); 800 return 0; 801} 802 803static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) 804{ 805 struct sd *sd = (struct sd *) gspca_dev; 806 807 *val = sd->gain; 808 return 0; 809} 810 811static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) 812{ 813 struct sd *sd = (struct sd *) gspca_dev; 814 815 sd->exposure = val; 816 if (gspca_dev->streaming) 817 setexposure(gspca_dev); 818 return 0; 819} 820 821static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) 822{ 823 struct sd *sd = (struct sd *) gspca_dev; 824 825 *val = sd->exposure; 826 return 0; 827} 828 829static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) 830{ 831 struct sd *sd = (struct sd *) gspca_dev; 832 833 sd->autogain = val; 834 /* when switching to autogain set defaults to make sure 835 we are on a valid point of the autogain gain / 836 exposure knee graph, and give this change time to 837 take effect before doing autogain. */ 838 if (sd->autogain) { 839 sd->exposure = EXPOSURE_DEF; 840 sd->gain = GAIN_DEF; 841 if (gspca_dev->streaming) { 842 sd->autogain_ignore_frames = 843 PAC_AUTOGAIN_IGNORE_FRAMES; 844 setexposure(gspca_dev); 845 setgain(gspca_dev); 846 } 847 } 848 849 return 0; 850} 851 852static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) 853{ 854 struct sd *sd = (struct sd *) gspca_dev; 855 856 *val = sd->autogain; 857 return 0; 858} 859 860static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) 861{ 862 struct sd *sd = (struct sd *) gspca_dev; 863 864 sd->hflip = val; 865 if (gspca_dev->streaming) 866 sethvflip(gspca_dev); 867 return 0; 868} 869 870static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) 871{ 872 struct sd *sd = (struct sd *) gspca_dev; 873 874 *val = sd->hflip; 875 return 0; 876} 877 878static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) 879{ 880 struct sd *sd = (struct sd *) gspca_dev; 881 882 sd->vflip = val; 883 if (gspca_dev->streaming) 884 sethvflip(gspca_dev); 885 return 0; 886} 887 888static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) 889{ 890 struct sd *sd = (struct sd *) gspca_dev; 891 892 *val = sd->vflip; 893 return 0; 894} 895 896/* sub-driver description for pac7302 */ 897static struct sd_desc sd_desc = { 898 .name = MODULE_NAME, 899 .ctrls = sd_ctrls, 900 .nctrls = ARRAY_SIZE(sd_ctrls), 901 .config = sd_config, 902 .init = sd_init, 903 .start = sd_start, 904 .stopN = sd_stopN, 905 .stop0 = sd_stop0, 906 .pkt_scan = sd_pkt_scan, 907 .dq_callback = do_autogain, 908}; 909 910/* -- module initialisation -- */ 911static __devinitdata struct usb_device_id device_table[] = { 912 {USB_DEVICE(0x06f8, 0x3009)}, 913 {USB_DEVICE(0x093a, 0x2620)}, 914 {USB_DEVICE(0x093a, 0x2621)}, 915 {USB_DEVICE(0x093a, 0x2622)}, 916 {USB_DEVICE(0x093a, 0x2624)}, 917 {USB_DEVICE(0x093a, 0x2626)}, 918 {USB_DEVICE(0x093a, 0x2628)}, 919 {USB_DEVICE(0x093a, 0x2629)}, 920 {USB_DEVICE(0x093a, 0x262a)}, 921 {USB_DEVICE(0x093a, 0x262c)}, 922 {} 923}; 924MODULE_DEVICE_TABLE(usb, device_table); 925 926/* -- device connect -- */ 927static int sd_probe(struct usb_interface *intf, 928 const struct usb_device_id *id) 929{ 930 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 931 THIS_MODULE); 932} 933 934static struct usb_driver sd_driver = { 935 .name = MODULE_NAME, 936 .id_table = device_table, 937 .probe = sd_probe, 938 .disconnect = gspca_disconnect, 939#ifdef CONFIG_PM 940 .suspend = gspca_suspend, 941 .resume = gspca_resume, 942#endif 943}; 944 945/* -- module insert / remove -- */ 946static int __init sd_mod_init(void) 947{ 948 int ret; 949 ret = usb_register(&sd_driver); 950 if (ret < 0) 951 return ret; 952 PDEBUG(D_PROBE, "registered"); 953 return 0; 954} 955static void __exit sd_mod_exit(void) 956{ 957 usb_deregister(&sd_driver); 958 PDEBUG(D_PROBE, "deregistered"); 959} 960 961module_init(sd_mod_init); 962module_exit(sd_mod_exit); 963