Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* Subdriver for the GL860 chip with the MI1320 sensor
0003  * Author Olivier LORIN from own logs
0004  */
0005 
0006 /* Sensor : MI1320 */
0007 
0008 #include "gl860.h"
0009 
0010 static struct validx tbl_common[] = {
0011     {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba51, 0x0066}, {0xba02, 0x00f1},
0012     {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
0013     {0xffff, 0xffff},
0014     {0xba00, 0x00f0}, {0xba02, 0x00f1}, {0xbafa, 0x0028}, {0xba02, 0x00f1},
0015     {0xba00, 0x00f0}, {0xba01, 0x00f1}, {0xbaf0, 0x0006}, {0xba0e, 0x00f1},
0016     {0xba70, 0x0006}, {0xba0e, 0x00f1},
0017     {0xffff, 0xffff},
0018     {0xba74, 0x0006}, {0xba0e, 0x00f1},
0019     {0xffff, 0xffff},
0020     {0x0061, 0x0000}, {0x0068, 0x000d},
0021 };
0022 
0023 static struct validx tbl_init_at_startup[] = {
0024     {0x0000, 0x0000}, {0x0010, 0x0010},
0025     {35, 0xffff},
0026     {0x0008, 0x00c0}, {0x0001, 0x00c1}, {0x0001, 0x00c2}, {0x0020, 0x0006},
0027     {0x006a, 0x000d},
0028 };
0029 
0030 static struct validx tbl_sensor_settings_common[] = {
0031     {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, {0x0040, 0x0000},
0032     {0x006a, 0x0007}, {0x006a, 0x000d}, {0x0063, 0x0006},
0033 };
0034 static struct validx tbl_sensor_settings_1280[] = {
0035     {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1},
0036     {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1},
0037 };
0038 static struct validx tbl_sensor_settings_800[] = {
0039     {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1},
0040     {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1},
0041 };
0042 static struct validx tbl_sensor_settings_640[] = {
0043     {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
0044     {0xba51, 0x0066}, {0xba02, 0x00f1}, {0xba05, 0x0067}, {0xba05, 0x00f1},
0045     {0xba20, 0x0065}, {0xba00, 0x00f1},
0046 };
0047 static struct validx tbl_post_unset_alt[] = {
0048     {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
0049     {0x0061, 0x0000}, {0x0068, 0x000d},
0050 };
0051 
0052 static u8 *tbl_1280[] = {
0053     (u8[]){
0054         0x0d, 0x80, 0xf1, 0x08, 0x03, 0x04, 0xf1, 0x00,
0055         0x04, 0x05, 0xf1, 0x02, 0x05, 0x00, 0xf1, 0xf1,
0056         0x06, 0x00, 0xf1, 0x0d, 0x20, 0x01, 0xf1, 0x00,
0057         0x21, 0x84, 0xf1, 0x00, 0x0d, 0x00, 0xf1, 0x08,
0058         0xf0, 0x00, 0xf1, 0x01, 0x34, 0x00, 0xf1, 0x00,
0059         0x9b, 0x43, 0xf1, 0x00, 0xa6, 0x05, 0xf1, 0x00,
0060         0xa9, 0x04, 0xf1, 0x00, 0xa1, 0x05, 0xf1, 0x00,
0061         0xa4, 0x04, 0xf1, 0x00, 0xae, 0x0a, 0xf1, 0x08
0062     }, (u8[]){
0063         0xf0, 0x00, 0xf1, 0x02, 0x3a, 0x05, 0xf1, 0xf1,
0064         0x3c, 0x05, 0xf1, 0xf1, 0x59, 0x01, 0xf1, 0x47,
0065         0x5a, 0x01, 0xf1, 0x88, 0x5c, 0x0a, 0xf1, 0x06,
0066         0x5d, 0x0e, 0xf1, 0x0a, 0x64, 0x5e, 0xf1, 0x1c,
0067         0xd2, 0x00, 0xf1, 0xcf, 0xcb, 0x00, 0xf1, 0x01
0068     }, (u8[]){
0069         0xd3, 0x02, 0xd4, 0x28, 0xd5, 0x01, 0xd0, 0x02,
0070         0xd1, 0x18, 0xd2, 0xc1
0071     }
0072 };
0073 
0074 static u8 *tbl_800[] = {
0075     (u8[]){
0076         0x0d, 0x80, 0xf1, 0x08, 0x03, 0x03, 0xf1, 0xc0,
0077         0x04, 0x05, 0xf1, 0x02, 0x05, 0x00, 0xf1, 0xf1,
0078         0x06, 0x00, 0xf1, 0x0d, 0x20, 0x01, 0xf1, 0x00,
0079         0x21, 0x84, 0xf1, 0x00, 0x0d, 0x00, 0xf1, 0x08,
0080         0xf0, 0x00, 0xf1, 0x01, 0x34, 0x00, 0xf1, 0x00,
0081         0x9b, 0x43, 0xf1, 0x00, 0xa6, 0x05, 0xf1, 0x00,
0082         0xa9, 0x03, 0xf1, 0xc0, 0xa1, 0x03, 0xf1, 0x20,
0083         0xa4, 0x02, 0xf1, 0x5a, 0xae, 0x0a, 0xf1, 0x08
0084     }, (u8[]){
0085         0xf0, 0x00, 0xf1, 0x02, 0x3a, 0x05, 0xf1, 0xf1,
0086         0x3c, 0x05, 0xf1, 0xf1, 0x59, 0x01, 0xf1, 0x47,
0087         0x5a, 0x01, 0xf1, 0x88, 0x5c, 0x0a, 0xf1, 0x06,
0088         0x5d, 0x0e, 0xf1, 0x0a, 0x64, 0x5e, 0xf1, 0x1c,
0089         0xd2, 0x00, 0xf1, 0xcf, 0xcb, 0x00, 0xf1, 0x01
0090     }, (u8[]){
0091         0xd3, 0x02, 0xd4, 0x18, 0xd5, 0x21, 0xd0, 0x02,
0092         0xd1, 0x10, 0xd2, 0x59
0093     }
0094 };
0095 
0096 static u8 *tbl_640[] = {
0097     (u8[]){
0098         0x0d, 0x80, 0xf1, 0x08, 0x03, 0x04, 0xf1, 0x04,
0099         0x04, 0x05, 0xf1, 0x02, 0x07, 0x01, 0xf1, 0x7c,
0100         0x08, 0x00, 0xf1, 0x0e, 0x21, 0x80, 0xf1, 0x00,
0101         0x0d, 0x00, 0xf1, 0x08, 0xf0, 0x00, 0xf1, 0x01,
0102         0x34, 0x10, 0xf1, 0x10, 0x3a, 0x43, 0xf1, 0x00,
0103         0xa6, 0x05, 0xf1, 0x02, 0xa9, 0x04, 0xf1, 0x04,
0104         0xa7, 0x02, 0xf1, 0x81, 0xaa, 0x01, 0xf1, 0xe2,
0105         0xae, 0x0c, 0xf1, 0x09
0106     }, (u8[]){
0107         0xf0, 0x00, 0xf1, 0x02, 0x39, 0x03, 0xf1, 0xfc,
0108         0x3b, 0x04, 0xf1, 0x04, 0x57, 0x01, 0xf1, 0xb6,
0109         0x58, 0x02, 0xf1, 0x0d, 0x5c, 0x1f, 0xf1, 0x19,
0110         0x5d, 0x24, 0xf1, 0x1e, 0x64, 0x5e, 0xf1, 0x1c,
0111         0xd2, 0x00, 0xf1, 0x00, 0xcb, 0x00, 0xf1, 0x01
0112     }, (u8[]){
0113         0xd3, 0x02, 0xd4, 0x10, 0xd5, 0x81, 0xd0, 0x02,
0114         0xd1, 0x08, 0xd2, 0xe1
0115     }
0116 };
0117 
0118 static s32 tbl_sat[] = {0x25, 0x1d, 0x15, 0x0d, 0x05, 0x4d, 0x55, 0x5d, 0x2d};
0119 static s32 tbl_bright[] = {0, 8, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70};
0120 static s32 tbl_backlight[] = {0x0e, 0x06, 0x02};
0121 
0122 static s32 tbl_cntr1[] = {
0123     0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xe0, 0xf0};
0124 static s32 tbl_cntr2[] = {
0125     0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40, 0x38, 0x30, 0x20, 0x10};
0126 
0127 static u8 dat_wbalNL[] =
0128     "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x3b\x04\xf1\x2a\x47\x10\xf1\x10"
0129     "\x9d\x3c\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\x91\xf1\x20"
0130     "\x9c\x91\xf1\x20\x37\x03\xf1\x00" "\x9d\xc5\xf1\x0f\xf0\x00\xf1\x00";
0131 
0132 static u8 dat_wbalLL[] =
0133     "\xf0\x00\xf1\x01\x05\x00\xf1\x0c" "\x3b\x04\xf1\x2a\x47\x40\xf1\x40"
0134     "\x9d\x20\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\xd1\xf1\x00"
0135     "\x9c\xd1\xf1\x00\x37\x03\xf1\x00" "\x9d\xc5\xf1\x3f\xf0\x00\xf1\x00";
0136 
0137 static u8 dat_wbalBL[] =
0138     "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x47\x10\xf1\x30\x9d\x3c\xf1\xae"
0139     "\xaf\x10\xf1\x00\xf0\x00\xf1\x02" "\x2f\x91\xf1\x20\x9c\x91\xf1\x20"
0140     "\x37\x03\xf1\x00\x9d\xc5\xf1\x2f" "\xf0\x00\xf1\x00";
0141 
0142 static u8 dat_hvflip1[] = {0xf0, 0x00, 0xf1, 0x00};
0143 
0144 static u8 dat_common00[] =
0145     "\x00\x01\x07\x6a\x06\x63\x0d\x6a" "\xc0\x00\x10\x10\xc1\x03\xc2\x42"
0146     "\xd8\x04\x58\x00\x04\x02";
0147 static u8 dat_common01[] =
0148     "\x0d\x00\xf1\x0b\x0d\x00\xf1\x08" "\x35\x00\xf1\x22\x68\x00\xf1\x5d"
0149     "\xf0\x00\xf1\x01\x06\x70\xf1\x0e" "\xf0\x00\xf1\x02\xdd\x18\xf1\xe0";
0150 static u8 dat_common02[] =
0151     "\x05\x01\xf1\x84\x06\x00\xf1\x44" "\x07\x00\xf1\xbe\x08\x00\xf1\x1e"
0152     "\x20\x01\xf1\x03\x21\x84\xf1\x00" "\x22\x0d\xf1\x0f\x24\x80\xf1\x00"
0153     "\x34\x18\xf1\x2d\x35\x00\xf1\x22" "\x43\x83\xf1\x83\x59\x00\xf1\xff";
0154 static u8 dat_common03[] =
0155     "\xf0\x00\xf1\x02\x39\x06\xf1\x8c" "\x3a\x06\xf1\x8c\x3b\x03\xf1\xda"
0156     "\x3c\x05\xf1\x30\x57\x01\xf1\x0c" "\x58\x01\xf1\x42\x59\x01\xf1\x0c"
0157     "\x5a\x01\xf1\x42\x5c\x13\xf1\x0e" "\x5d\x17\xf1\x12\x64\x1e\xf1\x1c";
0158 static u8 dat_common04[] =
0159     "\xf0\x00\xf1\x02\x24\x5f\xf1\x20" "\x28\xea\xf1\x02\x5f\x41\xf1\x43";
0160 static u8 dat_common05[] =
0161     "\x02\x00\xf1\xee\x03\x29\xf1\x1a" "\x04\x02\xf1\xa4\x09\x00\xf1\x68"
0162     "\x0a\x00\xf1\x2a\x0b\x00\xf1\x04" "\x0c\x00\xf1\x93\x0d\x00\xf1\x82"
0163     "\x0e\x00\xf1\x40\x0f\x00\xf1\x5f" "\x10\x00\xf1\x4e\x11\x00\xf1\x5b";
0164 static u8 dat_common06[] =
0165     "\x15\x00\xf1\xc9\x16\x00\xf1\x5e" "\x17\x00\xf1\x9d\x18\x00\xf1\x06"
0166     "\x19\x00\xf1\x89\x1a\x00\xf1\x12" "\x1b\x00\xf1\xa1\x1c\x00\xf1\xe4"
0167     "\x1d\x00\xf1\x7a\x1e\x00\xf1\x64" "\xf6\x00\xf1\x5f";
0168 static u8 dat_common07[] =
0169     "\xf0\x00\xf1\x01\x53\x09\xf1\x03" "\x54\x3d\xf1\x1c\x55\x99\xf1\x72"
0170     "\x56\xc1\xf1\xb1\x57\xd8\xf1\xce" "\x58\xe0\xf1\x00\xdc\x0a\xf1\x03"
0171     "\xdd\x45\xf1\x20\xde\xae\xf1\x82" "\xdf\xdc\xf1\xc9\xe0\xf6\xf1\xea"
0172     "\xe1\xff\xf1\x00";
0173 static u8 dat_common08[] =
0174     "\xf0\x00\xf1\x01\x80\x00\xf1\x06" "\x81\xf6\xf1\x08\x82\xfb\xf1\xf7"
0175     "\x83\x00\xf1\xfe\xb6\x07\xf1\x03" "\xb7\x18\xf1\x0c\x84\xfb\xf1\x06"
0176     "\x85\xfb\xf1\xf9\x86\x00\xf1\xff" "\xb8\x07\xf1\x04\xb9\x16\xf1\x0a";
0177 static u8 dat_common09[] =
0178     "\x87\xfa\xf1\x05\x88\xfc\xf1\xf9" "\x89\x00\xf1\xff\xba\x06\xf1\x03"
0179     "\xbb\x17\xf1\x09\x8a\xe8\xf1\x14" "\x8b\xf7\xf1\xf0\x8c\xfd\xf1\xfa"
0180     "\x8d\x00\xf1\x00\xbc\x05\xf1\x01" "\xbd\x0c\xf1\x08\xbe\x00\xf1\x14";
0181 static u8 dat_common10[] =
0182     "\x8e\xea\xf1\x13\x8f\xf7\xf1\xf2" "\x90\xfd\xf1\xfa\x91\x00\xf1\x00"
0183     "\xbf\x05\xf1\x01\xc0\x0a\xf1\x08" "\xc1\x00\xf1\x0c\x92\xed\xf1\x0f"
0184     "\x93\xf9\xf1\xf4\x94\xfe\xf1\xfb" "\x95\x00\xf1\x00\xc2\x04\xf1\x01"
0185     "\xc3\x0a\xf1\x07\xc4\x00\xf1\x10";
0186 static u8 dat_common11[] =
0187     "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x25\x00\xf1\x55\x34\x10\xf1\x10"
0188     "\x35\xf0\xf1\x10\x3a\x02\xf1\x03" "\x3b\x04\xf1\x2a\x9b\x43\xf1\x00"
0189     "\xa4\x03\xf1\xc0\xa7\x02\xf1\x81";
0190 
0191 static int  mi1320_init_at_startup(struct gspca_dev *gspca_dev);
0192 static int  mi1320_configure_alt(struct gspca_dev *gspca_dev);
0193 static int  mi1320_init_pre_alt(struct gspca_dev *gspca_dev);
0194 static int  mi1320_init_post_alt(struct gspca_dev *gspca_dev);
0195 static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev);
0196 static int  mi1320_sensor_settings(struct gspca_dev *gspca_dev);
0197 static int  mi1320_camera_settings(struct gspca_dev *gspca_dev);
0198 /*==========================================================================*/
0199 
0200 void mi1320_init_settings(struct gspca_dev *gspca_dev)
0201 {
0202     struct sd *sd = (struct sd *) gspca_dev;
0203 
0204     sd->vcur.backlight  =  0;
0205     sd->vcur.brightness =  0;
0206     sd->vcur.sharpness  =  6;
0207     sd->vcur.contrast   = 10;
0208     sd->vcur.gamma      = 20;
0209     sd->vcur.hue        =  0;
0210     sd->vcur.saturation =  6;
0211     sd->vcur.whitebal   =  0;
0212     sd->vcur.mirror     = 0;
0213     sd->vcur.flip       = 0;
0214     sd->vcur.AC50Hz     = 1;
0215 
0216     sd->vmax.backlight  =  2;
0217     sd->vmax.brightness =  8;
0218     sd->vmax.sharpness  =  7;
0219     sd->vmax.contrast   =  0; /* 10 but not working with this driver */
0220     sd->vmax.gamma      = 40;
0221     sd->vmax.hue        =  5 + 1;
0222     sd->vmax.saturation =  8;
0223     sd->vmax.whitebal   =  2;
0224     sd->vmax.mirror     = 1;
0225     sd->vmax.flip       = 1;
0226     sd->vmax.AC50Hz     = 1;
0227 
0228     sd->dev_camera_settings = mi1320_camera_settings;
0229     sd->dev_init_at_startup = mi1320_init_at_startup;
0230     sd->dev_configure_alt   = mi1320_configure_alt;
0231     sd->dev_init_pre_alt    = mi1320_init_pre_alt;
0232     sd->dev_post_unset_alt  = mi1320_post_unset_alt;
0233 }
0234 
0235 /*==========================================================================*/
0236 
0237 static void common(struct gspca_dev *gspca_dev)
0238 {
0239     s32 n; /* reserved for FETCH functions */
0240 
0241     ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 22, dat_common00);
0242     ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL);
0243     ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 32, dat_common01);
0244     n = fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common));
0245     ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common02);
0246     ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common03);
0247     ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 16, dat_common04);
0248     ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common05);
0249     ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 44, dat_common06);
0250     keep_on_fetching_validx(gspca_dev, tbl_common,
0251                     ARRAY_SIZE(tbl_common), n);
0252     ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 52, dat_common07);
0253     ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common08);
0254     ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common09);
0255     ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 56, dat_common10);
0256     keep_on_fetching_validx(gspca_dev, tbl_common,
0257                     ARRAY_SIZE(tbl_common), n);
0258     ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, dat_common11);
0259     keep_on_fetching_validx(gspca_dev, tbl_common,
0260                     ARRAY_SIZE(tbl_common), n);
0261 }
0262 
0263 static int mi1320_init_at_startup(struct gspca_dev *gspca_dev)
0264 {
0265     fetch_validx(gspca_dev, tbl_init_at_startup,
0266                 ARRAY_SIZE(tbl_init_at_startup));
0267 
0268     common(gspca_dev);
0269 
0270 /*  ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */
0271 
0272     return 0;
0273 }
0274 
0275 static int mi1320_init_pre_alt(struct gspca_dev *gspca_dev)
0276 {
0277     struct sd *sd = (struct sd *) gspca_dev;
0278 
0279     sd->mirrorMask = 0;
0280 
0281     sd->vold.backlight  = -1;
0282     sd->vold.brightness = -1;
0283     sd->vold.sharpness  = -1;
0284     sd->vold.contrast   = -1;
0285     sd->vold.saturation = -1;
0286     sd->vold.gamma    = -1;
0287     sd->vold.hue      = -1;
0288     sd->vold.whitebal = -1;
0289     sd->vold.mirror   = -1;
0290     sd->vold.flip     = -1;
0291     sd->vold.AC50Hz   = -1;
0292 
0293     common(gspca_dev);
0294 
0295     mi1320_sensor_settings(gspca_dev);
0296 
0297     mi1320_init_post_alt(gspca_dev);
0298 
0299     return 0;
0300 }
0301 
0302 static int mi1320_init_post_alt(struct gspca_dev *gspca_dev)
0303 {
0304     mi1320_camera_settings(gspca_dev);
0305 
0306     return 0;
0307 }
0308 
0309 static int mi1320_sensor_settings(struct gspca_dev *gspca_dev)
0310 {
0311     s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
0312 
0313     ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
0314 
0315     fetch_validx(gspca_dev, tbl_sensor_settings_common,
0316                 ARRAY_SIZE(tbl_sensor_settings_common));
0317 
0318     switch (reso) {
0319     case IMAGE_1280:
0320         fetch_validx(gspca_dev, tbl_sensor_settings_1280,
0321                     ARRAY_SIZE(tbl_sensor_settings_1280));
0322         ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_1280[0]);
0323         ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_1280[1]);
0324         ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_1280[2]);
0325         break;
0326 
0327     case IMAGE_800:
0328         fetch_validx(gspca_dev, tbl_sensor_settings_800,
0329                     ARRAY_SIZE(tbl_sensor_settings_800));
0330         ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_800[0]);
0331         ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_800[1]);
0332         ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_800[2]);
0333         break;
0334 
0335     default:
0336         fetch_validx(gspca_dev, tbl_sensor_settings_640,
0337                     ARRAY_SIZE(tbl_sensor_settings_640));
0338         ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 60, tbl_640[0]);
0339         ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_640[1]);
0340         ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_640[2]);
0341         break;
0342     }
0343     return 0;
0344 }
0345 
0346 static int mi1320_configure_alt(struct gspca_dev *gspca_dev)
0347 {
0348     s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
0349 
0350     switch (reso) {
0351     case IMAGE_640:
0352         gspca_dev->alt = 3 + 1;
0353         break;
0354 
0355     case IMAGE_800:
0356     case IMAGE_1280:
0357         gspca_dev->alt = 1 + 1;
0358         break;
0359     }
0360     return 0;
0361 }
0362 
0363 static int mi1320_camera_settings(struct gspca_dev *gspca_dev)
0364 {
0365     struct sd *sd = (struct sd *) gspca_dev;
0366 
0367     s32 backlight = sd->vcur.backlight;
0368     s32 bright = sd->vcur.brightness;
0369     s32 sharp  = sd->vcur.sharpness;
0370     s32 cntr   = sd->vcur.contrast;
0371     s32 gam    = sd->vcur.gamma;
0372     s32 hue    = sd->vcur.hue;
0373     s32 sat    = sd->vcur.saturation;
0374     s32 wbal   = sd->vcur.whitebal;
0375     s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
0376     s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
0377     s32 freq   = (sd->vcur.AC50Hz > 0);
0378     s32 i;
0379 
0380     if (freq != sd->vold.AC50Hz) {
0381         sd->vold.AC50Hz = freq;
0382 
0383         freq = 2 * (freq == 0);
0384         ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
0385         ctrl_out(gspca_dev, 0x40, 1, 0xba02, 0x00f1, 0, NULL);
0386         ctrl_out(gspca_dev, 0x40, 1, 0xba00       , 0x005b, 0, NULL);
0387         ctrl_out(gspca_dev, 0x40, 1, 0xba01 + freq, 0x00f1, 0, NULL);
0388     }
0389 
0390     if (wbal != sd->vold.whitebal) {
0391         sd->vold.whitebal = wbal;
0392         if (wbal < 0 || wbal > sd->vmax.whitebal)
0393             wbal = 0;
0394 
0395         for (i = 0; i < 2; i++) {
0396             if (wbal == 0) { /* Normal light */
0397                 ctrl_out(gspca_dev, 0x40, 1,
0398                         0x0010, 0x0010, 0, NULL);
0399                 ctrl_out(gspca_dev, 0x40, 1,
0400                         0x0003, 0x00c1, 0, NULL);
0401                 ctrl_out(gspca_dev, 0x40, 1,
0402                         0x0042, 0x00c2, 0, NULL);
0403                 ctrl_out(gspca_dev, 0x40, 3,
0404                         0xba00, 0x0200, 48, dat_wbalNL);
0405             }
0406 
0407             if (wbal == 1) { /* Low light */
0408                 ctrl_out(gspca_dev, 0x40, 1,
0409                         0x0010, 0x0010, 0, NULL);
0410                 ctrl_out(gspca_dev, 0x40, 1,
0411                         0x0004, 0x00c1, 0, NULL);
0412                 ctrl_out(gspca_dev, 0x40, 1,
0413                         0x0043, 0x00c2, 0, NULL);
0414                 ctrl_out(gspca_dev, 0x40, 3,
0415                         0xba00, 0x0200, 48, dat_wbalLL);
0416             }
0417 
0418             if (wbal == 2) { /* Back light */
0419                 ctrl_out(gspca_dev, 0x40, 1,
0420                         0x0010, 0x0010, 0, NULL);
0421                 ctrl_out(gspca_dev, 0x40, 1,
0422                         0x0003, 0x00c1, 0, NULL);
0423                 ctrl_out(gspca_dev, 0x40, 1,
0424                         0x0042, 0x00c2, 0, NULL);
0425                 ctrl_out(gspca_dev, 0x40, 3,
0426                         0xba00, 0x0200, 44, dat_wbalBL);
0427             }
0428         }
0429     }
0430 
0431     if (bright != sd->vold.brightness) {
0432         sd->vold.brightness = bright;
0433         if (bright < 0 || bright > sd->vmax.brightness)
0434             bright = 0;
0435 
0436         bright = tbl_bright[bright];
0437         ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
0438         ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
0439         ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x0034, 0, NULL);
0440         ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x00f1, 0, NULL);
0441     }
0442 
0443     if (sat != sd->vold.saturation) {
0444         sd->vold.saturation = sat;
0445         if (sat < 0 || sat > sd->vmax.saturation)
0446             sat = 0;
0447 
0448         sat = tbl_sat[sat];
0449         ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
0450         ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
0451         ctrl_out(gspca_dev, 0x40, 1, 0xba00      , 0x0025, 0, NULL);
0452         ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sat, 0x00f1, 0, NULL);
0453     }
0454 
0455     if (sharp != sd->vold.sharpness) {
0456         sd->vold.sharpness = sharp;
0457         if (sharp < 0 || sharp > sd->vmax.sharpness)
0458             sharp = 0;
0459 
0460         ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
0461         ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
0462         ctrl_out(gspca_dev, 0x40, 1, 0xba00        , 0x0005, 0, NULL);
0463         ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sharp, 0x00f1, 0, NULL);
0464     }
0465 
0466     if (hue != sd->vold.hue) {
0467         /* 0=normal  1=NB  2="sepia"  3=negative  4=other  5=other2 */
0468         if (hue < 0 || hue > sd->vmax.hue)
0469             hue = 0;
0470         if (hue == sd->vmax.hue)
0471             sd->swapRB = 1;
0472         else
0473             sd->swapRB = 0;
0474 
0475         ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
0476         ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
0477         ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL);
0478         ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1,
0479                             0, NULL);
0480     }
0481 
0482     if (backlight != sd->vold.backlight) {
0483         sd->vold.backlight = backlight;
0484         if (backlight < 0 || backlight > sd->vmax.backlight)
0485             backlight = 0;
0486 
0487         backlight = tbl_backlight[backlight];
0488         for (i = 0; i < 2; i++) {
0489             ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
0490             ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
0491             ctrl_out(gspca_dev, 0x40, 1, 0xba74, 0x0006, 0, NULL);
0492             ctrl_out(gspca_dev, 0x40, 1, 0xba80 + backlight, 0x00f1,
0493                                 0, NULL);
0494         }
0495     }
0496 
0497     if (hue != sd->vold.hue) {
0498         sd->vold.hue = hue;
0499 
0500         ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
0501         ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
0502         ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL);
0503         ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1,
0504                             0, NULL);
0505     }
0506 
0507     if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
0508         u8 dat_hvflip2[4] = {0x20, 0x01, 0xf1, 0x00};
0509         sd->vold.mirror = mirror;
0510         sd->vold.flip = flip;
0511 
0512         dat_hvflip2[3] = flip + 2 * mirror;
0513         ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip1);
0514         ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip2);
0515     }
0516 
0517     if (gam != sd->vold.gamma) {
0518         sd->vold.gamma = gam;
0519         if (gam < 0 || gam > sd->vmax.gamma)
0520             gam = 0;
0521 
0522         gam = 2 * gam;
0523         ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
0524         ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
0525         ctrl_out(gspca_dev, 0x40, 1, 0xba04      , 0x003b, 0, NULL);
0526         ctrl_out(gspca_dev, 0x40, 1, 0xba02 + gam, 0x00f1, 0, NULL);
0527     }
0528 
0529     if (cntr != sd->vold.contrast) {
0530         sd->vold.contrast = cntr;
0531         if (cntr < 0 || cntr > sd->vmax.contrast)
0532             cntr = 0;
0533 
0534         ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
0535         ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
0536         ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr1[cntr], 0x0035,
0537                             0, NULL);
0538         ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr2[cntr], 0x00f1,
0539                             0, NULL);
0540     }
0541 
0542     return 0;
0543 }
0544 
0545 static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev)
0546 {
0547     ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
0548 
0549     fetch_validx(gspca_dev, tbl_post_unset_alt,
0550                 ARRAY_SIZE(tbl_post_unset_alt));
0551 }