0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010
0011 #define MODULE_NAME "conex"
0012
0013 #include "gspca.h"
0014 #define CONEX_CAM 1
0015 #include "jpeg.h"
0016
0017 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
0018 MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
0019 MODULE_LICENSE("GPL");
0020
0021 #define QUALITY 50
0022
0023
0024 struct sd {
0025 struct gspca_dev gspca_dev;
0026 struct v4l2_ctrl *brightness;
0027 struct v4l2_ctrl *contrast;
0028 struct v4l2_ctrl *sat;
0029
0030 u8 jpeg_hdr[JPEG_HDR_SZ];
0031 };
0032
0033 static const struct v4l2_pix_format vga_mode[] = {
0034 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0035 .bytesperline = 176,
0036 .sizeimage = 176 * 144 * 3 / 8 + 590,
0037 .colorspace = V4L2_COLORSPACE_JPEG,
0038 .priv = 3},
0039 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0040 .bytesperline = 320,
0041 .sizeimage = 320 * 240 * 3 / 8 + 590,
0042 .colorspace = V4L2_COLORSPACE_JPEG,
0043 .priv = 2},
0044 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0045 .bytesperline = 352,
0046 .sizeimage = 352 * 288 * 3 / 8 + 590,
0047 .colorspace = V4L2_COLORSPACE_JPEG,
0048 .priv = 1},
0049 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0050 .bytesperline = 640,
0051 .sizeimage = 640 * 480 * 3 / 8 + 590,
0052 .colorspace = V4L2_COLORSPACE_JPEG,
0053 .priv = 0},
0054 };
0055
0056
0057 static void reg_r(struct gspca_dev *gspca_dev,
0058 __u16 index,
0059 __u16 len)
0060 {
0061 struct usb_device *dev = gspca_dev->dev;
0062
0063 if (len > USB_BUF_SZ) {
0064 gspca_err(gspca_dev, "reg_r: buffer overflow\n");
0065 return;
0066 }
0067
0068 usb_control_msg(dev,
0069 usb_rcvctrlpipe(dev, 0),
0070 0,
0071 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0072 0,
0073 index, gspca_dev->usb_buf, len,
0074 500);
0075 gspca_dbg(gspca_dev, D_USBI, "reg read [%02x] -> %02x ..\n",
0076 index, gspca_dev->usb_buf[0]);
0077 }
0078
0079
0080 static void reg_w_val(struct gspca_dev *gspca_dev,
0081 __u16 index,
0082 __u8 val)
0083 {
0084 struct usb_device *dev = gspca_dev->dev;
0085
0086 gspca_dev->usb_buf[0] = val;
0087 usb_control_msg(dev,
0088 usb_sndctrlpipe(dev, 0),
0089 0,
0090 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0091 0,
0092 index, gspca_dev->usb_buf, 1, 500);
0093 }
0094
0095 static void reg_w(struct gspca_dev *gspca_dev,
0096 __u16 index,
0097 const __u8 *buffer,
0098 __u16 len)
0099 {
0100 struct usb_device *dev = gspca_dev->dev;
0101
0102 if (len > USB_BUF_SZ) {
0103 gspca_err(gspca_dev, "reg_w: buffer overflow\n");
0104 return;
0105 }
0106 gspca_dbg(gspca_dev, D_USBO, "reg write [%02x] = %02x..\n",
0107 index, *buffer);
0108
0109 memcpy(gspca_dev->usb_buf, buffer, len);
0110 usb_control_msg(dev,
0111 usb_sndctrlpipe(dev, 0),
0112 0,
0113 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0114 0,
0115 index, gspca_dev->usb_buf, len, 500);
0116 }
0117
0118 static const __u8 cx_sensor_init[][4] = {
0119 {0x88, 0x11, 0x01, 0x01},
0120 {0x88, 0x12, 0x70, 0x01},
0121 {0x88, 0x0f, 0x00, 0x01},
0122 {0x88, 0x05, 0x01, 0x01},
0123 {}
0124 };
0125
0126 static const __u8 cx11646_fw1[][3] = {
0127 {0x00, 0x02, 0x00},
0128 {0x01, 0x43, 0x00},
0129 {0x02, 0xA7, 0x00},
0130 {0x03, 0x8B, 0x01},
0131 {0x04, 0xE9, 0x02},
0132 {0x05, 0x08, 0x04},
0133 {0x06, 0x08, 0x05},
0134 {0x07, 0x07, 0x06},
0135 {0x08, 0xE7, 0x06},
0136 {0x09, 0xC6, 0x07},
0137 {0x0A, 0x86, 0x08},
0138 {0x0B, 0x46, 0x09},
0139 {0x0C, 0x05, 0x0A},
0140 {0x0D, 0xA5, 0x0A},
0141 {0x0E, 0x45, 0x0B},
0142 {0x0F, 0xE5, 0x0B},
0143 {0x10, 0x85, 0x0C},
0144 {0x11, 0x25, 0x0D},
0145 {0x12, 0xC4, 0x0D},
0146 {0x13, 0x45, 0x0E},
0147 {0x14, 0xE4, 0x0E},
0148 {0x15, 0x64, 0x0F},
0149 {0x16, 0xE4, 0x0F},
0150 {0x17, 0x64, 0x10},
0151 {0x18, 0xE4, 0x10},
0152 {0x19, 0x64, 0x11},
0153 {0x1A, 0xE4, 0x11},
0154 {0x1B, 0x64, 0x12},
0155 {0x1C, 0xE3, 0x12},
0156 {0x1D, 0x44, 0x13},
0157 {0x1E, 0xC3, 0x13},
0158 {0x1F, 0x24, 0x14},
0159 {0x20, 0xA3, 0x14},
0160 {0x21, 0x04, 0x15},
0161 {0x22, 0x83, 0x15},
0162 {0x23, 0xE3, 0x15},
0163 {0x24, 0x43, 0x16},
0164 {0x25, 0xA4, 0x16},
0165 {0x26, 0x23, 0x17},
0166 {0x27, 0x83, 0x17},
0167 {0x28, 0xE3, 0x17},
0168 {0x29, 0x43, 0x18},
0169 {0x2A, 0xA3, 0x18},
0170 {0x2B, 0x03, 0x19},
0171 {0x2C, 0x63, 0x19},
0172 {0x2D, 0xC3, 0x19},
0173 {0x2E, 0x22, 0x1A},
0174 {0x2F, 0x63, 0x1A},
0175 {0x30, 0xC3, 0x1A},
0176 {0x31, 0x23, 0x1B},
0177 {0x32, 0x83, 0x1B},
0178 {0x33, 0xE2, 0x1B},
0179 {0x34, 0x23, 0x1C},
0180 {0x35, 0x83, 0x1C},
0181 {0x36, 0xE2, 0x1C},
0182 {0x37, 0x23, 0x1D},
0183 {0x38, 0x83, 0x1D},
0184 {0x39, 0xE2, 0x1D},
0185 {0x3A, 0x23, 0x1E},
0186 {0x3B, 0x82, 0x1E},
0187 {0x3C, 0xC3, 0x1E},
0188 {0x3D, 0x22, 0x1F},
0189 {0x3E, 0x63, 0x1F},
0190 {0x3F, 0xC1, 0x1F},
0191 {}
0192 };
0193 static void cx11646_fw(struct gspca_dev*gspca_dev)
0194 {
0195 int i = 0;
0196
0197 reg_w_val(gspca_dev, 0x006a, 0x02);
0198 while (cx11646_fw1[i][1]) {
0199 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
0200 i++;
0201 }
0202 reg_w_val(gspca_dev, 0x006a, 0x00);
0203 }
0204
0205 static const __u8 cxsensor[] = {
0206 0x88, 0x12, 0x70, 0x01,
0207 0x88, 0x0d, 0x02, 0x01,
0208 0x88, 0x0f, 0x00, 0x01,
0209 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01,
0210 0x88, 0x02, 0x10, 0x01,
0211 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01,
0212 0x88, 0x0B, 0x00, 0x01,
0213 0x88, 0x0A, 0x0A, 0x01,
0214 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01,
0215 0x88, 0x05, 0x01, 0x01,
0216 0xA1, 0x18, 0x00, 0x01,
0217 0x00
0218 };
0219
0220 static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
0221 static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
0222 static const __u8 reg10[] = { 0xb1, 0xb1 };
0223 static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e };
0224 static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
0225
0226 static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
0227
0228 static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 };
0229 static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
0230
0231 static void cx_sensor(struct gspca_dev*gspca_dev)
0232 {
0233 int i = 0;
0234 int length;
0235 const __u8 *ptsensor = cxsensor;
0236
0237 reg_w(gspca_dev, 0x0020, reg20, 8);
0238 reg_w(gspca_dev, 0x0028, reg28, 8);
0239 reg_w(gspca_dev, 0x0010, reg10, 2);
0240 reg_w_val(gspca_dev, 0x0092, 0x03);
0241
0242 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
0243 case 0:
0244 reg_w(gspca_dev, 0x0071, reg71a, 4);
0245 break;
0246 case 1:
0247 reg_w(gspca_dev, 0x0071, reg71b, 4);
0248 break;
0249 default:
0250
0251 reg_w(gspca_dev, 0x0071, reg71c, 4);
0252 break;
0253 case 3:
0254 reg_w(gspca_dev, 0x0071, reg71d, 4);
0255 break;
0256 }
0257 reg_w(gspca_dev, 0x007b, reg7b, 6);
0258 reg_w_val(gspca_dev, 0x00f8, 0x00);
0259 reg_w(gspca_dev, 0x0010, reg10, 2);
0260 reg_w_val(gspca_dev, 0x0098, 0x41);
0261 for (i = 0; i < 11; i++) {
0262 if (i == 3 || i == 5 || i == 8)
0263 length = 8;
0264 else
0265 length = 4;
0266 reg_w(gspca_dev, 0x00e5, ptsensor, length);
0267 if (length == 4)
0268 reg_r(gspca_dev, 0x00e8, 1);
0269 else
0270 reg_r(gspca_dev, 0x00e8, length);
0271 ptsensor += length;
0272 }
0273 reg_r(gspca_dev, 0x00e7, 8);
0274 }
0275
0276 static const __u8 cx_inits_176[] = {
0277 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03,
0278 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
0279 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
0280 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0281 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
0282 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
0283 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0284 };
0285 static const __u8 cx_inits_320[] = {
0286 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
0287 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
0288 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
0289 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0290 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
0291 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
0292 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0293 };
0294 static const __u8 cx_inits_352[] = {
0295 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
0296 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
0297 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
0298 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
0299 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
0300 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
0301 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0302 };
0303 static const __u8 cx_inits_640[] = {
0304 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
0305 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
0306 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
0307 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0308 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
0309 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
0310 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0311 };
0312
0313 static void cx11646_initsize(struct gspca_dev *gspca_dev)
0314 {
0315 const __u8 *cxinit;
0316 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
0317 static const __u8 reg17[] =
0318 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
0319
0320 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
0321 case 0:
0322 cxinit = cx_inits_640;
0323 break;
0324 case 1:
0325 cxinit = cx_inits_352;
0326 break;
0327 default:
0328
0329 cxinit = cx_inits_320;
0330 break;
0331 case 3:
0332 cxinit = cx_inits_176;
0333 break;
0334 }
0335 reg_w_val(gspca_dev, 0x009a, 0x01);
0336 reg_w_val(gspca_dev, 0x0010, 0x10);
0337 reg_w(gspca_dev, 0x0012, reg12, 5);
0338 reg_w(gspca_dev, 0x0017, reg17, 8);
0339 reg_w_val(gspca_dev, 0x00c0, 0x00);
0340 reg_w_val(gspca_dev, 0x00c1, 0x04);
0341 reg_w_val(gspca_dev, 0x00c2, 0x04);
0342
0343 reg_w(gspca_dev, 0x0061, cxinit, 8);
0344 cxinit += 8;
0345 reg_w(gspca_dev, 0x00ca, cxinit, 8);
0346 cxinit += 8;
0347 reg_w(gspca_dev, 0x00d2, cxinit, 8);
0348 cxinit += 8;
0349 reg_w(gspca_dev, 0x00da, cxinit, 6);
0350 cxinit += 8;
0351 reg_w(gspca_dev, 0x0041, cxinit, 8);
0352 cxinit += 8;
0353 reg_w(gspca_dev, 0x0049, cxinit, 8);
0354 cxinit += 8;
0355 reg_w(gspca_dev, 0x0051, cxinit, 2);
0356
0357 reg_r(gspca_dev, 0x0010, 1);
0358 }
0359
0360 static const __u8 cx_jpeg_init[][8] = {
0361 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15},
0362 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
0363 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
0364 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
0365 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
0366 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
0367 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
0368 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
0369 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
0370 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
0371 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
0372 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
0373 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
0374 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
0375 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
0376 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
0377 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
0378 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
0379 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
0380 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
0381 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
0382 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
0383 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
0384 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
0385 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
0386 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
0387 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
0388 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
0389 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
0390 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
0391 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
0392 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
0393 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
0394 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
0395 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
0396 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
0397 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
0398 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
0399 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
0400 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
0401 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
0402 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
0403 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
0404 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
0405 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
0406 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
0407 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
0408 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
0409 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
0410 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
0411 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
0412 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
0413 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
0414 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
0415 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
0416 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
0417 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
0418 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
0419 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
0420 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
0421 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
0422 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
0423 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
0424 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
0425 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
0426 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
0427 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
0428 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
0429 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
0430 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
0431 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
0432 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
0433 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
0434 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
0435 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
0436 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
0437 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
0438 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
0439 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00}
0440 };
0441
0442
0443 static const __u8 cxjpeg_640[][8] = {
0444 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10},
0445 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
0446 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
0447 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
0448 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
0449 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
0450 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
0451 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
0452 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
0453 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
0454 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
0455 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
0456 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
0457 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
0458 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
0459 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
0460 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
0461 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
0462 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
0463 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
0464 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
0465 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
0466 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
0467 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
0468 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
0469 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
0470 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
0471 };
0472 static const __u8 cxjpeg_352[][8] = {
0473 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
0474 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
0475 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
0476 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
0477 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
0478 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
0479 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
0480 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
0481 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
0482 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
0483 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
0484 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
0485 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
0486 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
0487 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
0488 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
0489 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
0490 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
0491 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
0492 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
0493 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
0494 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
0495 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
0496 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
0497 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
0498 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
0499 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
0500 };
0501 static const __u8 cxjpeg_320[][8] = {
0502 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
0503 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
0504 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
0505 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
0506 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
0507 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
0508 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
0509 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
0510 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
0511 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
0512 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
0513 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
0514 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
0515 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
0516 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
0517 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
0518 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
0519 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
0520 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
0521 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
0522 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
0523 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
0524 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
0525 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
0526 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
0527 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
0528 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
0529 };
0530 static const __u8 cxjpeg_176[][8] = {
0531 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
0532 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
0533 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
0534 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
0535 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
0536 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
0537 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
0538 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
0539 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
0540 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
0541 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
0542 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
0543 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
0544 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
0545 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
0546 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
0547 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
0548 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
0549 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
0550 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
0551 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
0552 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
0553 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
0554 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
0555 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
0556 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
0557 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
0558 };
0559
0560 static const __u8 cxjpeg_qtable[][8] = {
0561 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
0562 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
0563 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
0564 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
0565 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
0566 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
0567 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
0568 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
0569 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
0570 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
0571 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
0572 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
0573 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
0574 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
0575 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
0576 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
0577 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
0578 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
0579 };
0580
0581
0582 static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
0583 {
0584 int i;
0585 int length;
0586
0587 reg_w_val(gspca_dev, 0x00c0, 0x01);
0588 reg_w_val(gspca_dev, 0x00c3, 0x00);
0589 reg_w_val(gspca_dev, 0x00c0, 0x00);
0590 reg_r(gspca_dev, 0x0001, 1);
0591 length = 8;
0592 for (i = 0; i < 79; i++) {
0593 if (i == 78)
0594 length = 6;
0595 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
0596 }
0597 reg_r(gspca_dev, 0x0002, 1);
0598 reg_w_val(gspca_dev, 0x0055, 0x14);
0599 }
0600
0601 static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
0602 static const __u8 regE5_8[] =
0603 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
0604 static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
0605 static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
0606 static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
0607 static const __u8 reg51[] = { 0x77, 0x03 };
0608 #define reg70 0x03
0609
0610 static void cx11646_jpeg(struct gspca_dev*gspca_dev)
0611 {
0612 int i;
0613 int length;
0614 __u8 Reg55;
0615 int retry;
0616
0617 reg_w_val(gspca_dev, 0x00c0, 0x01);
0618 reg_w_val(gspca_dev, 0x00c3, 0x00);
0619 reg_w_val(gspca_dev, 0x00c0, 0x00);
0620 reg_r(gspca_dev, 0x0001, 1);
0621 length = 8;
0622 switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
0623 case 0:
0624 for (i = 0; i < 27; i++) {
0625 if (i == 26)
0626 length = 2;
0627 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
0628 }
0629 Reg55 = 0x28;
0630 break;
0631 case 1:
0632 for (i = 0; i < 27; i++) {
0633 if (i == 26)
0634 length = 2;
0635 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
0636 }
0637 Reg55 = 0x16;
0638 break;
0639 default:
0640
0641 for (i = 0; i < 27; i++) {
0642 if (i == 26)
0643 length = 2;
0644 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
0645 }
0646 Reg55 = 0x14;
0647 break;
0648 case 3:
0649 for (i = 0; i < 27; i++) {
0650 if (i == 26)
0651 length = 2;
0652 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
0653 }
0654 Reg55 = 0x0B;
0655 break;
0656 }
0657
0658 reg_r(gspca_dev, 0x0002, 1);
0659 reg_w_val(gspca_dev, 0x0055, Reg55);
0660 reg_r(gspca_dev, 0x0002, 1);
0661 reg_w(gspca_dev, 0x0010, reg10, 2);
0662 reg_w_val(gspca_dev, 0x0054, 0x02);
0663 reg_w_val(gspca_dev, 0x0054, 0x01);
0664 reg_w_val(gspca_dev, 0x0000, 0x94);
0665 reg_w_val(gspca_dev, 0x0053, 0xc0);
0666 reg_w_val(gspca_dev, 0x00fc, 0xe1);
0667 reg_w_val(gspca_dev, 0x0000, 0x00);
0668
0669 retry = 50;
0670 do {
0671 reg_r(gspca_dev, 0x0002, 1);
0672
0673 if (gspca_dev->usb_buf[0] == 0x00)
0674 break;
0675 reg_w_val(gspca_dev, 0x0053, 0x00);
0676 } while (--retry);
0677 if (retry == 0)
0678 gspca_err(gspca_dev, "Damned Errors sending jpeg Table\n");
0679
0680 reg_r(gspca_dev, 0x0001, 1);
0681 length = 8;
0682 for (i = 0; i < 18; i++) {
0683 if (i == 17)
0684 length = 2;
0685 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
0686
0687 }
0688 reg_r(gspca_dev, 0x0002, 1);
0689 reg_r(gspca_dev, 0x0053, 1);
0690 reg_w_val(gspca_dev, 0x0054, 0x02);
0691 reg_w_val(gspca_dev, 0x0054, 0x01);
0692 reg_w_val(gspca_dev, 0x0000, 0x94);
0693 reg_w_val(gspca_dev, 0x0053, 0xc0);
0694
0695 reg_r(gspca_dev, 0x0038, 1);
0696 reg_r(gspca_dev, 0x0038, 1);
0697 reg_r(gspca_dev, 0x001f, 1);
0698 reg_w(gspca_dev, 0x0012, reg12, 5);
0699 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
0700 reg_r(gspca_dev, 0x00e8, 8);
0701 reg_w(gspca_dev, 0x00e5, regE5a, 4);
0702 reg_r(gspca_dev, 0x00e8, 1);
0703 reg_w_val(gspca_dev, 0x009a, 0x01);
0704 reg_w(gspca_dev, 0x00e5, regE5b, 4);
0705 reg_r(gspca_dev, 0x00e8, 1);
0706 reg_w(gspca_dev, 0x00e5, regE5c, 4);
0707 reg_r(gspca_dev, 0x00e8, 1);
0708
0709 reg_w(gspca_dev, 0x0051, reg51, 2);
0710 reg_w(gspca_dev, 0x0010, reg10, 2);
0711 reg_w_val(gspca_dev, 0x0070, reg70);
0712 }
0713
0714 static void cx11646_init1(struct gspca_dev *gspca_dev)
0715 {
0716 int i = 0;
0717
0718 reg_w_val(gspca_dev, 0x0010, 0x00);
0719 reg_w_val(gspca_dev, 0x0053, 0x00);
0720 reg_w_val(gspca_dev, 0x0052, 0x00);
0721 reg_w_val(gspca_dev, 0x009b, 0x2f);
0722 reg_w_val(gspca_dev, 0x009c, 0x10);
0723 reg_r(gspca_dev, 0x0098, 1);
0724 reg_w_val(gspca_dev, 0x0098, 0x40);
0725 reg_r(gspca_dev, 0x0099, 1);
0726 reg_w_val(gspca_dev, 0x0099, 0x07);
0727 reg_w_val(gspca_dev, 0x0039, 0x40);
0728 reg_w_val(gspca_dev, 0x003c, 0xff);
0729 reg_w_val(gspca_dev, 0x003f, 0x1f);
0730 reg_w_val(gspca_dev, 0x003d, 0x40);
0731
0732 reg_r(gspca_dev, 0x0099, 1);
0733
0734 while (cx_sensor_init[i][0]) {
0735 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
0736 reg_r(gspca_dev, 0x00e8, 1);
0737 if (i == 1) {
0738 reg_w_val(gspca_dev, 0x00ed, 0x01);
0739 reg_r(gspca_dev, 0x00ed, 1);
0740 }
0741 i++;
0742 }
0743 reg_w_val(gspca_dev, 0x00c3, 0x00);
0744 }
0745
0746
0747 static int sd_config(struct gspca_dev *gspca_dev,
0748 const struct usb_device_id *id)
0749 {
0750 struct cam *cam;
0751
0752 cam = &gspca_dev->cam;
0753 cam->cam_mode = vga_mode;
0754 cam->nmodes = ARRAY_SIZE(vga_mode);
0755 return 0;
0756 }
0757
0758
0759 static int sd_init(struct gspca_dev *gspca_dev)
0760 {
0761 cx11646_init1(gspca_dev);
0762 cx11646_initsize(gspca_dev);
0763 cx11646_fw(gspca_dev);
0764 cx_sensor(gspca_dev);
0765 cx11646_jpegInit(gspca_dev);
0766 return 0;
0767 }
0768
0769 static int sd_start(struct gspca_dev *gspca_dev)
0770 {
0771 struct sd *sd = (struct sd *) gspca_dev;
0772
0773
0774 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
0775 gspca_dev->pixfmt.width,
0776 0x22);
0777 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
0778
0779 cx11646_initsize(gspca_dev);
0780 cx11646_fw(gspca_dev);
0781 cx_sensor(gspca_dev);
0782 cx11646_jpeg(gspca_dev);
0783 return 0;
0784 }
0785
0786
0787 static void sd_stop0(struct gspca_dev *gspca_dev)
0788 {
0789 int retry = 50;
0790
0791 if (!gspca_dev->present)
0792 return;
0793 reg_w_val(gspca_dev, 0x0000, 0x00);
0794 reg_r(gspca_dev, 0x0002, 1);
0795 reg_w_val(gspca_dev, 0x0053, 0x00);
0796
0797 while (retry--) {
0798
0799 reg_r(gspca_dev, 0x0053, 1);
0800 if (gspca_dev->usb_buf[0] == 0)
0801 break;
0802 }
0803 reg_w_val(gspca_dev, 0x0000, 0x00);
0804 reg_r(gspca_dev, 0x0002, 1);
0805
0806 reg_w_val(gspca_dev, 0x0010, 0x00);
0807 reg_r(gspca_dev, 0x0033, 1);
0808 reg_w_val(gspca_dev, 0x00fc, 0xe0);
0809 }
0810
0811 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
0812 u8 *data,
0813 int len)
0814 {
0815 struct sd *sd = (struct sd *) gspca_dev;
0816
0817 if (data[0] == 0xff && data[1] == 0xd8) {
0818
0819
0820 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
0821
0822
0823 gspca_frame_add(gspca_dev, FIRST_PACKET,
0824 sd->jpeg_hdr, JPEG_HDR_SZ);
0825 data += 2;
0826 len -= 2;
0827 }
0828 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
0829 }
0830
0831 static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
0832 {
0833 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
0834 __u8 reg51c[2];
0835
0836 regE5cbx[2] = val;
0837 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
0838 reg_r(gspca_dev, 0x00e8, 8);
0839 reg_w(gspca_dev, 0x00e5, regE5c, 4);
0840 reg_r(gspca_dev, 0x00e8, 1);
0841
0842 reg51c[0] = 0x77;
0843 reg51c[1] = sat;
0844 reg_w(gspca_dev, 0x0051, reg51c, 2);
0845 reg_w(gspca_dev, 0x0010, reg10, 2);
0846 reg_w_val(gspca_dev, 0x0070, reg70);
0847 }
0848
0849 static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
0850 {
0851 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 };
0852
0853 __u8 reg51c[2];
0854
0855 regE5acx[2] = val;
0856 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
0857 reg_r(gspca_dev, 0x00e8, 1);
0858 reg51c[0] = 0x77;
0859 reg51c[1] = sat;
0860 reg_w(gspca_dev, 0x0051, reg51c, 2);
0861 reg_w(gspca_dev, 0x0010, reg10, 2);
0862 reg_w_val(gspca_dev, 0x0070, reg70);
0863 }
0864
0865 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
0866 {
0867 struct gspca_dev *gspca_dev =
0868 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0869 struct sd *sd = (struct sd *)gspca_dev;
0870
0871 gspca_dev->usb_err = 0;
0872
0873 if (!gspca_dev->streaming)
0874 return 0;
0875
0876 switch (ctrl->id) {
0877 case V4L2_CID_BRIGHTNESS:
0878 setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
0879 break;
0880 case V4L2_CID_CONTRAST:
0881 setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
0882 break;
0883 case V4L2_CID_SATURATION:
0884 setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
0885 setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val);
0886 break;
0887 }
0888 return gspca_dev->usb_err;
0889 }
0890
0891 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
0892 .s_ctrl = sd_s_ctrl,
0893 };
0894
0895 static int sd_init_controls(struct gspca_dev *gspca_dev)
0896 {
0897 struct sd *sd = (struct sd *)gspca_dev;
0898 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
0899
0900 gspca_dev->vdev.ctrl_handler = hdl;
0901 v4l2_ctrl_handler_init(hdl, 3);
0902 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0903 V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4);
0904 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0905 V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c);
0906 sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0907 V4L2_CID_SATURATION, 0, 7, 1, 3);
0908 if (hdl->error) {
0909 pr_err("Could not initialize controls\n");
0910 return hdl->error;
0911 }
0912 return 0;
0913 }
0914
0915
0916 static const struct sd_desc sd_desc = {
0917 .name = MODULE_NAME,
0918 .config = sd_config,
0919 .init = sd_init,
0920 .init_controls = sd_init_controls,
0921 .start = sd_start,
0922 .stop0 = sd_stop0,
0923 .pkt_scan = sd_pkt_scan,
0924 };
0925
0926
0927 static const struct usb_device_id device_table[] = {
0928 {USB_DEVICE(0x0572, 0x0041)},
0929 {}
0930 };
0931 MODULE_DEVICE_TABLE(usb, device_table);
0932
0933
0934 static int sd_probe(struct usb_interface *intf,
0935 const struct usb_device_id *id)
0936 {
0937 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
0938 THIS_MODULE);
0939 }
0940
0941 static struct usb_driver sd_driver = {
0942 .name = MODULE_NAME,
0943 .id_table = device_table,
0944 .probe = sd_probe,
0945 .disconnect = gspca_disconnect,
0946 #ifdef CONFIG_PM
0947 .suspend = gspca_suspend,
0948 .resume = gspca_resume,
0949 .reset_resume = gspca_resume,
0950 #endif
0951 };
0952
0953 module_usb_driver(sd_driver);