Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * SPCA505 chip based cameras initialization data
0004  *
0005  * V4L2 by Jean-Francis Moine <http://moinejf.free.fr>
0006  */
0007 
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009 
0010 #define MODULE_NAME "spca505"
0011 
0012 #include "gspca.h"
0013 
0014 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
0015 MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");
0016 MODULE_LICENSE("GPL");
0017 
0018 /* specific webcam descriptor */
0019 struct sd {
0020     struct gspca_dev gspca_dev;     /* !! must be the first item */
0021 
0022     u8 subtype;
0023 #define IntelPCCameraPro 0
0024 #define Nxultra 1
0025 };
0026 
0027 static const struct v4l2_pix_format vga_mode[] = {
0028     {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
0029         .bytesperline = 160,
0030         .sizeimage = 160 * 120 * 3 / 2,
0031         .colorspace = V4L2_COLORSPACE_SRGB,
0032         .priv = 4},
0033     {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
0034         .bytesperline = 176,
0035         .sizeimage = 176 * 144 * 3 / 2,
0036         .colorspace = V4L2_COLORSPACE_SRGB,
0037         .priv = 3},
0038     {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
0039         .bytesperline = 320,
0040         .sizeimage = 320 * 240 * 3 / 2,
0041         .colorspace = V4L2_COLORSPACE_SRGB,
0042         .priv = 2},
0043     {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
0044         .bytesperline = 352,
0045         .sizeimage = 352 * 288 * 3 / 2,
0046         .colorspace = V4L2_COLORSPACE_SRGB,
0047         .priv = 1},
0048     {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
0049         .bytesperline = 640,
0050         .sizeimage = 640 * 480 * 3 / 2,
0051         .colorspace = V4L2_COLORSPACE_SRGB,
0052         .priv = 0},
0053 };
0054 
0055 #define SPCA50X_OFFSET_DATA 10
0056 
0057 #define SPCA50X_REG_USB 0x02    /* spca505 501 */
0058 
0059 #define SPCA50X_USB_CTRL 0x00   /* spca505 */
0060 #define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
0061 
0062 #define SPCA50X_REG_GLOBAL 0x03 /* spca505 */
0063 #define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
0064 #define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
0065 
0066 #define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
0067 #define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
0068 #define SPCA50X_GMISC3_SAA7113RST 0x20  /* Not sure about this one spca505 */
0069 
0070 /* Image format and compression control */
0071 #define SPCA50X_REG_COMPRESS 0x04
0072 
0073 /*
0074  * Data to initialize a SPCA505. Common to the CCD and external modes
0075  */
0076 static const u8 spca505_init_data[][3] = {
0077     /* bmRequest,value,index */
0078     {SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
0079     /* Sensor reset */
0080     {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
0081     {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
0082     /* Block USB reset */
0083     {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0},
0084 
0085     {0x05, 0x01, 0x10},
0086                     /* Maybe power down some stuff */
0087     {0x05, 0x0f, 0x11},
0088 
0089     /* Setup internal CCD  ? */
0090     {0x06, 0x10, 0x08},
0091     {0x06, 0x00, 0x09},
0092     {0x06, 0x00, 0x0a},
0093     {0x06, 0x00, 0x0b},
0094     {0x06, 0x10, 0x0c},
0095     {0x06, 0x00, 0x0d},
0096     {0x06, 0x00, 0x0e},
0097     {0x06, 0x00, 0x0f},
0098     {0x06, 0x10, 0x10},
0099     {0x06, 0x02, 0x11},
0100     {0x06, 0x00, 0x12},
0101     {0x06, 0x04, 0x13},
0102     {0x06, 0x02, 0x14},
0103     {0x06, 0x8a, 0x51},
0104     {0x06, 0x40, 0x52},
0105     {0x06, 0xb6, 0x53},
0106     {0x06, 0x3d, 0x54},
0107     {}
0108 };
0109 
0110 /*
0111  * Data to initialize the camera using the internal CCD
0112  */
0113 static const u8 spca505_open_data_ccd[][3] = {
0114     /* bmRequest,value,index */
0115     /* Internal CCD data set */
0116     {0x03, 0x04, 0x01},
0117     /* This could be a reset */
0118     {0x03, 0x00, 0x01},
0119 
0120     /* Setup compression and image registers. 0x6 and 0x7 seem to be
0121        related to H&V hold, and are resolution mode specific */
0122         {0x04, 0x10, 0x01},
0123         /* DIFF(0x50), was (0x10) */
0124     {0x04, 0x00, 0x04},
0125     {0x04, 0x00, 0x05},
0126     {0x04, 0x20, 0x06},
0127     {0x04, 0x20, 0x07},
0128 
0129     {0x08, 0x0a, 0x00},
0130     /* DIFF (0x4a), was (0xa) */
0131 
0132     {0x05, 0x00, 0x10},
0133     {0x05, 0x00, 0x11},
0134     {0x05, 0x00, 0x00},
0135     /* DIFF not written */
0136     {0x05, 0x00, 0x01},
0137     /* DIFF not written */
0138     {0x05, 0x00, 0x02},
0139     /* DIFF not written */
0140     {0x05, 0x00, 0x03},
0141     /* DIFF not written */
0142     {0x05, 0x00, 0x04},
0143     /* DIFF not written */
0144         {0x05, 0x80, 0x05},
0145         /* DIFF not written */
0146         {0x05, 0xe0, 0x06},
0147         /* DIFF not written */
0148         {0x05, 0x20, 0x07},
0149         /* DIFF not written */
0150         {0x05, 0xa0, 0x08},
0151         /* DIFF not written */
0152         {0x05, 0x0, 0x12},
0153         /* DIFF not written */
0154     {0x05, 0x02, 0x0f},
0155     /* DIFF not written */
0156         {0x05, 0x10, 0x46},
0157         /* DIFF not written */
0158         {0x05, 0x8, 0x4a},
0159         /* DIFF not written */
0160 
0161     {0x03, 0x08, 0x03},
0162     /* DIFF (0x3,0x28,0x3) */
0163     {0x03, 0x08, 0x01},
0164     {0x03, 0x0c, 0x03},
0165     /* DIFF not written */
0166         {0x03, 0x21, 0x00},
0167         /* DIFF (0x39) */
0168 
0169 /* Extra block copied from init to hopefully ensure CCD is in a sane state */
0170     {0x06, 0x10, 0x08},
0171     {0x06, 0x00, 0x09},
0172     {0x06, 0x00, 0x0a},
0173     {0x06, 0x00, 0x0b},
0174     {0x06, 0x10, 0x0c},
0175     {0x06, 0x00, 0x0d},
0176     {0x06, 0x00, 0x0e},
0177     {0x06, 0x00, 0x0f},
0178     {0x06, 0x10, 0x10},
0179     {0x06, 0x02, 0x11},
0180     {0x06, 0x00, 0x12},
0181     {0x06, 0x04, 0x13},
0182     {0x06, 0x02, 0x14},
0183     {0x06, 0x8a, 0x51},
0184     {0x06, 0x40, 0x52},
0185     {0x06, 0xb6, 0x53},
0186     {0x06, 0x3d, 0x54},
0187     /* End of extra block */
0188 
0189         {0x06, 0x3f, 0x1},
0190         /* Block skipped */
0191     {0x06, 0x10, 0x02},
0192     {0x06, 0x64, 0x07},
0193     {0x06, 0x10, 0x08},
0194     {0x06, 0x00, 0x09},
0195     {0x06, 0x00, 0x0a},
0196     {0x06, 0x00, 0x0b},
0197     {0x06, 0x10, 0x0c},
0198     {0x06, 0x00, 0x0d},
0199     {0x06, 0x00, 0x0e},
0200     {0x06, 0x00, 0x0f},
0201     {0x06, 0x10, 0x10},
0202     {0x06, 0x02, 0x11},
0203     {0x06, 0x00, 0x12},
0204     {0x06, 0x04, 0x13},
0205     {0x06, 0x02, 0x14},
0206     {0x06, 0x8a, 0x51},
0207     {0x06, 0x40, 0x52},
0208     {0x06, 0xb6, 0x53},
0209     {0x06, 0x3d, 0x54},
0210     {0x06, 0x60, 0x57},
0211     {0x06, 0x20, 0x58},
0212     {0x06, 0x15, 0x59},
0213     {0x06, 0x05, 0x5a},
0214 
0215     {0x05, 0x01, 0xc0},
0216     {0x05, 0x10, 0xcb},
0217         {0x05, 0x80, 0xc1},
0218         /* */
0219         {0x05, 0x0, 0xc2},
0220         /* 4 was 0 */
0221     {0x05, 0x00, 0xca},
0222         {0x05, 0x80, 0xc1},
0223         /*  */
0224     {0x05, 0x04, 0xc2},
0225     {0x05, 0x00, 0xca},
0226         {0x05, 0x0, 0xc1},
0227         /*  */
0228     {0x05, 0x00, 0xc2},
0229     {0x05, 0x00, 0xca},
0230         {0x05, 0x40, 0xc1},
0231         /* */
0232     {0x05, 0x17, 0xc2},
0233     {0x05, 0x00, 0xca},
0234         {0x05, 0x80, 0xc1},
0235         /* */
0236     {0x05, 0x06, 0xc2},
0237     {0x05, 0x00, 0xca},
0238         {0x05, 0x80, 0xc1},
0239         /* */
0240     {0x05, 0x04, 0xc2},
0241     {0x05, 0x00, 0xca},
0242 
0243     {0x03, 0x4c, 0x3},
0244     {0x03, 0x18, 0x1},
0245 
0246     {0x06, 0x70, 0x51},
0247     {0x06, 0xbe, 0x53},
0248     {0x06, 0x71, 0x57},
0249     {0x06, 0x20, 0x58},
0250     {0x06, 0x05, 0x59},
0251     {0x06, 0x15, 0x5a},
0252 
0253     {0x04, 0x00, 0x08},
0254     /* Compress = OFF (0x1 to turn on) */
0255     {0x04, 0x12, 0x09},
0256     {0x04, 0x21, 0x0a},
0257     {0x04, 0x10, 0x0b},
0258     {0x04, 0x21, 0x0c},
0259     {0x04, 0x05, 0x00},
0260     /* was 5 (Image Type ? ) */
0261     {0x04, 0x00, 0x01},
0262 
0263     {0x06, 0x3f, 0x01},
0264 
0265     {0x04, 0x00, 0x04},
0266     {0x04, 0x00, 0x05},
0267     {0x04, 0x40, 0x06},
0268     {0x04, 0x40, 0x07},
0269 
0270     {0x06, 0x1c, 0x17},
0271     {0x06, 0xe2, 0x19},
0272     {0x06, 0x1c, 0x1b},
0273     {0x06, 0xe2, 0x1d},
0274     {0x06, 0xaa, 0x1f},
0275     {0x06, 0x70, 0x20},
0276 
0277     {0x05, 0x01, 0x10},
0278     {0x05, 0x00, 0x11},
0279     {0x05, 0x01, 0x00},
0280     {0x05, 0x05, 0x01},
0281         {0x05, 0x00, 0xc1},
0282         /* */
0283     {0x05, 0x00, 0xc2},
0284     {0x05, 0x00, 0xca},
0285 
0286     {0x06, 0x70, 0x51},
0287     {0x06, 0xbe, 0x53},
0288     {}
0289 };
0290 
0291 /*
0292  * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
0293  * SPCA505b chip based cameras initialization data
0294  */
0295 /* jfm */
0296 #define initial_brightness 0x7f /* 0x0(white)-0xff(black) */
0297 /* #define initial_brightness 0x0   //0x0(white)-0xff(black) */
0298 /*
0299  * Data to initialize a SPCA505. Common to the CCD and external modes
0300  */
0301 static const u8 spca505b_init_data[][3] = {
0302 /* start */
0303     {0x02, 0x00, 0x00},     /* init */
0304     {0x02, 0x00, 0x01},
0305     {0x02, 0x00, 0x02},
0306     {0x02, 0x00, 0x03},
0307     {0x02, 0x00, 0x04},
0308     {0x02, 0x00, 0x05},
0309     {0x02, 0x00, 0x06},
0310     {0x02, 0x00, 0x07},
0311     {0x02, 0x00, 0x08},
0312     {0x02, 0x00, 0x09},
0313     {0x03, 0x00, 0x00},
0314     {0x03, 0x00, 0x01},
0315     {0x03, 0x00, 0x02},
0316     {0x03, 0x00, 0x03},
0317     {0x03, 0x00, 0x04},
0318     {0x03, 0x00, 0x05},
0319     {0x03, 0x00, 0x06},
0320     {0x04, 0x00, 0x00},
0321     {0x04, 0x00, 0x02},
0322     {0x04, 0x00, 0x04},
0323     {0x04, 0x00, 0x05},
0324     {0x04, 0x00, 0x06},
0325     {0x04, 0x00, 0x07},
0326     {0x04, 0x00, 0x08},
0327     {0x04, 0x00, 0x09},
0328     {0x04, 0x00, 0x0a},
0329     {0x04, 0x00, 0x0b},
0330     {0x04, 0x00, 0x0c},
0331     {0x07, 0x00, 0x00},
0332     {0x07, 0x00, 0x03},
0333     {0x08, 0x00, 0x00},
0334     {0x08, 0x00, 0x01},
0335     {0x08, 0x00, 0x02},
0336     {0x06, 0x18, 0x08},
0337     {0x06, 0xfc, 0x09},
0338     {0x06, 0xfc, 0x0a},
0339     {0x06, 0xfc, 0x0b},
0340     {0x06, 0x18, 0x0c},
0341     {0x06, 0xfc, 0x0d},
0342     {0x06, 0xfc, 0x0e},
0343     {0x06, 0xfc, 0x0f},
0344     {0x06, 0x18, 0x10},
0345     {0x06, 0xfe, 0x12},
0346     {0x06, 0x00, 0x11},
0347     {0x06, 0x00, 0x14},
0348     {0x06, 0x00, 0x13},
0349     {0x06, 0x28, 0x51},
0350     {0x06, 0xff, 0x53},
0351     {0x02, 0x00, 0x08},
0352 
0353     {0x03, 0x00, 0x03},
0354     {0x03, 0x10, 0x03},
0355     {}
0356 };
0357 
0358 /*
0359  * Data to initialize the camera using the internal CCD
0360  */
0361 static const u8 spca505b_open_data_ccd[][3] = {
0362 
0363 /* {0x02,0x00,0x00}, */
0364     {0x03, 0x04, 0x01},     /* rst */
0365     {0x03, 0x00, 0x01},
0366     {0x03, 0x00, 0x00},
0367     {0x03, 0x21, 0x00},
0368     {0x03, 0x00, 0x04},
0369     {0x03, 0x00, 0x03},
0370     {0x03, 0x18, 0x03},
0371     {0x03, 0x08, 0x01},
0372     {0x03, 0x1c, 0x03},
0373     {0x03, 0x5c, 0x03},
0374     {0x03, 0x5c, 0x03},
0375     {0x03, 0x18, 0x01},
0376 
0377 /* same as 505 */
0378     {0x04, 0x10, 0x01},
0379     {0x04, 0x00, 0x04},
0380     {0x04, 0x00, 0x05},
0381     {0x04, 0x20, 0x06},
0382     {0x04, 0x20, 0x07},
0383 
0384     {0x08, 0x0a, 0x00},
0385 
0386     {0x05, 0x00, 0x10},
0387     {0x05, 0x00, 0x11},
0388     {0x05, 0x00, 0x12},
0389     {0x05, 0x6f, 0x00},
0390     {0x05, initial_brightness >> 6, 0x00},
0391     {0x05, (initial_brightness << 2) & 0xff, 0x01},
0392     {0x05, 0x00, 0x02},
0393     {0x05, 0x01, 0x03},
0394     {0x05, 0x00, 0x04},
0395     {0x05, 0x03, 0x05},
0396     {0x05, 0xe0, 0x06},
0397     {0x05, 0x20, 0x07},
0398     {0x05, 0xa0, 0x08},
0399     {0x05, 0x00, 0x12},
0400     {0x05, 0x02, 0x0f},
0401     {0x05, 0x80, 0x14},     /* max exposure off (0=on) */
0402     {0x05, 0x01, 0xb0},
0403     {0x05, 0x01, 0xbf},
0404     {0x03, 0x02, 0x06},
0405     {0x05, 0x10, 0x46},
0406     {0x05, 0x08, 0x4a},
0407 
0408     {0x06, 0x00, 0x01},
0409     {0x06, 0x10, 0x02},
0410     {0x06, 0x64, 0x07},
0411     {0x06, 0x18, 0x08},
0412     {0x06, 0xfc, 0x09},
0413     {0x06, 0xfc, 0x0a},
0414     {0x06, 0xfc, 0x0b},
0415     {0x04, 0x00, 0x01},
0416     {0x06, 0x18, 0x0c},
0417     {0x06, 0xfc, 0x0d},
0418     {0x06, 0xfc, 0x0e},
0419     {0x06, 0xfc, 0x0f},
0420     {0x06, 0x11, 0x10},     /* contrast */
0421     {0x06, 0x00, 0x11},
0422     {0x06, 0xfe, 0x12},
0423     {0x06, 0x00, 0x13},
0424     {0x06, 0x00, 0x14},
0425     {0x06, 0x9d, 0x51},
0426     {0x06, 0x40, 0x52},
0427     {0x06, 0x7c, 0x53},
0428     {0x06, 0x40, 0x54},
0429     {0x06, 0x02, 0x57},
0430     {0x06, 0x03, 0x58},
0431     {0x06, 0x15, 0x59},
0432     {0x06, 0x05, 0x5a},
0433     {0x06, 0x03, 0x56},
0434     {0x06, 0x02, 0x3f},
0435     {0x06, 0x00, 0x40},
0436     {0x06, 0x39, 0x41},
0437     {0x06, 0x69, 0x42},
0438     {0x06, 0x87, 0x43},
0439     {0x06, 0x9e, 0x44},
0440     {0x06, 0xb1, 0x45},
0441     {0x06, 0xbf, 0x46},
0442     {0x06, 0xcc, 0x47},
0443     {0x06, 0xd5, 0x48},
0444     {0x06, 0xdd, 0x49},
0445     {0x06, 0xe3, 0x4a},
0446     {0x06, 0xe8, 0x4b},
0447     {0x06, 0xed, 0x4c},
0448     {0x06, 0xf2, 0x4d},
0449     {0x06, 0xf7, 0x4e},
0450     {0x06, 0xfc, 0x4f},
0451     {0x06, 0xff, 0x50},
0452 
0453     {0x05, 0x01, 0xc0},
0454     {0x05, 0x10, 0xcb},
0455     {0x05, 0x40, 0xc1},
0456     {0x05, 0x04, 0xc2},
0457     {0x05, 0x00, 0xca},
0458     {0x05, 0x40, 0xc1},
0459     {0x05, 0x09, 0xc2},
0460     {0x05, 0x00, 0xca},
0461     {0x05, 0xc0, 0xc1},
0462     {0x05, 0x09, 0xc2},
0463     {0x05, 0x00, 0xca},
0464     {0x05, 0x40, 0xc1},
0465     {0x05, 0x59, 0xc2},
0466     {0x05, 0x00, 0xca},
0467     {0x04, 0x00, 0x01},
0468     {0x05, 0x80, 0xc1},
0469     {0x05, 0xec, 0xc2},
0470     {0x05, 0x0, 0xca},
0471 
0472     {0x06, 0x02, 0x57},
0473     {0x06, 0x01, 0x58},
0474     {0x06, 0x15, 0x59},
0475     {0x06, 0x0a, 0x5a},
0476     {0x06, 0x01, 0x57},
0477     {0x06, 0x8a, 0x03},
0478     {0x06, 0x0a, 0x6c},
0479     {0x06, 0x30, 0x01},
0480     {0x06, 0x20, 0x02},
0481     {0x06, 0x00, 0x03},
0482 
0483     {0x05, 0x8c, 0x25},
0484 
0485     {0x06, 0x4d, 0x51},     /* maybe saturation (4d) */
0486     {0x06, 0x84, 0x53},     /* making green (84) */
0487     {0x06, 0x00, 0x57},     /* sharpness (1) */
0488     {0x06, 0x18, 0x08},
0489     {0x06, 0xfc, 0x09},
0490     {0x06, 0xfc, 0x0a},
0491     {0x06, 0xfc, 0x0b},
0492     {0x06, 0x18, 0x0c},     /* maybe hue (18) */
0493     {0x06, 0xfc, 0x0d},
0494     {0x06, 0xfc, 0x0e},
0495     {0x06, 0xfc, 0x0f},
0496     {0x06, 0x18, 0x10},     /* maybe contrast (18) */
0497 
0498     {0x05, 0x01, 0x02},
0499 
0500     {0x04, 0x00, 0x08},     /* compression */
0501     {0x04, 0x12, 0x09},
0502     {0x04, 0x21, 0x0a},
0503     {0x04, 0x10, 0x0b},
0504     {0x04, 0x21, 0x0c},
0505     {0x04, 0x1d, 0x00},     /* imagetype (1d) */
0506     {0x04, 0x41, 0x01},     /* hardware snapcontrol */
0507 
0508     {0x04, 0x00, 0x04},
0509     {0x04, 0x00, 0x05},
0510     {0x04, 0x10, 0x06},
0511     {0x04, 0x10, 0x07},
0512     {0x04, 0x40, 0x06},
0513     {0x04, 0x40, 0x07},
0514     {0x04, 0x00, 0x04},
0515     {0x04, 0x00, 0x05},
0516 
0517     {0x06, 0x1c, 0x17},
0518     {0x06, 0xe2, 0x19},
0519     {0x06, 0x1c, 0x1b},
0520     {0x06, 0xe2, 0x1d},
0521     {0x06, 0x5f, 0x1f},
0522     {0x06, 0x32, 0x20},
0523 
0524     {0x05, initial_brightness >> 6, 0x00},
0525     {0x05, (initial_brightness << 2) & 0xff, 0x01},
0526     {0x05, 0x06, 0xc1},
0527     {0x05, 0x58, 0xc2},
0528     {0x05, 0x00, 0xca},
0529     {0x05, 0x00, 0x11},
0530     {}
0531 };
0532 
0533 static int reg_write(struct gspca_dev *gspca_dev,
0534              u16 req, u16 index, u16 value)
0535 {
0536     int ret;
0537     struct usb_device *dev = gspca_dev->dev;
0538 
0539     ret = usb_control_msg(dev,
0540             usb_sndctrlpipe(dev, 0),
0541             req,
0542             USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0543             value, index, NULL, 0, 500);
0544     gspca_dbg(gspca_dev, D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d\n",
0545           req, index, value, ret);
0546     if (ret < 0)
0547         pr_err("reg write: error %d\n", ret);
0548     return ret;
0549 }
0550 
0551 /* returns: negative is error, pos or zero is data */
0552 static int reg_read(struct gspca_dev *gspca_dev,
0553             u16 req,    /* bRequest */
0554             u16 index)  /* wIndex */
0555 {
0556     int ret;
0557 
0558     ret = usb_control_msg(gspca_dev->dev,
0559             usb_rcvctrlpipe(gspca_dev->dev, 0),
0560             req,
0561             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0562             0,          /* value */
0563             index,
0564             gspca_dev->usb_buf, 2,
0565             500);           /* timeout */
0566     if (ret < 0)
0567         return ret;
0568     return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
0569 }
0570 
0571 static int write_vector(struct gspca_dev *gspca_dev,
0572             const u8 data[][3])
0573 {
0574     int ret, i = 0;
0575 
0576     while (data[i][0] != 0) {
0577         ret = reg_write(gspca_dev, data[i][0], data[i][2],
0578                                 data[i][1]);
0579         if (ret < 0)
0580             return ret;
0581         i++;
0582     }
0583     return 0;
0584 }
0585 
0586 /* this function is called at probe time */
0587 static int sd_config(struct gspca_dev *gspca_dev,
0588             const struct usb_device_id *id)
0589 {
0590     struct sd *sd = (struct sd *) gspca_dev;
0591     struct cam *cam;
0592 
0593     cam = &gspca_dev->cam;
0594     cam->cam_mode = vga_mode;
0595     sd->subtype = id->driver_info;
0596     if (sd->subtype != IntelPCCameraPro)
0597         cam->nmodes = ARRAY_SIZE(vga_mode);
0598     else            /* no 640x480 for IntelPCCameraPro */
0599         cam->nmodes = ARRAY_SIZE(vga_mode) - 1;
0600 
0601     return 0;
0602 }
0603 
0604 /* this function is called at probe and resume time */
0605 static int sd_init(struct gspca_dev *gspca_dev)
0606 {
0607     struct sd *sd = (struct sd *) gspca_dev;
0608 
0609     if (write_vector(gspca_dev,
0610              sd->subtype == Nxultra
0611                 ? spca505b_init_data
0612                 : spca505_init_data))
0613         return -EIO;
0614     return 0;
0615 }
0616 
0617 static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
0618 {
0619     reg_write(gspca_dev, 0x05, 0x00, (255 - brightness) >> 6);
0620     reg_write(gspca_dev, 0x05, 0x01, (255 - brightness) << 2);
0621 }
0622 
0623 static int sd_start(struct gspca_dev *gspca_dev)
0624 {
0625     struct sd *sd = (struct sd *) gspca_dev;
0626     int ret, mode;
0627     static u8 mode_tb[][3] = {
0628     /*    r00   r06   r07   */
0629         {0x00, 0x10, 0x10}, /* 640x480 */
0630         {0x01, 0x1a, 0x1a}, /* 352x288 */
0631         {0x02, 0x1c, 0x1d}, /* 320x240 */
0632         {0x04, 0x34, 0x34}, /* 176x144 */
0633         {0x05, 0x40, 0x40}  /* 160x120 */
0634     };
0635 
0636     if (sd->subtype == Nxultra)
0637         write_vector(gspca_dev, spca505b_open_data_ccd);
0638     else
0639         write_vector(gspca_dev, spca505_open_data_ccd);
0640     ret = reg_read(gspca_dev, 0x06, 0x16);
0641 
0642     if (ret < 0) {
0643         gspca_err(gspca_dev, "register read failed err: %d\n", ret);
0644         return ret;
0645     }
0646     if (ret != 0x0101) {
0647         pr_err("After vector read returns 0x%04x should be 0x0101\n",
0648                ret);
0649     }
0650 
0651     ret = reg_write(gspca_dev, 0x06, 0x16, 0x0a);
0652     if (ret < 0)
0653         return ret;
0654     reg_write(gspca_dev, 0x05, 0xc2, 0x12);
0655 
0656     /* necessary because without it we can see stream
0657      * only once after loading module */
0658     /* stopping usb registers Tomasz change */
0659     reg_write(gspca_dev, 0x02, 0x00, 0x00);
0660 
0661     mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
0662     reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
0663     reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
0664     reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
0665 
0666     return reg_write(gspca_dev, SPCA50X_REG_USB,
0667              SPCA50X_USB_CTRL,
0668              SPCA50X_CUSB_ENABLE);
0669 }
0670 
0671 static void sd_stopN(struct gspca_dev *gspca_dev)
0672 {
0673     /* Disable ISO packet machine */
0674     reg_write(gspca_dev, 0x02, 0x00, 0x00);
0675 }
0676 
0677 /* called on streamoff with alt 0 and on disconnect */
0678 static void sd_stop0(struct gspca_dev *gspca_dev)
0679 {
0680     if (!gspca_dev->present)
0681         return;
0682 
0683     /* This maybe reset or power control */
0684     reg_write(gspca_dev, 0x03, 0x03, 0x20);
0685     reg_write(gspca_dev, 0x03, 0x01, 0x00);
0686     reg_write(gspca_dev, 0x03, 0x00, 0x01);
0687     reg_write(gspca_dev, 0x05, 0x10, 0x01);
0688     reg_write(gspca_dev, 0x05, 0x11, 0x0f);
0689 }
0690 
0691 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
0692             u8 *data,           /* isoc packet */
0693             int len)            /* iso packet length */
0694 {
0695     switch (data[0]) {
0696     case 0:             /* start of frame */
0697         gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
0698         data += SPCA50X_OFFSET_DATA;
0699         len -= SPCA50X_OFFSET_DATA;
0700         gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
0701         break;
0702     case 0xff:          /* drop */
0703         break;
0704     default:
0705         data += 1;
0706         len -= 1;
0707         gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
0708         break;
0709     }
0710 }
0711 
0712 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
0713 {
0714     struct gspca_dev *gspca_dev =
0715         container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0716 
0717     gspca_dev->usb_err = 0;
0718 
0719     if (!gspca_dev->streaming)
0720         return 0;
0721 
0722     switch (ctrl->id) {
0723     case V4L2_CID_BRIGHTNESS:
0724         setbrightness(gspca_dev, ctrl->val);
0725         break;
0726     }
0727     return gspca_dev->usb_err;
0728 }
0729 
0730 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
0731     .s_ctrl = sd_s_ctrl,
0732 };
0733 
0734 static int sd_init_controls(struct gspca_dev *gspca_dev)
0735 {
0736     struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
0737 
0738     gspca_dev->vdev.ctrl_handler = hdl;
0739     v4l2_ctrl_handler_init(hdl, 5);
0740     v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0741             V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
0742 
0743     if (hdl->error) {
0744         pr_err("Could not initialize controls\n");
0745         return hdl->error;
0746     }
0747     return 0;
0748 }
0749 
0750 /* sub-driver description */
0751 static const struct sd_desc sd_desc = {
0752     .name = MODULE_NAME,
0753     .config = sd_config,
0754     .init_controls = sd_init_controls,
0755     .init = sd_init,
0756     .start = sd_start,
0757     .stopN = sd_stopN,
0758     .stop0 = sd_stop0,
0759     .pkt_scan = sd_pkt_scan,
0760 };
0761 
0762 /* -- module initialisation -- */
0763 static const struct usb_device_id device_table[] = {
0764     {USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},
0765     {USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},
0766 /*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
0767     {}
0768 };
0769 MODULE_DEVICE_TABLE(usb, device_table);
0770 
0771 /* -- device connect -- */
0772 static int sd_probe(struct usb_interface *intf,
0773             const struct usb_device_id *id)
0774 {
0775     return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
0776                 THIS_MODULE);
0777 }
0778 
0779 static struct usb_driver sd_driver = {
0780     .name = MODULE_NAME,
0781     .id_table = device_table,
0782     .probe = sd_probe,
0783     .disconnect = gspca_disconnect,
0784 #ifdef CONFIG_PM
0785     .suspend = gspca_suspend,
0786     .resume = gspca_resume,
0787     .reset_resume = gspca_resume,
0788 #endif
0789 };
0790 
0791 module_usb_driver(sd_driver);