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