1 /* 2 * Connexant Cx11646 library 3 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr 4 * 5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 23 24 #define MODULE_NAME "conex" 25 26 #include "gspca.h" 27 #define CONEX_CAM 1 /* special JPEG header */ 28 #include "jpeg.h" 29 30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); 31 MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver"); 32 MODULE_LICENSE("GPL"); 33 34 #define QUALITY 50 35 36 /* specific webcam descriptor */ 37 struct sd { 38 struct gspca_dev gspca_dev; /* !! must be the first item */ 39 struct v4l2_ctrl *brightness; 40 struct v4l2_ctrl *contrast; 41 struct v4l2_ctrl *sat; 42 43 u8 jpeg_hdr[JPEG_HDR_SZ]; 44 }; 45 46 static const struct v4l2_pix_format vga_mode[] = { 47 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 48 .bytesperline = 176, 49 .sizeimage = 176 * 144 * 3 / 8 + 590, 50 .colorspace = V4L2_COLORSPACE_JPEG, 51 .priv = 3}, 52 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 53 .bytesperline = 320, 54 .sizeimage = 320 * 240 * 3 / 8 + 590, 55 .colorspace = V4L2_COLORSPACE_JPEG, 56 .priv = 2}, 57 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 58 .bytesperline = 352, 59 .sizeimage = 352 * 288 * 3 / 8 + 590, 60 .colorspace = V4L2_COLORSPACE_JPEG, 61 .priv = 1}, 62 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 63 .bytesperline = 640, 64 .sizeimage = 640 * 480 * 3 / 8 + 590, 65 .colorspace = V4L2_COLORSPACE_JPEG, 66 .priv = 0}, 67 }; 68 69 /* the read bytes are found in gspca_dev->usb_buf */ 70 static void reg_r(struct gspca_dev *gspca_dev, 71 __u16 index, 72 __u16 len) 73 { 74 struct usb_device *dev = gspca_dev->dev; 75 76 #ifdef GSPCA_DEBUG 77 if (len > USB_BUF_SZ) { 78 pr_err("reg_r: buffer overflow\n"); 79 return; 80 } 81 #endif 82 usb_control_msg(dev, 83 usb_rcvctrlpipe(dev, 0), 84 0, 85 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 86 0, 87 index, gspca_dev->usb_buf, len, 88 500); 89 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..", 90 index, gspca_dev->usb_buf[0]); 91 } 92 93 /* the bytes to write are in gspca_dev->usb_buf */ 94 static void reg_w_val(struct gspca_dev *gspca_dev, 95 __u16 index, 96 __u8 val) 97 { 98 struct usb_device *dev = gspca_dev->dev; 99 100 gspca_dev->usb_buf[0] = val; 101 usb_control_msg(dev, 102 usb_sndctrlpipe(dev, 0), 103 0, 104 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 105 0, 106 index, gspca_dev->usb_buf, 1, 500); 107 } 108 109 static void reg_w(struct gspca_dev *gspca_dev, 110 __u16 index, 111 const __u8 *buffer, 112 __u16 len) 113 { 114 struct usb_device *dev = gspca_dev->dev; 115 116 #ifdef GSPCA_DEBUG 117 if (len > USB_BUF_SZ) { 118 pr_err("reg_w: buffer overflow\n"); 119 return; 120 } 121 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer); 122 #endif 123 memcpy(gspca_dev->usb_buf, buffer, len); 124 usb_control_msg(dev, 125 usb_sndctrlpipe(dev, 0), 126 0, 127 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 128 0, 129 index, gspca_dev->usb_buf, len, 500); 130 } 131 132 static const __u8 cx_sensor_init[][4] = { 133 {0x88, 0x11, 0x01, 0x01}, 134 {0x88, 0x12, 0x70, 0x01}, 135 {0x88, 0x0f, 0x00, 0x01}, 136 {0x88, 0x05, 0x01, 0x01}, 137 {} 138 }; 139 140 static const __u8 cx11646_fw1[][3] = { 141 {0x00, 0x02, 0x00}, 142 {0x01, 0x43, 0x00}, 143 {0x02, 0xA7, 0x00}, 144 {0x03, 0x8B, 0x01}, 145 {0x04, 0xE9, 0x02}, 146 {0x05, 0x08, 0x04}, 147 {0x06, 0x08, 0x05}, 148 {0x07, 0x07, 0x06}, 149 {0x08, 0xE7, 0x06}, 150 {0x09, 0xC6, 0x07}, 151 {0x0A, 0x86, 0x08}, 152 {0x0B, 0x46, 0x09}, 153 {0x0C, 0x05, 0x0A}, 154 {0x0D, 0xA5, 0x0A}, 155 {0x0E, 0x45, 0x0B}, 156 {0x0F, 0xE5, 0x0B}, 157 {0x10, 0x85, 0x0C}, 158 {0x11, 0x25, 0x0D}, 159 {0x12, 0xC4, 0x0D}, 160 {0x13, 0x45, 0x0E}, 161 {0x14, 0xE4, 0x0E}, 162 {0x15, 0x64, 0x0F}, 163 {0x16, 0xE4, 0x0F}, 164 {0x17, 0x64, 0x10}, 165 {0x18, 0xE4, 0x10}, 166 {0x19, 0x64, 0x11}, 167 {0x1A, 0xE4, 0x11}, 168 {0x1B, 0x64, 0x12}, 169 {0x1C, 0xE3, 0x12}, 170 {0x1D, 0x44, 0x13}, 171 {0x1E, 0xC3, 0x13}, 172 {0x1F, 0x24, 0x14}, 173 {0x20, 0xA3, 0x14}, 174 {0x21, 0x04, 0x15}, 175 {0x22, 0x83, 0x15}, 176 {0x23, 0xE3, 0x15}, 177 {0x24, 0x43, 0x16}, 178 {0x25, 0xA4, 0x16}, 179 {0x26, 0x23, 0x17}, 180 {0x27, 0x83, 0x17}, 181 {0x28, 0xE3, 0x17}, 182 {0x29, 0x43, 0x18}, 183 {0x2A, 0xA3, 0x18}, 184 {0x2B, 0x03, 0x19}, 185 {0x2C, 0x63, 0x19}, 186 {0x2D, 0xC3, 0x19}, 187 {0x2E, 0x22, 0x1A}, 188 {0x2F, 0x63, 0x1A}, 189 {0x30, 0xC3, 0x1A}, 190 {0x31, 0x23, 0x1B}, 191 {0x32, 0x83, 0x1B}, 192 {0x33, 0xE2, 0x1B}, 193 {0x34, 0x23, 0x1C}, 194 {0x35, 0x83, 0x1C}, 195 {0x36, 0xE2, 0x1C}, 196 {0x37, 0x23, 0x1D}, 197 {0x38, 0x83, 0x1D}, 198 {0x39, 0xE2, 0x1D}, 199 {0x3A, 0x23, 0x1E}, 200 {0x3B, 0x82, 0x1E}, 201 {0x3C, 0xC3, 0x1E}, 202 {0x3D, 0x22, 0x1F}, 203 {0x3E, 0x63, 0x1F}, 204 {0x3F, 0xC1, 0x1F}, 205 {} 206 }; 207 static void cx11646_fw(struct gspca_dev*gspca_dev) 208 { 209 int i = 0; 210 211 reg_w_val(gspca_dev, 0x006a, 0x02); 212 while (cx11646_fw1[i][1]) { 213 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3); 214 i++; 215 } 216 reg_w_val(gspca_dev, 0x006a, 0x00); 217 } 218 219 static const __u8 cxsensor[] = { 220 0x88, 0x12, 0x70, 0x01, 221 0x88, 0x0d, 0x02, 0x01, 222 0x88, 0x0f, 0x00, 0x01, 223 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */ 224 0x88, 0x02, 0x10, 0x01, 225 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */ 226 0x88, 0x0B, 0x00, 0x01, 227 0x88, 0x0A, 0x0A, 0x01, 228 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */ 229 0x88, 0x05, 0x01, 0x01, 230 0xA1, 0x18, 0x00, 0x01, 231 0x00 232 }; 233 234 static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff }; 235 static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff }; 236 static const __u8 reg10[] = { 0xb1, 0xb1 }; 237 static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */ 238 static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f }; 239 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */ 240 static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 }; 241 /* 320{0x04,0x0c,0x05,0x0f}; //320 */ 242 static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */ 243 static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }; 244 245 static void cx_sensor(struct gspca_dev*gspca_dev) 246 { 247 int i = 0; 248 int length; 249 const __u8 *ptsensor = cxsensor; 250 251 reg_w(gspca_dev, 0x0020, reg20, 8); 252 reg_w(gspca_dev, 0x0028, reg28, 8); 253 reg_w(gspca_dev, 0x0010, reg10, 2); 254 reg_w_val(gspca_dev, 0x0092, 0x03); 255 256 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { 257 case 0: 258 reg_w(gspca_dev, 0x0071, reg71a, 4); 259 break; 260 case 1: 261 reg_w(gspca_dev, 0x0071, reg71b, 4); 262 break; 263 default: 264 /* case 2: */ 265 reg_w(gspca_dev, 0x0071, reg71c, 4); 266 break; 267 case 3: 268 reg_w(gspca_dev, 0x0071, reg71d, 4); 269 break; 270 } 271 reg_w(gspca_dev, 0x007b, reg7b, 6); 272 reg_w_val(gspca_dev, 0x00f8, 0x00); 273 reg_w(gspca_dev, 0x0010, reg10, 2); 274 reg_w_val(gspca_dev, 0x0098, 0x41); 275 for (i = 0; i < 11; i++) { 276 if (i == 3 || i == 5 || i == 8) 277 length = 8; 278 else 279 length = 4; 280 reg_w(gspca_dev, 0x00e5, ptsensor, length); 281 if (length == 4) 282 reg_r(gspca_dev, 0x00e8, 1); 283 else 284 reg_r(gspca_dev, 0x00e8, length); 285 ptsensor += length; 286 } 287 reg_r(gspca_dev, 0x00e7, 8); 288 } 289 290 static const __u8 cx_inits_176[] = { 291 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */ 292 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03, 293 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30, 294 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 295 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF, 296 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02, 297 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 298 }; 299 static const __u8 cx_inits_320[] = { 300 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01, 301 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01, 302 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81, 303 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 304 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff, 305 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02, 306 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 307 }; 308 static const __u8 cx_inits_352[] = { 309 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03, 310 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b, 311 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25, 312 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00, 313 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff, 314 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02, 315 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 316 }; 317 static const __u8 cx_inits_640[] = { 318 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01, 319 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01, 320 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81, 321 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 322 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff, 323 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02, 324 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 325 }; 326 327 static void cx11646_initsize(struct gspca_dev *gspca_dev) 328 { 329 const __u8 *cxinit; 330 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 }; 331 static const __u8 reg17[] = 332 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 }; 333 334 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { 335 case 0: 336 cxinit = cx_inits_640; 337 break; 338 case 1: 339 cxinit = cx_inits_352; 340 break; 341 default: 342 /* case 2: */ 343 cxinit = cx_inits_320; 344 break; 345 case 3: 346 cxinit = cx_inits_176; 347 break; 348 } 349 reg_w_val(gspca_dev, 0x009a, 0x01); 350 reg_w_val(gspca_dev, 0x0010, 0x10); 351 reg_w(gspca_dev, 0x0012, reg12, 5); 352 reg_w(gspca_dev, 0x0017, reg17, 8); 353 reg_w_val(gspca_dev, 0x00c0, 0x00); 354 reg_w_val(gspca_dev, 0x00c1, 0x04); 355 reg_w_val(gspca_dev, 0x00c2, 0x04); 356 357 reg_w(gspca_dev, 0x0061, cxinit, 8); 358 cxinit += 8; 359 reg_w(gspca_dev, 0x00ca, cxinit, 8); 360 cxinit += 8; 361 reg_w(gspca_dev, 0x00d2, cxinit, 8); 362 cxinit += 8; 363 reg_w(gspca_dev, 0x00da, cxinit, 6); 364 cxinit += 8; 365 reg_w(gspca_dev, 0x0041, cxinit, 8); 366 cxinit += 8; 367 reg_w(gspca_dev, 0x0049, cxinit, 8); 368 cxinit += 8; 369 reg_w(gspca_dev, 0x0051, cxinit, 2); 370 371 reg_r(gspca_dev, 0x0010, 1); 372 } 373 374 static const __u8 cx_jpeg_init[][8] = { 375 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */ 376 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11}, 377 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22}, 378 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26}, 379 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a}, 380 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73}, 381 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D}, 382 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0}, 383 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01}, 384 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12}, 385 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35}, 386 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31}, 387 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43}, 388 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A}, 389 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73}, 390 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95}, 391 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83}, 392 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05}, 393 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}, 394 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02}, 395 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A}, 396 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01}, 397 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00}, 398 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05}, 399 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00}, 400 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05}, 401 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01}, 402 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21}, 403 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22}, 404 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23}, 405 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24}, 406 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17}, 407 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29}, 408 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A}, 409 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A}, 410 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A}, 411 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A}, 412 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A}, 413 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A}, 414 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99}, 415 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8}, 416 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7}, 417 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6}, 418 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5}, 419 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3}, 420 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1}, 421 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9}, 422 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04}, 423 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01}, 424 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04}, 425 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07}, 426 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14}, 427 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33}, 428 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16}, 429 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19}, 430 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36}, 431 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46}, 432 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56}, 433 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66}, 434 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76}, 435 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85}, 436 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94}, 437 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3}, 438 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2}, 439 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA}, 440 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9}, 441 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8}, 442 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7}, 443 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6}, 444 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F}, 445 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00}, 446 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22}, 447 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11}, 448 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00}, 449 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08}, 450 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00}, 451 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA}, 452 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02}, 453 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */ 454 }; 455 456 457 static const __u8 cxjpeg_640[][8] = { 458 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */ 459 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d}, 460 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a}, 461 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d}, 462 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38}, 463 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57}, 464 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F}, 465 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79}, 466 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01}, 467 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E}, 468 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28}, 469 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25}, 470 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33}, 471 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44}, 472 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57}, 473 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71}, 474 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63}, 475 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00}, 476 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00}, 477 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22}, 478 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55}, 479 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF}, 480 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80}, 481 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02}, 482 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00}, 483 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00}, 484 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */ 485 }; 486 static const __u8 cxjpeg_352[][8] = { 487 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d}, 488 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a}, 489 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14}, 490 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17}, 491 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C}, 492 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44}, 493 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A}, 494 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F}, 495 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01}, 496 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B}, 497 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F}, 498 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D}, 499 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28}, 500 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35}, 501 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44}, 502 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58}, 503 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D}, 504 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00}, 505 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00}, 506 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22}, 507 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55}, 508 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF}, 509 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60}, 510 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02}, 511 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00}, 512 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00}, 513 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 514 }; 515 static const __u8 cxjpeg_320[][8] = { 516 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05}, 517 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04}, 518 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08}, 519 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09}, 520 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11}, 521 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A}, 522 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D}, 523 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24}, 524 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01}, 525 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04}, 526 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C}, 527 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B}, 528 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F}, 529 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14}, 530 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A}, 531 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22}, 532 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E}, 533 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00}, 534 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00}, 535 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22}, 536 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55}, 537 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF}, 538 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40}, 539 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02}, 540 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00}, 541 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00}, 542 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */ 543 }; 544 static const __u8 cxjpeg_176[][8] = { 545 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d}, 546 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A}, 547 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14}, 548 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17}, 549 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C}, 550 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44}, 551 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A}, 552 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F}, 553 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01}, 554 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B}, 555 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F}, 556 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D}, 557 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28}, 558 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35}, 559 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44}, 560 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58}, 561 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D}, 562 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00}, 563 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00}, 564 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22}, 565 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55}, 566 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF}, 567 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0}, 568 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02}, 569 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00}, 570 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00}, 571 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 572 }; 573 /* 640 take with the zcx30x part */ 574 static const __u8 cxjpeg_qtable[][8] = { 575 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08}, 576 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07}, 577 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a}, 578 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f}, 579 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c}, 580 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c}, 581 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30}, 582 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d}, 583 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01}, 584 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a}, 585 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32}, 586 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}, 587 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}, 588 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}, 589 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}, 590 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}, 591 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}, 592 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */ 593 }; 594 595 596 static void cx11646_jpegInit(struct gspca_dev*gspca_dev) 597 { 598 int i; 599 int length; 600 601 reg_w_val(gspca_dev, 0x00c0, 0x01); 602 reg_w_val(gspca_dev, 0x00c3, 0x00); 603 reg_w_val(gspca_dev, 0x00c0, 0x00); 604 reg_r(gspca_dev, 0x0001, 1); 605 length = 8; 606 for (i = 0; i < 79; i++) { 607 if (i == 78) 608 length = 6; 609 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length); 610 } 611 reg_r(gspca_dev, 0x0002, 1); 612 reg_w_val(gspca_dev, 0x0055, 0x14); 613 } 614 615 static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 }; 616 static const __u8 regE5_8[] = 617 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 }; 618 static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 }; 619 static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 }; 620 static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 }; 621 static const __u8 reg51[] = { 0x77, 0x03 }; 622 #define reg70 0x03 623 624 static void cx11646_jpeg(struct gspca_dev*gspca_dev) 625 { 626 int i; 627 int length; 628 __u8 Reg55; 629 int retry; 630 631 reg_w_val(gspca_dev, 0x00c0, 0x01); 632 reg_w_val(gspca_dev, 0x00c3, 0x00); 633 reg_w_val(gspca_dev, 0x00c0, 0x00); 634 reg_r(gspca_dev, 0x0001, 1); 635 length = 8; 636 switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) { 637 case 0: 638 for (i = 0; i < 27; i++) { 639 if (i == 26) 640 length = 2; 641 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length); 642 } 643 Reg55 = 0x28; 644 break; 645 case 1: 646 for (i = 0; i < 27; i++) { 647 if (i == 26) 648 length = 2; 649 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length); 650 } 651 Reg55 = 0x16; 652 break; 653 default: 654 /* case 2: */ 655 for (i = 0; i < 27; i++) { 656 if (i == 26) 657 length = 2; 658 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length); 659 } 660 Reg55 = 0x14; 661 break; 662 case 3: 663 for (i = 0; i < 27; i++) { 664 if (i == 26) 665 length = 2; 666 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length); 667 } 668 Reg55 = 0x0B; 669 break; 670 } 671 672 reg_r(gspca_dev, 0x0002, 1); 673 reg_w_val(gspca_dev, 0x0055, Reg55); 674 reg_r(gspca_dev, 0x0002, 1); 675 reg_w(gspca_dev, 0x0010, reg10, 2); 676 reg_w_val(gspca_dev, 0x0054, 0x02); 677 reg_w_val(gspca_dev, 0x0054, 0x01); 678 reg_w_val(gspca_dev, 0x0000, 0x94); 679 reg_w_val(gspca_dev, 0x0053, 0xc0); 680 reg_w_val(gspca_dev, 0x00fc, 0xe1); 681 reg_w_val(gspca_dev, 0x0000, 0x00); 682 /* wait for completion */ 683 retry = 50; 684 do { 685 reg_r(gspca_dev, 0x0002, 1); 686 /* 0x07 until 0x00 */ 687 if (gspca_dev->usb_buf[0] == 0x00) 688 break; 689 reg_w_val(gspca_dev, 0x0053, 0x00); 690 } while (--retry); 691 if (retry == 0) 692 PDEBUG(D_ERR, "Damned Errors sending jpeg Table"); 693 /* send the qtable now */ 694 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */ 695 length = 8; 696 for (i = 0; i < 18; i++) { 697 if (i == 17) 698 length = 2; 699 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length); 700 701 } 702 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */ 703 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */ 704 reg_w_val(gspca_dev, 0x0054, 0x02); 705 reg_w_val(gspca_dev, 0x0054, 0x01); 706 reg_w_val(gspca_dev, 0x0000, 0x94); 707 reg_w_val(gspca_dev, 0x0053, 0xc0); 708 709 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */ 710 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */ 711 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */ 712 reg_w(gspca_dev, 0x0012, reg12, 5); 713 reg_w(gspca_dev, 0x00e5, regE5_8, 8); 714 reg_r(gspca_dev, 0x00e8, 8); 715 reg_w(gspca_dev, 0x00e5, regE5a, 4); 716 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */ 717 reg_w_val(gspca_dev, 0x009a, 0x01); 718 reg_w(gspca_dev, 0x00e5, regE5b, 4); 719 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */ 720 reg_w(gspca_dev, 0x00e5, regE5c, 4); 721 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */ 722 723 reg_w(gspca_dev, 0x0051, reg51, 2); 724 reg_w(gspca_dev, 0x0010, reg10, 2); 725 reg_w_val(gspca_dev, 0x0070, reg70); 726 } 727 728 static void cx11646_init1(struct gspca_dev *gspca_dev) 729 { 730 int i = 0; 731 732 reg_w_val(gspca_dev, 0x0010, 0x00); 733 reg_w_val(gspca_dev, 0x0053, 0x00); 734 reg_w_val(gspca_dev, 0x0052, 0x00); 735 reg_w_val(gspca_dev, 0x009b, 0x2f); 736 reg_w_val(gspca_dev, 0x009c, 0x10); 737 reg_r(gspca_dev, 0x0098, 1); 738 reg_w_val(gspca_dev, 0x0098, 0x40); 739 reg_r(gspca_dev, 0x0099, 1); 740 reg_w_val(gspca_dev, 0x0099, 0x07); 741 reg_w_val(gspca_dev, 0x0039, 0x40); 742 reg_w_val(gspca_dev, 0x003c, 0xff); 743 reg_w_val(gspca_dev, 0x003f, 0x1f); 744 reg_w_val(gspca_dev, 0x003d, 0x40); 745 /* reg_w_val(gspca_dev, 0x003d, 0x60); */ 746 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */ 747 748 while (cx_sensor_init[i][0]) { 749 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]); 750 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */ 751 if (i == 1) { 752 reg_w_val(gspca_dev, 0x00ed, 0x01); 753 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */ 754 } 755 i++; 756 } 757 reg_w_val(gspca_dev, 0x00c3, 0x00); 758 } 759 760 /* this function is called at probe time */ 761 static int sd_config(struct gspca_dev *gspca_dev, 762 const struct usb_device_id *id) 763 { 764 struct cam *cam; 765 766 cam = &gspca_dev->cam; 767 cam->cam_mode = vga_mode; 768 cam->nmodes = ARRAY_SIZE(vga_mode); 769 return 0; 770 } 771 772 /* this function is called at probe and resume time */ 773 static int sd_init(struct gspca_dev *gspca_dev) 774 { 775 cx11646_init1(gspca_dev); 776 cx11646_initsize(gspca_dev); 777 cx11646_fw(gspca_dev); 778 cx_sensor(gspca_dev); 779 cx11646_jpegInit(gspca_dev); 780 return 0; 781 } 782 783 static int sd_start(struct gspca_dev *gspca_dev) 784 { 785 struct sd *sd = (struct sd *) gspca_dev; 786 787 /* create the JPEG header */ 788 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 789 0x22); /* JPEG 411 */ 790 jpeg_set_qual(sd->jpeg_hdr, QUALITY); 791 792 cx11646_initsize(gspca_dev); 793 cx11646_fw(gspca_dev); 794 cx_sensor(gspca_dev); 795 cx11646_jpeg(gspca_dev); 796 return 0; 797 } 798 799 /* called on streamoff with alt 0 and on disconnect */ 800 static void sd_stop0(struct gspca_dev *gspca_dev) 801 { 802 int retry = 50; 803 804 if (!gspca_dev->present) 805 return; 806 reg_w_val(gspca_dev, 0x0000, 0x00); 807 reg_r(gspca_dev, 0x0002, 1); 808 reg_w_val(gspca_dev, 0x0053, 0x00); 809 810 while (retry--) { 811 /* reg_r(gspca_dev, 0x0002, 1);*/ 812 reg_r(gspca_dev, 0x0053, 1); 813 if (gspca_dev->usb_buf[0] == 0) 814 break; 815 } 816 reg_w_val(gspca_dev, 0x0000, 0x00); 817 reg_r(gspca_dev, 0x0002, 1); 818 819 reg_w_val(gspca_dev, 0x0010, 0x00); 820 reg_r(gspca_dev, 0x0033, 1); 821 reg_w_val(gspca_dev, 0x00fc, 0xe0); 822 } 823 824 static void sd_pkt_scan(struct gspca_dev *gspca_dev, 825 u8 *data, /* isoc packet */ 826 int len) /* iso packet length */ 827 { 828 struct sd *sd = (struct sd *) gspca_dev; 829 830 if (data[0] == 0xff && data[1] == 0xd8) { 831 832 /* start of frame */ 833 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 834 835 /* put the JPEG header in the new frame */ 836 gspca_frame_add(gspca_dev, FIRST_PACKET, 837 sd->jpeg_hdr, JPEG_HDR_SZ); 838 data += 2; 839 len -= 2; 840 } 841 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 842 } 843 844 static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat) 845 { 846 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 }; 847 __u8 reg51c[2]; 848 849 regE5cbx[2] = val; 850 reg_w(gspca_dev, 0x00e5, regE5cbx, 8); 851 reg_r(gspca_dev, 0x00e8, 8); 852 reg_w(gspca_dev, 0x00e5, regE5c, 4); 853 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */ 854 855 reg51c[0] = 0x77; 856 reg51c[1] = sat; 857 reg_w(gspca_dev, 0x0051, reg51c, 2); 858 reg_w(gspca_dev, 0x0010, reg10, 2); 859 reg_w_val(gspca_dev, 0x0070, reg70); 860 } 861 862 static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat) 863 { 864 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */ 865 /* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */ 866 __u8 reg51c[2]; 867 868 regE5acx[2] = val; 869 reg_w(gspca_dev, 0x00e5, regE5acx, 4); 870 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */ 871 reg51c[0] = 0x77; 872 reg51c[1] = sat; 873 reg_w(gspca_dev, 0x0051, reg51c, 2); 874 reg_w(gspca_dev, 0x0010, reg10, 2); 875 reg_w_val(gspca_dev, 0x0070, reg70); 876 } 877 878 static int sd_s_ctrl(struct v4l2_ctrl *ctrl) 879 { 880 struct gspca_dev *gspca_dev = 881 container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 882 struct sd *sd = (struct sd *)gspca_dev; 883 884 gspca_dev->usb_err = 0; 885 886 if (!gspca_dev->streaming) 887 return 0; 888 889 switch (ctrl->id) { 890 case V4L2_CID_BRIGHTNESS: 891 setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val); 892 break; 893 case V4L2_CID_CONTRAST: 894 setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val); 895 break; 896 case V4L2_CID_SATURATION: 897 setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val); 898 setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val); 899 break; 900 } 901 return gspca_dev->usb_err; 902 } 903 904 static const struct v4l2_ctrl_ops sd_ctrl_ops = { 905 .s_ctrl = sd_s_ctrl, 906 }; 907 908 static int sd_init_controls(struct gspca_dev *gspca_dev) 909 { 910 struct sd *sd = (struct sd *)gspca_dev; 911 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 912 913 gspca_dev->vdev.ctrl_handler = hdl; 914 v4l2_ctrl_handler_init(hdl, 3); 915 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 916 V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4); 917 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 918 V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c); 919 sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 920 V4L2_CID_SATURATION, 0, 7, 1, 3); 921 if (hdl->error) { 922 pr_err("Could not initialize controls\n"); 923 return hdl->error; 924 } 925 return 0; 926 } 927 928 /* sub-driver description */ 929 static const struct sd_desc sd_desc = { 930 .name = MODULE_NAME, 931 .config = sd_config, 932 .init = sd_init, 933 .init_controls = sd_init_controls, 934 .start = sd_start, 935 .stop0 = sd_stop0, 936 .pkt_scan = sd_pkt_scan, 937 }; 938 939 /* -- module initialisation -- */ 940 static const struct usb_device_id device_table[] = { 941 {USB_DEVICE(0x0572, 0x0041)}, 942 {} 943 }; 944 MODULE_DEVICE_TABLE(usb, device_table); 945 946 /* -- device connect -- */ 947 static int sd_probe(struct usb_interface *intf, 948 const struct usb_device_id *id) 949 { 950 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 951 THIS_MODULE); 952 } 953 954 static struct usb_driver sd_driver = { 955 .name = MODULE_NAME, 956 .id_table = device_table, 957 .probe = sd_probe, 958 .disconnect = gspca_disconnect, 959 #ifdef CONFIG_PM 960 .suspend = gspca_suspend, 961 .resume = gspca_resume, 962 .reset_resume = gspca_resume, 963 #endif 964 }; 965 966 module_usb_driver(sd_driver); 967