GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / media / usb / gspca / gl860 / gl860-mi1320.c
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
10 static 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
23 static 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
30 static struct validx tbl_sensor_settings_common[] = {
31         {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, {0x0040, 0x0000},
32         {0x006a, 0x0007}, {0x006a, 0x000d}, {0x0063, 0x0006},
33 };
34 static 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 };
38 static 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 };
42 static 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 };
47 static struct validx tbl_post_unset_alt[] = {
48         {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
49         {0x0061, 0x0000}, {0x0068, 0x000d},
50 };
51
52 static 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
74 static 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
96 static 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
118 static s32 tbl_sat[] = {0x25, 0x1d, 0x15, 0x0d, 0x05, 0x4d, 0x55, 0x5d, 0x2d};
119 static s32 tbl_bright[] = {0, 8, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70};
120 static s32 tbl_backlight[] = {0x0e, 0x06, 0x02};
121
122 static s32 tbl_cntr1[] = {
123         0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xe0, 0xf0};
124 static s32 tbl_cntr2[] = {
125         0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40, 0x38, 0x30, 0x20, 0x10};
126
127 static 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
132 static 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
137 static 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
142 static u8 dat_hvflip1[] = {0xf0, 0x00, 0xf1, 0x00};
143
144 static 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";
147 static 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";
150 static 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";
154 static 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";
158 static u8 dat_common04[] =
159         "\xf0\x00\xf1\x02\x24\x5f\xf1\x20" "\x28\xea\xf1\x02\x5f\x41\xf1\x43";
160 static 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";
164 static 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";
168 static 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";
173 static 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";
177 static 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";
181 static 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";
186 static 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
191 static int  mi1320_init_at_startup(struct gspca_dev *gspca_dev);
192 static int  mi1320_configure_alt(struct gspca_dev *gspca_dev);
193 static int  mi1320_init_pre_alt(struct gspca_dev *gspca_dev);
194 static int  mi1320_init_post_alt(struct gspca_dev *gspca_dev);
195 static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev);
196 static int  mi1320_sensor_settings(struct gspca_dev *gspca_dev);
197 static int  mi1320_camera_settings(struct gspca_dev *gspca_dev);
198 /*==========================================================================*/
199
200 void 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
237 static 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
263 static 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
275 static 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
302 static int mi1320_init_post_alt(struct gspca_dev *gspca_dev)
303 {
304         mi1320_camera_settings(gspca_dev);
305
306         return 0;
307 }
308
309 static 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
346 static 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
363 static 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
545 static 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 }