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