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