cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gl860-mi1320.c (18919B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* Subdriver for the GL860 chip with the MI1320 sensor
      3 * Author Olivier LORIN from own logs
      4 */
      5
      6/* Sensor : MI1320 */
      7
      8#include "gl860.h"
      9
     10static struct validx tbl_common[] = {
     11	{0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba51, 0x0066}, {0xba02, 0x00f1},
     12	{0xba05, 0x0067}, {0xba05, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
     13	{0xffff, 0xffff},
     14	{0xba00, 0x00f0}, {0xba02, 0x00f1}, {0xbafa, 0x0028}, {0xba02, 0x00f1},
     15	{0xba00, 0x00f0}, {0xba01, 0x00f1}, {0xbaf0, 0x0006}, {0xba0e, 0x00f1},
     16	{0xba70, 0x0006}, {0xba0e, 0x00f1},
     17	{0xffff, 0xffff},
     18	{0xba74, 0x0006}, {0xba0e, 0x00f1},
     19	{0xffff, 0xffff},
     20	{0x0061, 0x0000}, {0x0068, 0x000d},
     21};
     22
     23static struct validx tbl_init_at_startup[] = {
     24	{0x0000, 0x0000}, {0x0010, 0x0010},
     25	{35, 0xffff},
     26	{0x0008, 0x00c0}, {0x0001, 0x00c1}, {0x0001, 0x00c2}, {0x0020, 0x0006},
     27	{0x006a, 0x000d},
     28};
     29
     30static struct validx tbl_sensor_settings_common[] = {
     31	{0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, {0x0040, 0x0000},
     32	{0x006a, 0x0007}, {0x006a, 0x000d}, {0x0063, 0x0006},
     33};
     34static struct validx tbl_sensor_settings_1280[] = {
     35	{0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1},
     36	{0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1},
     37};
     38static struct validx tbl_sensor_settings_800[] = {
     39	{0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1},
     40	{0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1},
     41};
     42static struct validx tbl_sensor_settings_640[] = {
     43	{0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
     44	{0xba51, 0x0066}, {0xba02, 0x00f1}, {0xba05, 0x0067}, {0xba05, 0x00f1},
     45	{0xba20, 0x0065}, {0xba00, 0x00f1},
     46};
     47static struct validx tbl_post_unset_alt[] = {
     48	{0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
     49	{0x0061, 0x0000}, {0x0068, 0x000d},
     50};
     51
     52static u8 *tbl_1280[] = {
     53	(u8[]){
     54		0x0d, 0x80, 0xf1, 0x08, 0x03, 0x04, 0xf1, 0x00,
     55		0x04, 0x05, 0xf1, 0x02, 0x05, 0x00, 0xf1, 0xf1,
     56		0x06, 0x00, 0xf1, 0x0d, 0x20, 0x01, 0xf1, 0x00,
     57		0x21, 0x84, 0xf1, 0x00, 0x0d, 0x00, 0xf1, 0x08,
     58		0xf0, 0x00, 0xf1, 0x01, 0x34, 0x00, 0xf1, 0x00,
     59		0x9b, 0x43, 0xf1, 0x00, 0xa6, 0x05, 0xf1, 0x00,
     60		0xa9, 0x04, 0xf1, 0x00, 0xa1, 0x05, 0xf1, 0x00,
     61		0xa4, 0x04, 0xf1, 0x00, 0xae, 0x0a, 0xf1, 0x08
     62	}, (u8[]){
     63		0xf0, 0x00, 0xf1, 0x02, 0x3a, 0x05, 0xf1, 0xf1,
     64		0x3c, 0x05, 0xf1, 0xf1, 0x59, 0x01, 0xf1, 0x47,
     65		0x5a, 0x01, 0xf1, 0x88, 0x5c, 0x0a, 0xf1, 0x06,
     66		0x5d, 0x0e, 0xf1, 0x0a, 0x64, 0x5e, 0xf1, 0x1c,
     67		0xd2, 0x00, 0xf1, 0xcf, 0xcb, 0x00, 0xf1, 0x01
     68	}, (u8[]){
     69		0xd3, 0x02, 0xd4, 0x28, 0xd5, 0x01, 0xd0, 0x02,
     70		0xd1, 0x18, 0xd2, 0xc1
     71	}
     72};
     73
     74static u8 *tbl_800[] = {
     75	(u8[]){
     76		0x0d, 0x80, 0xf1, 0x08, 0x03, 0x03, 0xf1, 0xc0,
     77		0x04, 0x05, 0xf1, 0x02, 0x05, 0x00, 0xf1, 0xf1,
     78		0x06, 0x00, 0xf1, 0x0d, 0x20, 0x01, 0xf1, 0x00,
     79		0x21, 0x84, 0xf1, 0x00, 0x0d, 0x00, 0xf1, 0x08,
     80		0xf0, 0x00, 0xf1, 0x01, 0x34, 0x00, 0xf1, 0x00,
     81		0x9b, 0x43, 0xf1, 0x00, 0xa6, 0x05, 0xf1, 0x00,
     82		0xa9, 0x03, 0xf1, 0xc0, 0xa1, 0x03, 0xf1, 0x20,
     83		0xa4, 0x02, 0xf1, 0x5a, 0xae, 0x0a, 0xf1, 0x08
     84	}, (u8[]){
     85		0xf0, 0x00, 0xf1, 0x02, 0x3a, 0x05, 0xf1, 0xf1,
     86		0x3c, 0x05, 0xf1, 0xf1, 0x59, 0x01, 0xf1, 0x47,
     87		0x5a, 0x01, 0xf1, 0x88, 0x5c, 0x0a, 0xf1, 0x06,
     88		0x5d, 0x0e, 0xf1, 0x0a, 0x64, 0x5e, 0xf1, 0x1c,
     89		0xd2, 0x00, 0xf1, 0xcf, 0xcb, 0x00, 0xf1, 0x01
     90	}, (u8[]){
     91		0xd3, 0x02, 0xd4, 0x18, 0xd5, 0x21, 0xd0, 0x02,
     92		0xd1, 0x10, 0xd2, 0x59
     93	}
     94};
     95
     96static u8 *tbl_640[] = {
     97	(u8[]){
     98		0x0d, 0x80, 0xf1, 0x08, 0x03, 0x04, 0xf1, 0x04,
     99		0x04, 0x05, 0xf1, 0x02, 0x07, 0x01, 0xf1, 0x7c,
    100		0x08, 0x00, 0xf1, 0x0e, 0x21, 0x80, 0xf1, 0x00,
    101		0x0d, 0x00, 0xf1, 0x08, 0xf0, 0x00, 0xf1, 0x01,
    102		0x34, 0x10, 0xf1, 0x10, 0x3a, 0x43, 0xf1, 0x00,
    103		0xa6, 0x05, 0xf1, 0x02, 0xa9, 0x04, 0xf1, 0x04,
    104		0xa7, 0x02, 0xf1, 0x81, 0xaa, 0x01, 0xf1, 0xe2,
    105		0xae, 0x0c, 0xf1, 0x09
    106	}, (u8[]){
    107		0xf0, 0x00, 0xf1, 0x02, 0x39, 0x03, 0xf1, 0xfc,
    108		0x3b, 0x04, 0xf1, 0x04, 0x57, 0x01, 0xf1, 0xb6,
    109		0x58, 0x02, 0xf1, 0x0d, 0x5c, 0x1f, 0xf1, 0x19,
    110		0x5d, 0x24, 0xf1, 0x1e, 0x64, 0x5e, 0xf1, 0x1c,
    111		0xd2, 0x00, 0xf1, 0x00, 0xcb, 0x00, 0xf1, 0x01
    112	}, (u8[]){
    113		0xd3, 0x02, 0xd4, 0x10, 0xd5, 0x81, 0xd0, 0x02,
    114		0xd1, 0x08, 0xd2, 0xe1
    115	}
    116};
    117
    118static s32 tbl_sat[] = {0x25, 0x1d, 0x15, 0x0d, 0x05, 0x4d, 0x55, 0x5d, 0x2d};
    119static s32 tbl_bright[] = {0, 8, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70};
    120static s32 tbl_backlight[] = {0x0e, 0x06, 0x02};
    121
    122static s32 tbl_cntr1[] = {
    123	0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xe0, 0xf0};
    124static s32 tbl_cntr2[] = {
    125	0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40, 0x38, 0x30, 0x20, 0x10};
    126
    127static u8 dat_wbalNL[] =
    128	"\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x3b\x04\xf1\x2a\x47\x10\xf1\x10"
    129	"\x9d\x3c\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\x91\xf1\x20"
    130	"\x9c\x91\xf1\x20\x37\x03\xf1\x00" "\x9d\xc5\xf1\x0f\xf0\x00\xf1\x00";
    131
    132static u8 dat_wbalLL[] =
    133	"\xf0\x00\xf1\x01\x05\x00\xf1\x0c" "\x3b\x04\xf1\x2a\x47\x40\xf1\x40"
    134	"\x9d\x20\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\xd1\xf1\x00"
    135	"\x9c\xd1\xf1\x00\x37\x03\xf1\x00" "\x9d\xc5\xf1\x3f\xf0\x00\xf1\x00";
    136
    137static u8 dat_wbalBL[] =
    138	"\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x47\x10\xf1\x30\x9d\x3c\xf1\xae"
    139	"\xaf\x10\xf1\x00\xf0\x00\xf1\x02" "\x2f\x91\xf1\x20\x9c\x91\xf1\x20"
    140	"\x37\x03\xf1\x00\x9d\xc5\xf1\x2f" "\xf0\x00\xf1\x00";
    141
    142static u8 dat_hvflip1[] = {0xf0, 0x00, 0xf1, 0x00};
    143
    144static u8 dat_common00[] =
    145	"\x00\x01\x07\x6a\x06\x63\x0d\x6a" "\xc0\x00\x10\x10\xc1\x03\xc2\x42"
    146	"\xd8\x04\x58\x00\x04\x02";
    147static u8 dat_common01[] =
    148	"\x0d\x00\xf1\x0b\x0d\x00\xf1\x08" "\x35\x00\xf1\x22\x68\x00\xf1\x5d"
    149	"\xf0\x00\xf1\x01\x06\x70\xf1\x0e" "\xf0\x00\xf1\x02\xdd\x18\xf1\xe0";
    150static u8 dat_common02[] =
    151	"\x05\x01\xf1\x84\x06\x00\xf1\x44" "\x07\x00\xf1\xbe\x08\x00\xf1\x1e"
    152	"\x20\x01\xf1\x03\x21\x84\xf1\x00" "\x22\x0d\xf1\x0f\x24\x80\xf1\x00"
    153	"\x34\x18\xf1\x2d\x35\x00\xf1\x22" "\x43\x83\xf1\x83\x59\x00\xf1\xff";
    154static u8 dat_common03[] =
    155	"\xf0\x00\xf1\x02\x39\x06\xf1\x8c" "\x3a\x06\xf1\x8c\x3b\x03\xf1\xda"
    156	"\x3c\x05\xf1\x30\x57\x01\xf1\x0c" "\x58\x01\xf1\x42\x59\x01\xf1\x0c"
    157	"\x5a\x01\xf1\x42\x5c\x13\xf1\x0e" "\x5d\x17\xf1\x12\x64\x1e\xf1\x1c";
    158static u8 dat_common04[] =
    159	"\xf0\x00\xf1\x02\x24\x5f\xf1\x20" "\x28\xea\xf1\x02\x5f\x41\xf1\x43";
    160static u8 dat_common05[] =
    161	"\x02\x00\xf1\xee\x03\x29\xf1\x1a" "\x04\x02\xf1\xa4\x09\x00\xf1\x68"
    162	"\x0a\x00\xf1\x2a\x0b\x00\xf1\x04" "\x0c\x00\xf1\x93\x0d\x00\xf1\x82"
    163	"\x0e\x00\xf1\x40\x0f\x00\xf1\x5f" "\x10\x00\xf1\x4e\x11\x00\xf1\x5b";
    164static u8 dat_common06[] =
    165	"\x15\x00\xf1\xc9\x16\x00\xf1\x5e" "\x17\x00\xf1\x9d\x18\x00\xf1\x06"
    166	"\x19\x00\xf1\x89\x1a\x00\xf1\x12" "\x1b\x00\xf1\xa1\x1c\x00\xf1\xe4"
    167	"\x1d\x00\xf1\x7a\x1e\x00\xf1\x64" "\xf6\x00\xf1\x5f";
    168static u8 dat_common07[] =
    169	"\xf0\x00\xf1\x01\x53\x09\xf1\x03" "\x54\x3d\xf1\x1c\x55\x99\xf1\x72"
    170	"\x56\xc1\xf1\xb1\x57\xd8\xf1\xce" "\x58\xe0\xf1\x00\xdc\x0a\xf1\x03"
    171	"\xdd\x45\xf1\x20\xde\xae\xf1\x82" "\xdf\xdc\xf1\xc9\xe0\xf6\xf1\xea"
    172	"\xe1\xff\xf1\x00";
    173static u8 dat_common08[] =
    174	"\xf0\x00\xf1\x01\x80\x00\xf1\x06" "\x81\xf6\xf1\x08\x82\xfb\xf1\xf7"
    175	"\x83\x00\xf1\xfe\xb6\x07\xf1\x03" "\xb7\x18\xf1\x0c\x84\xfb\xf1\x06"
    176	"\x85\xfb\xf1\xf9\x86\x00\xf1\xff" "\xb8\x07\xf1\x04\xb9\x16\xf1\x0a";
    177static u8 dat_common09[] =
    178	"\x87\xfa\xf1\x05\x88\xfc\xf1\xf9" "\x89\x00\xf1\xff\xba\x06\xf1\x03"
    179	"\xbb\x17\xf1\x09\x8a\xe8\xf1\x14" "\x8b\xf7\xf1\xf0\x8c\xfd\xf1\xfa"
    180	"\x8d\x00\xf1\x00\xbc\x05\xf1\x01" "\xbd\x0c\xf1\x08\xbe\x00\xf1\x14";
    181static u8 dat_common10[] =
    182	"\x8e\xea\xf1\x13\x8f\xf7\xf1\xf2" "\x90\xfd\xf1\xfa\x91\x00\xf1\x00"
    183	"\xbf\x05\xf1\x01\xc0\x0a\xf1\x08" "\xc1\x00\xf1\x0c\x92\xed\xf1\x0f"
    184	"\x93\xf9\xf1\xf4\x94\xfe\xf1\xfb" "\x95\x00\xf1\x00\xc2\x04\xf1\x01"
    185	"\xc3\x0a\xf1\x07\xc4\x00\xf1\x10";
    186static u8 dat_common11[] =
    187	"\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x25\x00\xf1\x55\x34\x10\xf1\x10"
    188	"\x35\xf0\xf1\x10\x3a\x02\xf1\x03" "\x3b\x04\xf1\x2a\x9b\x43\xf1\x00"
    189	"\xa4\x03\xf1\xc0\xa7\x02\xf1\x81";
    190
    191static int  mi1320_init_at_startup(struct gspca_dev *gspca_dev);
    192static int  mi1320_configure_alt(struct gspca_dev *gspca_dev);
    193static int  mi1320_init_pre_alt(struct gspca_dev *gspca_dev);
    194static int  mi1320_init_post_alt(struct gspca_dev *gspca_dev);
    195static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev);
    196static int  mi1320_sensor_settings(struct gspca_dev *gspca_dev);
    197static int  mi1320_camera_settings(struct gspca_dev *gspca_dev);
    198/*==========================================================================*/
    199
    200void mi1320_init_settings(struct gspca_dev *gspca_dev)
    201{
    202	struct sd *sd = (struct sd *) gspca_dev;
    203
    204	sd->vcur.backlight  =  0;
    205	sd->vcur.brightness =  0;
    206	sd->vcur.sharpness  =  6;
    207	sd->vcur.contrast   = 10;
    208	sd->vcur.gamma      = 20;
    209	sd->vcur.hue        =  0;
    210	sd->vcur.saturation =  6;
    211	sd->vcur.whitebal   =  0;
    212	sd->vcur.mirror     = 0;
    213	sd->vcur.flip       = 0;
    214	sd->vcur.AC50Hz     = 1;
    215
    216	sd->vmax.backlight  =  2;
    217	sd->vmax.brightness =  8;
    218	sd->vmax.sharpness  =  7;
    219	sd->vmax.contrast   =  0; /* 10 but not working with this driver */
    220	sd->vmax.gamma      = 40;
    221	sd->vmax.hue        =  5 + 1;
    222	sd->vmax.saturation =  8;
    223	sd->vmax.whitebal   =  2;
    224	sd->vmax.mirror     = 1;
    225	sd->vmax.flip       = 1;
    226	sd->vmax.AC50Hz     = 1;
    227
    228	sd->dev_camera_settings = mi1320_camera_settings;
    229	sd->dev_init_at_startup = mi1320_init_at_startup;
    230	sd->dev_configure_alt   = mi1320_configure_alt;
    231	sd->dev_init_pre_alt    = mi1320_init_pre_alt;
    232	sd->dev_post_unset_alt  = mi1320_post_unset_alt;
    233}
    234
    235/*==========================================================================*/
    236
    237static void common(struct gspca_dev *gspca_dev)
    238{
    239	s32 n; /* reserved for FETCH functions */
    240
    241	ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 22, dat_common00);
    242	ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL);
    243	ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 32, dat_common01);
    244	n = fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common));
    245	ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common02);
    246	ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common03);
    247	ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 16, dat_common04);
    248	ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common05);
    249	ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 44, dat_common06);
    250	keep_on_fetching_validx(gspca_dev, tbl_common,
    251					ARRAY_SIZE(tbl_common), n);
    252	ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 52, dat_common07);
    253	ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common08);
    254	ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common09);
    255	ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 56, dat_common10);
    256	keep_on_fetching_validx(gspca_dev, tbl_common,
    257					ARRAY_SIZE(tbl_common), n);
    258	ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, dat_common11);
    259	keep_on_fetching_validx(gspca_dev, tbl_common,
    260					ARRAY_SIZE(tbl_common), n);
    261}
    262
    263static int mi1320_init_at_startup(struct gspca_dev *gspca_dev)
    264{
    265	fetch_validx(gspca_dev, tbl_init_at_startup,
    266				ARRAY_SIZE(tbl_init_at_startup));
    267
    268	common(gspca_dev);
    269
    270/*	ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */
    271
    272	return 0;
    273}
    274
    275static int mi1320_init_pre_alt(struct gspca_dev *gspca_dev)
    276{
    277	struct sd *sd = (struct sd *) gspca_dev;
    278
    279	sd->mirrorMask = 0;
    280
    281	sd->vold.backlight  = -1;
    282	sd->vold.brightness = -1;
    283	sd->vold.sharpness  = -1;
    284	sd->vold.contrast   = -1;
    285	sd->vold.saturation = -1;
    286	sd->vold.gamma    = -1;
    287	sd->vold.hue      = -1;
    288	sd->vold.whitebal = -1;
    289	sd->vold.mirror   = -1;
    290	sd->vold.flip     = -1;
    291	sd->vold.AC50Hz   = -1;
    292
    293	common(gspca_dev);
    294
    295	mi1320_sensor_settings(gspca_dev);
    296
    297	mi1320_init_post_alt(gspca_dev);
    298
    299	return 0;
    300}
    301
    302static int mi1320_init_post_alt(struct gspca_dev *gspca_dev)
    303{
    304	mi1320_camera_settings(gspca_dev);
    305
    306	return 0;
    307}
    308
    309static int mi1320_sensor_settings(struct gspca_dev *gspca_dev)
    310{
    311	s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
    312
    313	ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
    314
    315	fetch_validx(gspca_dev, tbl_sensor_settings_common,
    316				ARRAY_SIZE(tbl_sensor_settings_common));
    317
    318	switch (reso) {
    319	case IMAGE_1280:
    320		fetch_validx(gspca_dev, tbl_sensor_settings_1280,
    321					ARRAY_SIZE(tbl_sensor_settings_1280));
    322		ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_1280[0]);
    323		ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_1280[1]);
    324		ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_1280[2]);
    325		break;
    326
    327	case IMAGE_800:
    328		fetch_validx(gspca_dev, tbl_sensor_settings_800,
    329					ARRAY_SIZE(tbl_sensor_settings_800));
    330		ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_800[0]);
    331		ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_800[1]);
    332		ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_800[2]);
    333		break;
    334
    335	default:
    336		fetch_validx(gspca_dev, tbl_sensor_settings_640,
    337					ARRAY_SIZE(tbl_sensor_settings_640));
    338		ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 60, tbl_640[0]);
    339		ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_640[1]);
    340		ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_640[2]);
    341		break;
    342	}
    343	return 0;
    344}
    345
    346static int mi1320_configure_alt(struct gspca_dev *gspca_dev)
    347{
    348	s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
    349
    350	switch (reso) {
    351	case IMAGE_640:
    352		gspca_dev->alt = 3 + 1;
    353		break;
    354
    355	case IMAGE_800:
    356	case IMAGE_1280:
    357		gspca_dev->alt = 1 + 1;
    358		break;
    359	}
    360	return 0;
    361}
    362
    363static int mi1320_camera_settings(struct gspca_dev *gspca_dev)
    364{
    365	struct sd *sd = (struct sd *) gspca_dev;
    366
    367	s32 backlight = sd->vcur.backlight;
    368	s32 bright = sd->vcur.brightness;
    369	s32 sharp  = sd->vcur.sharpness;
    370	s32 cntr   = sd->vcur.contrast;
    371	s32 gam	   = sd->vcur.gamma;
    372	s32 hue    = sd->vcur.hue;
    373	s32 sat	   = sd->vcur.saturation;
    374	s32 wbal   = sd->vcur.whitebal;
    375	s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
    376	s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
    377	s32 freq   = (sd->vcur.AC50Hz > 0);
    378	s32 i;
    379
    380	if (freq != sd->vold.AC50Hz) {
    381		sd->vold.AC50Hz = freq;
    382
    383		freq = 2 * (freq == 0);
    384		ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
    385		ctrl_out(gspca_dev, 0x40, 1, 0xba02, 0x00f1, 0, NULL);
    386		ctrl_out(gspca_dev, 0x40, 1, 0xba00       , 0x005b, 0, NULL);
    387		ctrl_out(gspca_dev, 0x40, 1, 0xba01 + freq, 0x00f1, 0, NULL);
    388	}
    389
    390	if (wbal != sd->vold.whitebal) {
    391		sd->vold.whitebal = wbal;
    392		if (wbal < 0 || wbal > sd->vmax.whitebal)
    393			wbal = 0;
    394
    395		for (i = 0; i < 2; i++) {
    396			if (wbal == 0) { /* Normal light */
    397				ctrl_out(gspca_dev, 0x40, 1,
    398						0x0010, 0x0010, 0, NULL);
    399				ctrl_out(gspca_dev, 0x40, 1,
    400						0x0003, 0x00c1, 0, NULL);
    401				ctrl_out(gspca_dev, 0x40, 1,
    402						0x0042, 0x00c2, 0, NULL);
    403				ctrl_out(gspca_dev, 0x40, 3,
    404						0xba00, 0x0200, 48, dat_wbalNL);
    405			}
    406
    407			if (wbal == 1) { /* Low light */
    408				ctrl_out(gspca_dev, 0x40, 1,
    409						0x0010, 0x0010, 0, NULL);
    410				ctrl_out(gspca_dev, 0x40, 1,
    411						0x0004, 0x00c1, 0, NULL);
    412				ctrl_out(gspca_dev, 0x40, 1,
    413						0x0043, 0x00c2, 0, NULL);
    414				ctrl_out(gspca_dev, 0x40, 3,
    415						0xba00, 0x0200, 48, dat_wbalLL);
    416			}
    417
    418			if (wbal == 2) { /* Back light */
    419				ctrl_out(gspca_dev, 0x40, 1,
    420						0x0010, 0x0010, 0, NULL);
    421				ctrl_out(gspca_dev, 0x40, 1,
    422						0x0003, 0x00c1, 0, NULL);
    423				ctrl_out(gspca_dev, 0x40, 1,
    424						0x0042, 0x00c2, 0, NULL);
    425				ctrl_out(gspca_dev, 0x40, 3,
    426						0xba00, 0x0200, 44, dat_wbalBL);
    427			}
    428		}
    429	}
    430
    431	if (bright != sd->vold.brightness) {
    432		sd->vold.brightness = bright;
    433		if (bright < 0 || bright > sd->vmax.brightness)
    434			bright = 0;
    435
    436		bright = tbl_bright[bright];
    437		ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
    438		ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
    439		ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x0034, 0, NULL);
    440		ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x00f1, 0, NULL);
    441	}
    442
    443	if (sat != sd->vold.saturation) {
    444		sd->vold.saturation = sat;
    445		if (sat < 0 || sat > sd->vmax.saturation)
    446			sat = 0;
    447
    448		sat = tbl_sat[sat];
    449		ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
    450		ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
    451		ctrl_out(gspca_dev, 0x40, 1, 0xba00      , 0x0025, 0, NULL);
    452		ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sat, 0x00f1, 0, NULL);
    453	}
    454
    455	if (sharp != sd->vold.sharpness) {
    456		sd->vold.sharpness = sharp;
    457		if (sharp < 0 || sharp > sd->vmax.sharpness)
    458			sharp = 0;
    459
    460		ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
    461		ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
    462		ctrl_out(gspca_dev, 0x40, 1, 0xba00        , 0x0005, 0, NULL);
    463		ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sharp, 0x00f1, 0, NULL);
    464	}
    465
    466	if (hue != sd->vold.hue) {
    467		/* 0=normal  1=NB  2="sepia"  3=negative  4=other  5=other2 */
    468		if (hue < 0 || hue > sd->vmax.hue)
    469			hue = 0;
    470		if (hue == sd->vmax.hue)
    471			sd->swapRB = 1;
    472		else
    473			sd->swapRB = 0;
    474
    475		ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
    476		ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
    477		ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL);
    478		ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1,
    479							0, NULL);
    480	}
    481
    482	if (backlight != sd->vold.backlight) {
    483		sd->vold.backlight = backlight;
    484		if (backlight < 0 || backlight > sd->vmax.backlight)
    485			backlight = 0;
    486
    487		backlight = tbl_backlight[backlight];
    488		for (i = 0; i < 2; i++) {
    489			ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
    490			ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
    491			ctrl_out(gspca_dev, 0x40, 1, 0xba74, 0x0006, 0, NULL);
    492			ctrl_out(gspca_dev, 0x40, 1, 0xba80 + backlight, 0x00f1,
    493								0, NULL);
    494		}
    495	}
    496
    497	if (hue != sd->vold.hue) {
    498		sd->vold.hue = hue;
    499
    500		ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
    501		ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
    502		ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL);
    503		ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1,
    504							0, NULL);
    505	}
    506
    507	if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
    508		u8 dat_hvflip2[4] = {0x20, 0x01, 0xf1, 0x00};
    509		sd->vold.mirror = mirror;
    510		sd->vold.flip = flip;
    511
    512		dat_hvflip2[3] = flip + 2 * mirror;
    513		ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip1);
    514		ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip2);
    515	}
    516
    517	if (gam != sd->vold.gamma) {
    518		sd->vold.gamma = gam;
    519		if (gam < 0 || gam > sd->vmax.gamma)
    520			gam = 0;
    521
    522		gam = 2 * gam;
    523		ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
    524		ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
    525		ctrl_out(gspca_dev, 0x40, 1, 0xba04      , 0x003b, 0, NULL);
    526		ctrl_out(gspca_dev, 0x40, 1, 0xba02 + gam, 0x00f1, 0, NULL);
    527	}
    528
    529	if (cntr != sd->vold.contrast) {
    530		sd->vold.contrast = cntr;
    531		if (cntr < 0 || cntr > sd->vmax.contrast)
    532			cntr = 0;
    533
    534		ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
    535		ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
    536		ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr1[cntr], 0x0035,
    537							0, NULL);
    538		ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr2[cntr], 0x00f1,
    539							0, NULL);
    540	}
    541
    542	return 0;
    543}
    544
    545static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev)
    546{
    547	ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
    548
    549	fetch_validx(gspca_dev, tbl_post_unset_alt,
    550				ARRAY_SIZE(tbl_post_unset_alt));
    551}