1/* 2 * Etoms Et61x151 GPL Linux driver by Michel Xhaard (09/09/2004) 3 * 4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 22 23#define MODULE_NAME "etoms" 24 25#include "gspca.h" 26 27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); 28MODULE_DESCRIPTION("Etoms USB Camera Driver"); 29MODULE_LICENSE("GPL"); 30 31/* specific webcam descriptor */ 32struct sd { 33 struct gspca_dev gspca_dev; /* !! must be the first item */ 34 35 unsigned char autogain; 36 37 char sensor; 38#define SENSOR_PAS106 0 39#define SENSOR_TAS5130CXX 1 40 signed char ag_cnt; 41#define AG_CNT_START 13 42}; 43 44static const struct v4l2_pix_format vga_mode[] = { 45 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 46 .bytesperline = 320, 47 .sizeimage = 320 * 240, 48 .colorspace = V4L2_COLORSPACE_SRGB, 49 .priv = 1}, 50/* {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 51 .bytesperline = 640, 52 .sizeimage = 640 * 480, 53 .colorspace = V4L2_COLORSPACE_SRGB, 54 .priv = 0}, */ 55}; 56 57static const struct v4l2_pix_format sif_mode[] = { 58 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 59 .bytesperline = 176, 60 .sizeimage = 176 * 144, 61 .colorspace = V4L2_COLORSPACE_SRGB, 62 .priv = 1}, 63 {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 64 .bytesperline = 352, 65 .sizeimage = 352 * 288, 66 .colorspace = V4L2_COLORSPACE_SRGB, 67 .priv = 0}, 68}; 69 70#define ETOMS_ALT_SIZE_1000 12 71 72#define ET_GPIO_DIR_CTRL 0x04 /* Control IO bit[0..5] (0 in 1 out) */ 73#define ET_GPIO_OUT 0x05 /* Only IO data */ 74#define ET_GPIO_IN 0x06 /* Read Only IO data */ 75#define ET_RESET_ALL 0x03 76#define ET_ClCK 0x01 77#define ET_CTRL 0x02 /* enable i2c OutClck Powerdown mode */ 78 79#define ET_COMP 0x12 /* Compression register */ 80#define ET_MAXQt 0x13 81#define ET_MINQt 0x14 82#define ET_COMP_VAL0 0x02 83#define ET_COMP_VAL1 0x03 84 85#define ET_REG1d 0x1d 86#define ET_REG1e 0x1e 87#define ET_REG1f 0x1f 88#define ET_REG20 0x20 89#define ET_REG21 0x21 90#define ET_REG22 0x22 91#define ET_REG23 0x23 92#define ET_REG24 0x24 93#define ET_REG25 0x25 94/* base registers for luma calculation */ 95#define ET_LUMA_CENTER 0x39 96 97#define ET_G_RED 0x4d 98#define ET_G_GREEN1 0x4e 99#define ET_G_BLUE 0x4f 100#define ET_G_GREEN2 0x50 101#define ET_G_GR_H 0x51 102#define ET_G_GB_H 0x52 103 104#define ET_O_RED 0x34 105#define ET_O_GREEN1 0x35 106#define ET_O_BLUE 0x36 107#define ET_O_GREEN2 0x37 108 109#define ET_SYNCHRO 0x68 110#define ET_STARTX 0x69 111#define ET_STARTY 0x6a 112#define ET_WIDTH_LOW 0x6b 113#define ET_HEIGTH_LOW 0x6c 114#define ET_W_H_HEIGTH 0x6d 115 116#define ET_REG6e 0x6e /* OBW */ 117#define ET_REG6f 0x6f /* OBW */ 118#define ET_REG70 0x70 /* OBW_AWB */ 119#define ET_REG71 0x71 /* OBW_AWB */ 120#define ET_REG72 0x72 /* OBW_AWB */ 121#define ET_REG73 0x73 /* Clkdelay ns */ 122#define ET_REG74 0x74 /* test pattern */ 123#define ET_REG75 0x75 /* test pattern */ 124 125#define ET_I2C_CLK 0x8c 126#define ET_PXL_CLK 0x60 127 128#define ET_I2C_BASE 0x89 129#define ET_I2C_COUNT 0x8a 130#define ET_I2C_PREFETCH 0x8b 131#define ET_I2C_REG 0x88 132#define ET_I2C_DATA7 0x87 133#define ET_I2C_DATA6 0x86 134#define ET_I2C_DATA5 0x85 135#define ET_I2C_DATA4 0x84 136#define ET_I2C_DATA3 0x83 137#define ET_I2C_DATA2 0x82 138#define ET_I2C_DATA1 0x81 139#define ET_I2C_DATA0 0x80 140 141#define PAS106_REG2 0x02 /* pxlClk = systemClk/(reg2) */ 142#define PAS106_REG3 0x03 /* line/frame H [11..4] */ 143#define PAS106_REG4 0x04 /* line/frame L [3..0] */ 144#define PAS106_REG5 0x05 /* exposure time line offset(default 5) */ 145#define PAS106_REG6 0x06 /* exposure time pixel offset(default 6) */ 146#define PAS106_REG7 0x07 /* signbit Dac (default 0) */ 147#define PAS106_REG9 0x09 148#define PAS106_REG0e 0x0e /* global gain [4..0](default 0x0e) */ 149#define PAS106_REG13 0x13 /* end i2c write */ 150 151static const __u8 GainRGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 }; 152 153static const __u8 I2c2[] = { 0x08, 0x08, 0x08, 0x08, 0x0d }; 154 155static const __u8 I2c3[] = { 0x12, 0x05 }; 156 157static const __u8 I2c4[] = { 0x41, 0x08 }; 158 159/* read 'len' bytes to gspca_dev->usb_buf */ 160static void reg_r(struct gspca_dev *gspca_dev, 161 __u16 index, 162 __u16 len) 163{ 164 struct usb_device *dev = gspca_dev->dev; 165 166 if (len > USB_BUF_SZ) { 167 PERR("reg_r: buffer overflow\n"); 168 return; 169 } 170 171 usb_control_msg(dev, 172 usb_rcvctrlpipe(dev, 0), 173 0, 174 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 175 0, 176 index, gspca_dev->usb_buf, len, 500); 177 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..", 178 index, gspca_dev->usb_buf[0]); 179} 180 181static void reg_w_val(struct gspca_dev *gspca_dev, 182 __u16 index, 183 __u8 val) 184{ 185 struct usb_device *dev = gspca_dev->dev; 186 187 gspca_dev->usb_buf[0] = val; 188 usb_control_msg(dev, 189 usb_sndctrlpipe(dev, 0), 190 0, 191 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 192 0, 193 index, gspca_dev->usb_buf, 1, 500); 194} 195 196static void reg_w(struct gspca_dev *gspca_dev, 197 __u16 index, 198 const __u8 *buffer, 199 __u16 len) 200{ 201 struct usb_device *dev = gspca_dev->dev; 202 203 if (len > USB_BUF_SZ) { 204 pr_err("reg_w: buffer overflow\n"); 205 return; 206 } 207 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer); 208 209 memcpy(gspca_dev->usb_buf, buffer, len); 210 usb_control_msg(dev, 211 usb_sndctrlpipe(dev, 0), 212 0, 213 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 214 0, index, gspca_dev->usb_buf, len, 500); 215} 216 217static int i2c_w(struct gspca_dev *gspca_dev, 218 __u8 reg, 219 const __u8 *buffer, 220 int len, __u8 mode) 221{ 222 /* buffer should be [D0..D7] */ 223 __u8 ptchcount; 224 225 /* set the base address */ 226 reg_w_val(gspca_dev, ET_I2C_BASE, 0x40); 227 /* sensor base for the pas106 */ 228 /* set count and prefetch */ 229 ptchcount = ((len & 0x07) << 4) | (mode & 0x03); 230 reg_w_val(gspca_dev, ET_I2C_COUNT, ptchcount); 231 /* set the register base */ 232 reg_w_val(gspca_dev, ET_I2C_REG, reg); 233 while (--len >= 0) 234 reg_w_val(gspca_dev, ET_I2C_DATA0 + len, buffer[len]); 235 return 0; 236} 237 238static int i2c_r(struct gspca_dev *gspca_dev, 239 __u8 reg) 240{ 241 /* set the base address */ 242 reg_w_val(gspca_dev, ET_I2C_BASE, 0x40); 243 /* sensor base for the pas106 */ 244 /* set count and prefetch (cnd: 4 bits - mode: 4 bits) */ 245 reg_w_val(gspca_dev, ET_I2C_COUNT, 0x11); 246 reg_w_val(gspca_dev, ET_I2C_REG, reg); /* set the register base */ 247 reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x02); /* prefetch */ 248 reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x00); 249 reg_r(gspca_dev, ET_I2C_DATA0, 1); /* read one byte */ 250 return 0; 251} 252 253static int Et_WaitStatus(struct gspca_dev *gspca_dev) 254{ 255 int retry = 10; 256 257 while (retry--) { 258 reg_r(gspca_dev, ET_ClCK, 1); 259 if (gspca_dev->usb_buf[0] != 0) 260 return 1; 261 } 262 return 0; 263} 264 265static int et_video(struct gspca_dev *gspca_dev, 266 int on) 267{ 268 int ret; 269 270 reg_w_val(gspca_dev, ET_GPIO_OUT, 271 on ? 0x10 /* startvideo - set Bit5 */ 272 : 0); /* stopvideo */ 273 ret = Et_WaitStatus(gspca_dev); 274 if (ret != 0) 275 PERR("timeout video on/off"); 276 return ret; 277} 278 279static void Et_init2(struct gspca_dev *gspca_dev) 280{ 281 __u8 value; 282 static const __u8 FormLine[] = { 0x84, 0x03, 0x14, 0xf4, 0x01, 0x05 }; 283 284 PDEBUG(D_STREAM, "Open Init2 ET"); 285 reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 0x2f); 286 reg_w_val(gspca_dev, ET_GPIO_OUT, 0x10); 287 reg_r(gspca_dev, ET_GPIO_IN, 1); 288 reg_w_val(gspca_dev, ET_ClCK, 0x14); /* 0x14 // 0x16 enabled pattern */ 289 reg_w_val(gspca_dev, ET_CTRL, 0x1b); 290 291 /* compression et subsampling */ 292 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) 293 value = ET_COMP_VAL1; /* 320 */ 294 else 295 value = ET_COMP_VAL0; /* 640 */ 296 reg_w_val(gspca_dev, ET_COMP, value); 297 reg_w_val(gspca_dev, ET_MAXQt, 0x1f); 298 reg_w_val(gspca_dev, ET_MINQt, 0x04); 299 /* undocumented registers */ 300 reg_w_val(gspca_dev, ET_REG1d, 0xff); 301 reg_w_val(gspca_dev, ET_REG1e, 0xff); 302 reg_w_val(gspca_dev, ET_REG1f, 0xff); 303 reg_w_val(gspca_dev, ET_REG20, 0x35); 304 reg_w_val(gspca_dev, ET_REG21, 0x01); 305 reg_w_val(gspca_dev, ET_REG22, 0x00); 306 reg_w_val(gspca_dev, ET_REG23, 0xff); 307 reg_w_val(gspca_dev, ET_REG24, 0xff); 308 reg_w_val(gspca_dev, ET_REG25, 0x0f); 309 /* colors setting */ 310 reg_w_val(gspca_dev, 0x30, 0x11); /* 0x30 */ 311 reg_w_val(gspca_dev, 0x31, 0x40); 312 reg_w_val(gspca_dev, 0x32, 0x00); 313 reg_w_val(gspca_dev, ET_O_RED, 0x00); /* 0x34 */ 314 reg_w_val(gspca_dev, ET_O_GREEN1, 0x00); 315 reg_w_val(gspca_dev, ET_O_BLUE, 0x00); 316 reg_w_val(gspca_dev, ET_O_GREEN2, 0x00); 317 /*************/ 318 reg_w_val(gspca_dev, ET_G_RED, 0x80); /* 0x4d */ 319 reg_w_val(gspca_dev, ET_G_GREEN1, 0x80); 320 reg_w_val(gspca_dev, ET_G_BLUE, 0x80); 321 reg_w_val(gspca_dev, ET_G_GREEN2, 0x80); 322 reg_w_val(gspca_dev, ET_G_GR_H, 0x00); 323 reg_w_val(gspca_dev, ET_G_GB_H, 0x00); /* 0x52 */ 324 /* Window control registers */ 325 reg_w_val(gspca_dev, 0x61, 0x80); /* use cmc_out */ 326 reg_w_val(gspca_dev, 0x62, 0x02); 327 reg_w_val(gspca_dev, 0x63, 0x03); 328 reg_w_val(gspca_dev, 0x64, 0x14); 329 reg_w_val(gspca_dev, 0x65, 0x0e); 330 reg_w_val(gspca_dev, 0x66, 0x02); 331 reg_w_val(gspca_dev, 0x67, 0x02); 332 333 /**************************************/ 334 reg_w_val(gspca_dev, ET_SYNCHRO, 0x8f); /* 0x68 */ 335 reg_w_val(gspca_dev, ET_STARTX, 0x69); /* 0x6a //0x69 */ 336 reg_w_val(gspca_dev, ET_STARTY, 0x0d); /* 0x0d //0x0c */ 337 reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x80); 338 reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0xe0); 339 reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x60); /* 6d */ 340 reg_w_val(gspca_dev, ET_REG6e, 0x86); 341 reg_w_val(gspca_dev, ET_REG6f, 0x01); 342 reg_w_val(gspca_dev, ET_REG70, 0x26); 343 reg_w_val(gspca_dev, ET_REG71, 0x7a); 344 reg_w_val(gspca_dev, ET_REG72, 0x01); 345 /* Clock Pattern registers ***************** */ 346 reg_w_val(gspca_dev, ET_REG73, 0x00); 347 reg_w_val(gspca_dev, ET_REG74, 0x18); /* 0x28 */ 348 reg_w_val(gspca_dev, ET_REG75, 0x0f); /* 0x01 */ 349 /**********************************************/ 350 reg_w_val(gspca_dev, 0x8a, 0x20); 351 reg_w_val(gspca_dev, 0x8d, 0x0f); 352 reg_w_val(gspca_dev, 0x8e, 0x08); 353 /**************************************/ 354 reg_w_val(gspca_dev, 0x03, 0x08); 355 reg_w_val(gspca_dev, ET_PXL_CLK, 0x03); 356 reg_w_val(gspca_dev, 0x81, 0xff); 357 reg_w_val(gspca_dev, 0x80, 0x00); 358 reg_w_val(gspca_dev, 0x81, 0xff); 359 reg_w_val(gspca_dev, 0x80, 0x20); 360 reg_w_val(gspca_dev, 0x03, 0x01); 361 reg_w_val(gspca_dev, 0x03, 0x00); 362 reg_w_val(gspca_dev, 0x03, 0x08); 363 /********************************************/ 364 365/* reg_r(gspca_dev, ET_I2C_BASE, 1); 366 always 0x40 as the pas106 ??? */ 367 /* set the sensor */ 368 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) 369 value = 0x04; /* 320 */ 370 else /* 640 */ 371 value = 0x1e; /* 0x17 * setting PixelClock 372 * 0x03 mean 24/(3+1) = 6 Mhz 373 * 0x05 -> 24/(5+1) = 4 Mhz 374 * 0x0b -> 24/(11+1) = 2 Mhz 375 * 0x17 -> 24/(23+1) = 1 Mhz 376 */ 377 reg_w_val(gspca_dev, ET_PXL_CLK, value); 378 /* now set by fifo the FormatLine setting */ 379 reg_w(gspca_dev, 0x62, FormLine, 6); 380 381 /* set exposure times [ 0..0x78] 0->longvalue 0x78->shortvalue */ 382 reg_w_val(gspca_dev, 0x81, 0x47); /* 0x47; */ 383 reg_w_val(gspca_dev, 0x80, 0x40); /* 0x40; */ 384 /* Pedro change */ 385 /* Brightness change Brith+ decrease value */ 386 /* Brigth- increase value */ 387 /* original value = 0x70; */ 388 reg_w_val(gspca_dev, 0x81, 0x30); /* 0x20; - set brightness */ 389 reg_w_val(gspca_dev, 0x80, 0x20); /* 0x20; */ 390} 391 392static void setbrightness(struct gspca_dev *gspca_dev, s32 val) 393{ 394 int i; 395 396 for (i = 0; i < 4; i++) 397 reg_w_val(gspca_dev, ET_O_RED + i, val); 398} 399 400static void setcontrast(struct gspca_dev *gspca_dev, s32 val) 401{ 402 __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 }; 403 404 memset(RGBG, val, sizeof(RGBG) - 2); 405 reg_w(gspca_dev, ET_G_RED, RGBG, 6); 406} 407 408static void setcolors(struct gspca_dev *gspca_dev, s32 val) 409{ 410 struct sd *sd = (struct sd *) gspca_dev; 411 __u8 I2cc[] = { 0x05, 0x02, 0x02, 0x05, 0x0d }; 412 __u8 i2cflags = 0x01; 413 /* __u8 green = 0; */ 414 415 I2cc[3] = val; /* red */ 416 I2cc[0] = 15 - val; /* blue */ 417 /* green = 15 - ((((7*I2cc[0]) >> 2 ) + I2cc[3]) >> 1); */ 418 /* I2cc[1] = I2cc[2] = green; */ 419 if (sd->sensor == SENSOR_PAS106) { 420 i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3); 421 i2c_w(gspca_dev, PAS106_REG9, I2cc, sizeof I2cc, 1); 422 } 423/* PDEBUG(D_CONF , "Etoms red %d blue %d green %d", 424 I2cc[3], I2cc[0], green); */ 425} 426 427static s32 getcolors(struct gspca_dev *gspca_dev) 428{ 429 struct sd *sd = (struct sd *) gspca_dev; 430 431 if (sd->sensor == SENSOR_PAS106) { 432/* i2c_r(gspca_dev, PAS106_REG9); * blue */ 433 i2c_r(gspca_dev, PAS106_REG9 + 3); /* red */ 434 return gspca_dev->usb_buf[0] & 0x0f; 435 } 436 return 0; 437} 438 439static void setautogain(struct gspca_dev *gspca_dev) 440{ 441 struct sd *sd = (struct sd *) gspca_dev; 442 443 if (sd->autogain) 444 sd->ag_cnt = AG_CNT_START; 445 else 446 sd->ag_cnt = -1; 447} 448 449static void Et_init1(struct gspca_dev *gspca_dev) 450{ 451 __u8 value; 452/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0x22, 0xac, 0x00, 0x01, 0x00}; */ 453 __u8 I2c0[] = { 0x0a, 0x12, 0x05, 0x6d, 0xcd, 0x00, 0x01, 0x00 }; 454 /* try 1/120 0x6d 0xcd 0x40 */ 455/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0xfe, 0xfe, 0xc0, 0x01, 0x00}; 456 * 1/60000 hmm ?? */ 457 458 PDEBUG(D_STREAM, "Open Init1 ET"); 459 reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 7); 460 reg_r(gspca_dev, ET_GPIO_IN, 1); 461 reg_w_val(gspca_dev, ET_RESET_ALL, 1); 462 reg_w_val(gspca_dev, ET_RESET_ALL, 0); 463 reg_w_val(gspca_dev, ET_ClCK, 0x10); 464 reg_w_val(gspca_dev, ET_CTRL, 0x19); 465 /* compression et subsampling */ 466 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) 467 value = ET_COMP_VAL1; 468 else 469 value = ET_COMP_VAL0; 470 PDEBUG(D_STREAM, "Open mode %d Compression %d", 471 gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv, 472 value); 473 reg_w_val(gspca_dev, ET_COMP, value); 474 reg_w_val(gspca_dev, ET_MAXQt, 0x1d); 475 reg_w_val(gspca_dev, ET_MINQt, 0x02); 476 /* undocumented registers */ 477 reg_w_val(gspca_dev, ET_REG1d, 0xff); 478 reg_w_val(gspca_dev, ET_REG1e, 0xff); 479 reg_w_val(gspca_dev, ET_REG1f, 0xff); 480 reg_w_val(gspca_dev, ET_REG20, 0x35); 481 reg_w_val(gspca_dev, ET_REG21, 0x01); 482 reg_w_val(gspca_dev, ET_REG22, 0x00); 483 reg_w_val(gspca_dev, ET_REG23, 0xf7); 484 reg_w_val(gspca_dev, ET_REG24, 0xff); 485 reg_w_val(gspca_dev, ET_REG25, 0x07); 486 /* colors setting */ 487 reg_w_val(gspca_dev, ET_G_RED, 0x80); 488 reg_w_val(gspca_dev, ET_G_GREEN1, 0x80); 489 reg_w_val(gspca_dev, ET_G_BLUE, 0x80); 490 reg_w_val(gspca_dev, ET_G_GREEN2, 0x80); 491 reg_w_val(gspca_dev, ET_G_GR_H, 0x00); 492 reg_w_val(gspca_dev, ET_G_GB_H, 0x00); 493 /* Window control registers */ 494 reg_w_val(gspca_dev, ET_SYNCHRO, 0xf0); 495 reg_w_val(gspca_dev, ET_STARTX, 0x56); /* 0x56 */ 496 reg_w_val(gspca_dev, ET_STARTY, 0x05); /* 0x04 */ 497 reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x60); 498 reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0x20); 499 reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x50); 500 reg_w_val(gspca_dev, ET_REG6e, 0x86); 501 reg_w_val(gspca_dev, ET_REG6f, 0x01); 502 reg_w_val(gspca_dev, ET_REG70, 0x86); 503 reg_w_val(gspca_dev, ET_REG71, 0x14); 504 reg_w_val(gspca_dev, ET_REG72, 0x00); 505 /* Clock Pattern registers */ 506 reg_w_val(gspca_dev, ET_REG73, 0x00); 507 reg_w_val(gspca_dev, ET_REG74, 0x00); 508 reg_w_val(gspca_dev, ET_REG75, 0x0a); 509 reg_w_val(gspca_dev, ET_I2C_CLK, 0x04); 510 reg_w_val(gspca_dev, ET_PXL_CLK, 0x01); 511 /* set the sensor */ 512 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { 513 I2c0[0] = 0x06; 514 i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1); 515 i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1); 516 value = 0x06; 517 i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1); 518 i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1); 519 /* value = 0x1f; */ 520 value = 0x04; 521 i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1); 522 } else { 523 I2c0[0] = 0x0a; 524 525 i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1); 526 i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1); 527 value = 0x0a; 528 i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1); 529 i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1); 530 value = 0x04; 531 /* value = 0x10; */ 532 i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1); 533 /* bit 2 enable bit 1:2 select 0 1 2 3 534 value = 0x07; * curve 0 * 535 i2c_w(gspca_dev, PAS106_REG0f, &value, 1, 1); 536 */ 537 } 538 539/* value = 0x01; */ 540/* value = 0x22; */ 541/* i2c_w(gspca_dev, PAS106_REG5, &value, 1, 1); */ 542 /* magnetude and sign bit for DAC */ 543 i2c_w(gspca_dev, PAS106_REG7, I2c4, sizeof I2c4, 1); 544 /* now set by fifo the whole colors setting */ 545 reg_w(gspca_dev, ET_G_RED, GainRGBG, 6); 546 setcolors(gspca_dev, getcolors(gspca_dev)); 547} 548 549/* this function is called at probe time */ 550static int sd_config(struct gspca_dev *gspca_dev, 551 const struct usb_device_id *id) 552{ 553 struct sd *sd = (struct sd *) gspca_dev; 554 struct cam *cam; 555 556 cam = &gspca_dev->cam; 557 sd->sensor = id->driver_info; 558 if (sd->sensor == SENSOR_PAS106) { 559 cam->cam_mode = sif_mode; 560 cam->nmodes = ARRAY_SIZE(sif_mode); 561 } else { 562 cam->cam_mode = vga_mode; 563 cam->nmodes = ARRAY_SIZE(vga_mode); 564 } 565 sd->ag_cnt = -1; 566 return 0; 567} 568 569/* this function is called at probe and resume time */ 570static int sd_init(struct gspca_dev *gspca_dev) 571{ 572 struct sd *sd = (struct sd *) gspca_dev; 573 574 if (sd->sensor == SENSOR_PAS106) 575 Et_init1(gspca_dev); 576 else 577 Et_init2(gspca_dev); 578 reg_w_val(gspca_dev, ET_RESET_ALL, 0x08); 579 et_video(gspca_dev, 0); /* video off */ 580 return 0; 581} 582 583/* -- start the camera -- */ 584static int sd_start(struct gspca_dev *gspca_dev) 585{ 586 struct sd *sd = (struct sd *) gspca_dev; 587 588 if (sd->sensor == SENSOR_PAS106) 589 Et_init1(gspca_dev); 590 else 591 Et_init2(gspca_dev); 592 593 setautogain(gspca_dev); 594 595 reg_w_val(gspca_dev, ET_RESET_ALL, 0x08); 596 et_video(gspca_dev, 1); /* video on */ 597 return 0; 598} 599 600static void sd_stopN(struct gspca_dev *gspca_dev) 601{ 602 et_video(gspca_dev, 0); /* video off */ 603} 604 605static __u8 Et_getgainG(struct gspca_dev *gspca_dev) 606{ 607 struct sd *sd = (struct sd *) gspca_dev; 608 609 if (sd->sensor == SENSOR_PAS106) { 610 i2c_r(gspca_dev, PAS106_REG0e); 611 PDEBUG(D_CONF, "Etoms gain G %d", gspca_dev->usb_buf[0]); 612 return gspca_dev->usb_buf[0]; 613 } 614 return 0x1f; 615} 616 617static void Et_setgainG(struct gspca_dev *gspca_dev, __u8 gain) 618{ 619 struct sd *sd = (struct sd *) gspca_dev; 620 621 if (sd->sensor == SENSOR_PAS106) { 622 __u8 i2cflags = 0x01; 623 624 i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3); 625 i2c_w(gspca_dev, PAS106_REG0e, &gain, 1, 1); 626 } 627} 628 629#define BLIMIT(bright) \ 630 (u8)((bright > 0x1f) ? 0x1f : ((bright < 4) ? 3 : bright)) 631#define LIMIT(color) \ 632 (u8)((color > 0xff) ? 0xff : ((color < 0) ? 0 : color)) 633 634static void do_autogain(struct gspca_dev *gspca_dev) 635{ 636 struct sd *sd = (struct sd *) gspca_dev; 637 __u8 luma; 638 __u8 luma_mean = 128; 639 __u8 luma_delta = 20; 640 __u8 spring = 4; 641 int Gbright; 642 __u8 r, g, b; 643 644 if (sd->ag_cnt < 0) 645 return; 646 if (--sd->ag_cnt >= 0) 647 return; 648 sd->ag_cnt = AG_CNT_START; 649 650 Gbright = Et_getgainG(gspca_dev); 651 reg_r(gspca_dev, ET_LUMA_CENTER, 4); 652 g = (gspca_dev->usb_buf[0] + gspca_dev->usb_buf[3]) >> 1; 653 r = gspca_dev->usb_buf[1]; 654 b = gspca_dev->usb_buf[2]; 655 r = ((r << 8) - (r << 4) - (r << 3)) >> 10; 656 b = ((b << 7) >> 10); 657 g = ((g << 9) + (g << 7) + (g << 5)) >> 10; 658 luma = LIMIT(r + g + b); 659 PDEBUG(D_FRAM, "Etoms luma G %d", luma); 660 if (luma < luma_mean - luma_delta || luma > luma_mean + luma_delta) { 661 Gbright += (luma_mean - luma) >> spring; 662 Gbright = BLIMIT(Gbright); 663 PDEBUG(D_FRAM, "Etoms Gbright %d", Gbright); 664 Et_setgainG(gspca_dev, (__u8) Gbright); 665 } 666} 667 668#undef BLIMIT 669#undef LIMIT 670 671static void sd_pkt_scan(struct gspca_dev *gspca_dev, 672 u8 *data, /* isoc packet */ 673 int len) /* iso packet length */ 674{ 675 int seqframe; 676 677 seqframe = data[0] & 0x3f; 678 len = (int) (((data[0] & 0xc0) << 2) | data[1]); 679 if (seqframe == 0x3f) { 680 PDEBUG(D_FRAM, 681 "header packet found datalength %d !!", len); 682 PDEBUG(D_FRAM, "G %d R %d G %d B %d", 683 data[2], data[3], data[4], data[5]); 684 data += 30; 685 /* don't change datalength as the chips provided it */ 686 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 687 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); 688 return; 689 } 690 if (len) { 691 data += 8; 692 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 693 } else { /* Drop Packet */ 694 gspca_dev->last_packet_type = DISCARD_PACKET; 695 } 696} 697 698static int sd_s_ctrl(struct v4l2_ctrl *ctrl) 699{ 700 struct gspca_dev *gspca_dev = 701 container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 702 struct sd *sd = (struct sd *)gspca_dev; 703 704 gspca_dev->usb_err = 0; 705 706 if (!gspca_dev->streaming) 707 return 0; 708 709 switch (ctrl->id) { 710 case V4L2_CID_BRIGHTNESS: 711 setbrightness(gspca_dev, ctrl->val); 712 break; 713 case V4L2_CID_CONTRAST: 714 setcontrast(gspca_dev, ctrl->val); 715 break; 716 case V4L2_CID_SATURATION: 717 setcolors(gspca_dev, ctrl->val); 718 break; 719 case V4L2_CID_AUTOGAIN: 720 sd->autogain = ctrl->val; 721 setautogain(gspca_dev); 722 break; 723 } 724 return gspca_dev->usb_err; 725} 726 727static const struct v4l2_ctrl_ops sd_ctrl_ops = { 728 .s_ctrl = sd_s_ctrl, 729}; 730 731static int sd_init_controls(struct gspca_dev *gspca_dev) 732{ 733 struct sd *sd = (struct sd *)gspca_dev; 734 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 735 736 gspca_dev->vdev.ctrl_handler = hdl; 737 v4l2_ctrl_handler_init(hdl, 4); 738 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 739 V4L2_CID_BRIGHTNESS, 1, 127, 1, 63); 740 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 741 V4L2_CID_CONTRAST, 0, 255, 1, 127); 742 if (sd->sensor == SENSOR_PAS106) 743 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 744 V4L2_CID_SATURATION, 0, 15, 1, 7); 745 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 746 V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 747 if (hdl->error) { 748 pr_err("Could not initialize controls\n"); 749 return hdl->error; 750 } 751 return 0; 752} 753 754/* sub-driver description */ 755static const struct sd_desc sd_desc = { 756 .name = MODULE_NAME, 757 .config = sd_config, 758 .init = sd_init, 759 .init_controls = sd_init_controls, 760 .start = sd_start, 761 .stopN = sd_stopN, 762 .pkt_scan = sd_pkt_scan, 763 .dq_callback = do_autogain, 764}; 765 766/* -- module initialisation -- */ 767static const struct usb_device_id device_table[] = { 768 {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106}, 769 {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX}, 770 {} 771}; 772 773MODULE_DEVICE_TABLE(usb, device_table); 774 775/* -- device connect -- */ 776static int sd_probe(struct usb_interface *intf, 777 const struct usb_device_id *id) 778{ 779 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 780 THIS_MODULE); 781} 782 783static struct usb_driver sd_driver = { 784 .name = MODULE_NAME, 785 .id_table = device_table, 786 .probe = sd_probe, 787 .disconnect = gspca_disconnect, 788#ifdef CONFIG_PM 789 .suspend = gspca_suspend, 790 .resume = gspca_resume, 791 .reset_resume = gspca_resume, 792#endif 793}; 794 795module_usb_driver(sd_driver); 796