Merge commit 'v2.6.33-rc5' into secretlab/test-devicetree
[sfrench/cifs-2.6.git] / drivers / media / video / gspca / gl860 / gl860-mi2020.c
1 /* Subdriver for the GL860 chip with the MI2020 sensor
2  * Author Olivier LORIN, from Ice/Soro2005's logs(A), Fret_saw/Hulkie's
3  * logs(B) and Tricid"s logs(C). With the help of Kytrix/BUGabundo/Blazercist.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 /* Sensor : MI2020 */
20
21 #include "gl860.h"
22
23 static u8 dat_bright1[] = {0x8c, 0xa2, 0x06};
24 static u8 dat_bright3[] = {0x8c, 0xa1, 0x02};
25 static u8 dat_bright4[] = {0x90, 0x00, 0x0f};
26 static u8 dat_bright5[] = {0x8c, 0xa1, 0x03};
27 static u8 dat_bright6[] = {0x90, 0x00, 0x05};
28
29 static u8 dat_dummy1[] = {0x90, 0x00, 0x06};
30 /*static u8 dummy2[] = {0x8c, 0xa1, 0x02};*/
31 /*static u8 dummy3[] = {0x90, 0x00, 0x1f};*/
32
33 static u8 dat_hvflip1[] = {0x8c, 0x27, 0x19};
34 static u8 dat_hvflip3[] = {0x8c, 0x27, 0x3b};
35 static u8 dat_hvflip5[] = {0x8c, 0xa1, 0x03};
36 static u8 dat_hvflip6[] = {0x90, 0x00, 0x06};
37
38 static u8 dat_freq1[] = { 0x8c, 0xa4, 0x04 };
39
40 static u8 dat_multi5[] = { 0x8c, 0xa1, 0x03 };
41 static u8 dat_multi6[] = { 0x90, 0x00, 0x05 };
42
43 static struct validx tbl_common1[] = {
44         {0x0000, 0x0000},
45         {1, 0xffff}, /* msleep(35); */
46         {0x006a, 0x0007}, {0x0063, 0x0006}, {0x006a, 0x000d}, {0x0000, 0x00c0},
47         {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, {0x0004, 0x00d8},
48         {0x0000, 0x0058}, {0x0002, 0x0004}, {0x0041, 0x0000},
49 };
50
51 static struct validx tbl_common2[] = {
52         {0x006a, 0x0007},
53         {35, 0xffff},
54         {0x00ef, 0x0006},
55         {35, 0xffff},
56         {0x006a, 0x000d},
57         {35, 0xffff},
58         {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2},
59         {0x0004, 0x00d8}, {0x0000, 0x0058}, {0x0041, 0x0000},
60 };
61
62 static struct idxdata tbl_common3[] = {
63         {0x32, "\x02\x00\x08"}, {0x33, "\xf4\x03\x1d"},
64         {6, "\xff\xff\xff"}, /* 12 */
65         {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
66         {2, "\xff\xff\xff"}, /* - */
67         {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\x22\x23"},
68         {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0f"}, {0x33, "\x90\x00\x0d"},
69         {0x33, "\x8c\xa2\x10"}, {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x11"},
70         {0x33, "\x90\x00\x07"}, {0x33, "\xf4\x03\x1d"}, {0x35, "\xa2\x00\xe2"},
71         {0x33, "\x8c\xab\x05"}, {0x33, "\x90\x00\x01"}, {0x32, "\x6e\x00\x86"},
72         {0x32, "\x70\x0f\xaa"}, {0x32, "\x72\x0f\xe4"}, {0x33, "\x8c\xa3\x4a"},
73         {0x33, "\x90\x00\x5a"}, {0x33, "\x8c\xa3\x4b"}, {0x33, "\x90\x00\xa6"},
74         {0x33, "\x8c\xa3\x61"}, {0x33, "\x90\x00\xc8"}, {0x33, "\x8c\xa3\x62"},
75         {0x33, "\x90\x00\xe1"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"},
76         {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"},
77         {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"},
78         {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"},
79         {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"},
80         {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"},
81         {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"},
82         {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"},
83         {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"},
84         {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"},
85         {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"},
86         {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"},
87         {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"},
88         {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"},
89         {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"},
90         {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"},
91         {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"},
92         {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"},
93         {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"},
94         {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"},
95         {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"},
96         {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"},
97         {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"},
98         {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"},
99         {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"},
100         {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"},
101         {1, "\xff\xff\xff"},
102         {0x33, "\x78\x00\x00"},
103         {1, "\xff\xff\xff"},
104         {0x35, "\xb8\x1f\x20"}, {0x33, "\x8c\xa2\x06"}, {0x33, "\x90\x00\x10"},
105         {0x33, "\x8c\xa2\x07"}, {0x33, "\x90\x00\x08"}, {0x33, "\x8c\xa2\x42"},
106         {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x4a"}, {0x33, "\x90\x00\x8c"},
107         {0x35, "\xba\xfa\x08"}, {0x33, "\x8c\xa2\x02"}, {0x33, "\x90\x00\x22"},
108         {0x33, "\x8c\xa2\x03"}, {0x33, "\x90\x00\xbb"},
109 };
110
111 static struct idxdata tbl_common4[] = {
112         {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa0"}, {0x33, "\x8c\xa4\x08"},
113         {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x21"},
114         {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\xa4\x0b"},
115         {0x33, "\x90\x00\x27"}, {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\xa0"},
116         {0x33, "\x8c\x24\x13"}, {0x33, "\x90\x00\xc0"}, {0x33, "\x8c\x24\x15"},
117         {0x33, "\x90\x00\xa0"}, {0x33, "\x8c\x24\x17"}, {0x33, "\x90\x00\xc0"},
118 };
119
120 static struct idxdata tbl_common5[] = {
121         {0x33, "\x8c\xa4\x04"}, {0x33, "\x90\x00\x80"}, {0x33, "\x8c\xa7\x9d"},
122         {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa7\x9e"}, {0x33, "\x90\x00\x00"},
123         {0x33, "\x8c\xa2\x0c"}, {0x33, "\x90\x00\x17"}, {0x33, "\x8c\xa2\x15"},
124         {0x33, "\x90\x00\x04"}, {0x33, "\x8c\xa2\x14"}, {0x33, "\x90\x00\x20"},
125         {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"},
126         /* msleep(53); */
127         {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x1b"}, {0x33, "\x90\x02\x4f"},
128         {0x33, "\x8c\x27\x25"}, {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x39"},
129         {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"},
130         {0x33, "\x8c\x27\x47"}, {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x03"},
131         {0x33, "\x90\x02\x84"}, {0x33, "\x8c\x27\x05"}, {0x33, "\x90\x01\xe2"},
132         {0x33, "\x8c\x27\x07"}, {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x09"},
133         {0x33, "\x90\x04\xb0"}, {0x33, "\x8c\x27\x0d"}, {0x33, "\x90\x00\x00"},
134         {0x33, "\x8c\x27\x0f"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x11"},
135         {0x33, "\x90\x04\xbd"}, {0x33, "\x8c\x27\x13"}, {0x33, "\x90\x06\x4d"},
136         {0x33, "\x8c\x27\x15"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"},
137         {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x19"}, {0x33, "\x90\x04\x6c"},
138         {0x33, "\x8c\x27\x1b"}, {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x1d"},
139         {0x33, "\x90\x01\x02"}, {0x33, "\x8c\x27\x1f"}, {0x33, "\x90\x02\x79"},
140         {0x33, "\x8c\x27\x21"}, {0x33, "\x90\x01\x55"}, {0x33, "\x8c\x27\x23"},
141         {0x33, "\x90\x02\x85"}, {0x33, "\x8c\x27\x25"}, {0x33, "\x90\x06\x0f"},
142         {0x33, "\x8c\x27\x27"}, {0x33, "\x90\x20\x20"}, {0x33, "\x8c\x27\x29"},
143         {0x33, "\x90\x20\x20"}, {0x33, "\x8c\x27\x2b"}, {0x33, "\x90\x10\x20"},
144         {0x33, "\x8c\x27\x2d"}, {0x33, "\x90\x20\x07"}, {0x33, "\x8c\x27\x2f"},
145         {0x33, "\x90\x00\x04"}, {0x33, "\x8c\x27\x31"}, {0x33, "\x90\x00\x04"},
146         {0x33, "\x8c\x27\x33"}, {0x33, "\x90\x04\xbb"}, {0x33, "\x8c\x27\x35"},
147         {0x33, "\x90\x06\x4b"}, {0x33, "\x8c\x27\x37"}, {0x33, "\x90\x00\x00"},
148         {0x33, "\x8c\x27\x39"}, {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x3b"},
149         {0x33, "\x90\x00\x24"}, {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"},
150         {0x33, "\x8c\x27\x41"}, {0x33, "\x90\x01\x69"}, {0x33, "\x8c\x27\x45"},
151         {0x33, "\x90\x04\xed"}, {0x33, "\x8c\x27\x47"}, {0x33, "\x90\x09\x4c"},
152         {0x33, "\x8c\x27\x51"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x53"},
153         {0x33, "\x90\x03\x20"}, {0x33, "\x8c\x27\x55"}, {0x33, "\x90\x00\x00"},
154         {0x33, "\x8c\x27\x57"}, {0x33, "\x90\x02\x58"}, {0x33, "\x8c\x27\x5f"},
155         {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x61"}, {0x33, "\x90\x06\x40"},
156         {0x33, "\x8c\x27\x63"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x65"},
157         {0x33, "\x90\x04\xb0"}, {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa1"},
158         {0x33, "\x8c\xa4\x08"}, {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"},
159         {0x33, "\x90\x00\x21"}, {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"},
160         {0x33, "\x8c\xa4\x0b"}, {0x33, "\x90\x00\x27"}, {0x33, "\x8c\x24\x11"},
161         {0x33, "\x90\x00\xa1"}, {0x33, "\x8c\x24\x13"}, {0x33, "\x90\x00\xc1"},
162         {0x33, "\x8c\x24\x15"},
163 };
164
165 static struct validx tbl_init_at_startup[] = {
166         {0x0000, 0x0000},
167         {53, 0xffff},
168         {0x0010, 0x0010},
169         {53, 0xffff},
170         {0x0008, 0x00c0},
171         {53, 0xffff},
172         {0x0001, 0x00c1},
173         {53, 0xffff},
174         {0x0001, 0x00c2},
175         {53, 0xffff},
176         {0x0020, 0x0006},
177         {53, 0xffff},
178         {0x006a, 0x000d},
179         {53, 0xffff},
180 };
181
182 static struct idxdata tbl_init_post_alt_low1[] = {
183         {0x33, "\x8c\x27\x15"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\x22\x2e"},
184         {0x33, "\x90\x00\x81"}, {0x33, "\x8c\xa4\x08"}, {0x33, "\x90\x00\x17"},
185         {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x1a"}, {0x33, "\x8c\xa4\x0a"},
186         {0x33, "\x90\x00\x1d"}, {0x33, "\x8c\xa4\x0b"}, {0x33, "\x90\x00\x20"},
187         {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\x81"}, {0x33, "\x8c\x24\x13"},
188         {0x33, "\x90\x00\x9b"},
189 };
190
191 static struct idxdata tbl_init_post_alt_low2[] = {
192         {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x03\x24"}, {0x33, "\x8c\x27\x05"},
193         {0x33, "\x90\x02\x58"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
194         {2, "\xff\xff\xff"},
195         {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
196         {2, "\xff\xff\xff"},
197 };
198
199 static struct idxdata tbl_init_post_alt_low3[] = {
200         {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
201         {2, "\xff\xff\xff"},
202         {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x20"},
203         {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x01"},
204         {0x33, "\x2e\x01\x00"}, {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"},
205         {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x95"}, {0x33, "\x90\x01\x00"},
206         {2, "\xff\xff\xff"},
207         {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x03"},
208         {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
209         {2, "\xff\xff\xff"},
210         {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"},
211         {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
212         {2, "\xff\xff\xff"}, /* - * */
213         {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
214         {2, "\xff\xff\xff"},
215         {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
216         {2, "\xff\xff\xff"},
217         {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
218         {2, "\xff\xff\xff"},
219         {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
220         {1, "\xff\xff\xff"},
221 };
222
223 static struct idxdata tbl_init_post_alt_low4[] = {
224         {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"},
225         {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"},
226         {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"},
227         {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"},
228         {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"},
229         {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"},
230         {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"},
231         {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"},
232         {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"},
233         {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"},
234         {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"},
235         {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"},
236         {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"},
237         {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"},
238         {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"},
239         {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"},
240         {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"},
241         {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"},
242         {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"},
243         {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"},
244         {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"},
245         {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"},
246         {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"},
247         {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"},
248         {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"},
249         {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"},
250         /* Flip/Mirror h/v=1 */
251         {0x33, "\x90\x00\x3c"}, {0x33, "\x8c\x27\x19"}, {0x33, "\x90\x04\x6c"},
252         {0x33, "\x8c\x27\x3b"}, {0x33, "\x90\x00\x24"}, {0x33, "\x8c\xa1\x03"},
253         {0x33, "\x90\x00\x06"},
254         {130, "\xff\xff\xff"},
255         {0x33, "\x90\x00\x06"}, {0x33, "\x90\x00\x06"}, {0x33, "\x90\x00\x06"},
256         {0x33, "\x90\x00\x06"}, {0x33, "\x90\x00\x06"}, {0x33, "\x90\x00\x06"},
257         {100, "\xff\xff\xff"},
258         /* ?? */
259         {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa1\x02"},
260         {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
261         {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
262         /* Brigthness=70 */
263         {0x33, "\x8c\xa2\x06"}, {0x33, "\x90\x00\x46"}, {0x33, "\x8c\xa1\x02"},
264         {0x33, "\x90\x00\x0f"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
265         /* Sharpness=20 */
266         {0x32, "\x6c\x14\x08"},
267 };
268
269 static struct idxdata tbl_init_post_alt_big1[] = {
270         {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
271         {2, "\xff\xff\xff"},
272         {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
273         {2, "\xff\xff\xff"},
274         {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
275         {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x03"},
276         {0x33, "\x90\x00\x05"},
277         {2, "\xff\xff\xff"},
278         {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
279         {2, "\xff\xff\xff"},
280         {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
281         {2, "\xff\xff\xff"},
282         {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, {0x33, "\x8c\xa1\x20"},
283         {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x30"}, {0x33, "\x90\x00\x03"},
284         {0x33, "\x8c\xa1\x31"}, {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa1\x32"},
285         {0x33, "\x90\x00\x03"}, {0x33, "\x8c\xa1\x34"}, {0x33, "\x90\x00\x03"},
286         {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x2e\x01\x00"},
287         {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
288 };
289
290 static struct idxdata tbl_init_post_alt_big2[] = {
291         {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"},
292         {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"},
293         {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"},
294         {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"},
295         {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"},
296         {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"},
297         {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"},
298         {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"},
299         {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"},
300         {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"},
301         {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"},
302         {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"},
303         {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"},
304         {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"},
305         {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"},
306         {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"},
307         {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"},
308         {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"},
309         {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"},
310         {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"},
311         {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"},
312         {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"},
313         {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"},
314         {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"},
315         {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"},
316         {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"},
317 };
318
319 static struct idxdata tbl_init_post_alt_big3[] = {
320         {0x33, "\x8c\xa1\x02"},
321         {0x33, "\x90\x00\x1f"},
322         {0x33, "\x8c\xa1\x02"},
323         {0x33, "\x90\x00\x1f"},
324         {0x33, "\x8c\xa1\x02"},
325         {0x33, "\x90\x00\x1f"},
326         {0x33, "\x8c\xa1\x02"},
327         {0x33, "\x90\x00\x1f"},
328 };
329
330 static u8 *dat_640  = "\xd0\x02\xd1\x08\xd2\xe1\xd3\x02\xd4\x10\xd5\x81";
331 static u8 *dat_800  = "\xd0\x02\xd1\x10\xd2\x57\xd3\x02\xd4\x18\xd5\x21";
332 static u8 *dat_1280 = "\xd0\x02\xd1\x20\xd2\x01\xd3\x02\xd4\x28\xd5\x01";
333 static u8 *dat_1600 = "\xd0\x02\xd1\x20\xd2\xaf\xd3\x02\xd4\x30\xd5\x41";
334
335 static int  mi2020_init_at_startup(struct gspca_dev *gspca_dev);
336 static int  mi2020_configure_alt(struct gspca_dev *gspca_dev);
337 static int  mi2020_init_pre_alt(struct gspca_dev *gspca_dev);
338 static int  mi2020_init_post_alt(struct gspca_dev *gspca_dev);
339 static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev);
340 static int  mi2020_camera_settings(struct gspca_dev *gspca_dev);
341 /*==========================================================================*/
342
343 void mi2020_init_settings(struct gspca_dev *gspca_dev)
344 {
345         struct sd *sd = (struct sd *) gspca_dev;
346
347         sd->vcur.backlight  =  0;
348         sd->vcur.brightness = 70;
349         sd->vcur.sharpness  = 20;
350         sd->vcur.contrast   =  0;
351         sd->vcur.gamma      =  0;
352         sd->vcur.hue        =  0;
353         sd->vcur.saturation = 60;
354         sd->vcur.whitebal   = 50;
355         sd->vcur.mirror = 0;
356         sd->vcur.flip   = 0;
357         sd->vcur.AC50Hz = 1;
358
359         sd->vmax.backlight  =  64;
360         sd->vmax.brightness = 128;
361         sd->vmax.sharpness  =  40;
362         sd->vmax.contrast   =   3;
363         sd->vmax.gamma      =   2;
364         sd->vmax.hue        =   0 + 1; /* 200 */
365         sd->vmax.saturation =   0;     /* 100 */
366         sd->vmax.whitebal   =   0;     /* 100 */
367         sd->vmax.mirror = 1;
368         sd->vmax.flip   = 1;
369         sd->vmax.AC50Hz = 1;
370         if (_MI2020b_) {
371                 sd->vmax.contrast  = 0;
372                 sd->vmax.gamma     = 0;
373                 sd->vmax.backlight = 0;
374         }
375
376         sd->dev_camera_settings = mi2020_camera_settings;
377         sd->dev_init_at_startup = mi2020_init_at_startup;
378         sd->dev_configure_alt   = mi2020_configure_alt;
379         sd->dev_init_pre_alt    = mi2020_init_pre_alt;
380         sd->dev_post_unset_alt  = mi2020_post_unset_alt;
381 }
382
383 /*==========================================================================*/
384
385 static void common(struct gspca_dev *gspca_dev)
386 {
387         s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
388
389         if (_MI2020b_) {
390                 fetch_validx(gspca_dev, tbl_common1, ARRAY_SIZE(tbl_common1));
391         } else {
392                 if (_MI2020_)
393                         ctrl_out(gspca_dev, 0x40,  1, 0x0008, 0x0004,  0, NULL);
394                 else
395                         ctrl_out(gspca_dev, 0x40,  1, 0x0002, 0x0004,  0, NULL);
396                 msleep(35);
397                 fetch_validx(gspca_dev, tbl_common2, ARRAY_SIZE(tbl_common2));
398         }
399         ctrl_out(gspca_dev, 0x40,  3, 0x7a00, 0x0033,  3, "\x86\x25\x01");
400         ctrl_out(gspca_dev, 0x40,  3, 0x7a00, 0x0033,  3, "\x86\x25\x00");
401         msleep(2); /* - * */
402         ctrl_out(gspca_dev, 0x40,  3, 0x7a00, 0x0030,  3, "\x1a\x0a\xcc");
403         if (reso == IMAGE_1600)
404                 msleep(2); /* 1600 */
405         fetch_idxdata(gspca_dev, tbl_common3, ARRAY_SIZE(tbl_common3));
406
407         if (_MI2020b_ || _MI2020_)
408                 fetch_idxdata(gspca_dev, tbl_common4,
409                                 ARRAY_SIZE(tbl_common4));
410
411         fetch_idxdata(gspca_dev, tbl_common5, ARRAY_SIZE(tbl_common5));
412         if (_MI2020b_ || _MI2020_) {
413                 /* Different from fret */
414                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x78");
415                 /* Same as fret */
416                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\x24\x17");
417                 /* Different from fret */
418                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x90");
419         } else {
420                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x6a");
421                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\x24\x17");
422                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x80");
423         }
424         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03");
425         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x05");
426         msleep(2);
427         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03");
428         if (reso == IMAGE_1600)
429                 msleep(14); /* 1600 */
430         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x06");
431         msleep(2);
432 }
433
434 static int mi2020_init_at_startup(struct gspca_dev *gspca_dev)
435 {
436         u8 c;
437
438         ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &c);
439         ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &c);
440
441         fetch_validx(gspca_dev, tbl_init_at_startup,
442                         ARRAY_SIZE(tbl_init_at_startup));
443
444         common(gspca_dev);
445
446         return 0;
447 }
448
449 static int mi2020_init_pre_alt(struct gspca_dev *gspca_dev)
450 {
451         struct sd *sd = (struct sd *) gspca_dev;
452
453         sd->mirrorMask = 0;
454
455         sd->vold.backlight  = -1;
456         sd->vold.brightness = -1;
457         sd->vold.sharpness  = -1;
458         sd->vold.contrast   = -1;
459         sd->vold.gamma  = -1;
460         sd->vold.hue    = -1;
461         sd->vold.mirror = -1;
462         sd->vold.flip   = -1;
463         sd->vold.AC50Hz = -1;
464
465         mi2020_init_post_alt(gspca_dev);
466
467         return 0;
468 }
469
470 static int mi2020_init_post_alt(struct gspca_dev *gspca_dev)
471 {
472         struct sd *sd = (struct sd *) gspca_dev;
473         s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
474
475         s32 backlight = sd->vcur.backlight;
476         s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
477         s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
478         s32 freq   = (sd->vcur.AC50Hz  > 0);
479
480         u8 dat_freq2[] = {0x90, 0x00, 0x80};
481         u8 dat_multi1[] = {0x8c, 0xa7, 0x00};
482         u8 dat_multi2[] = {0x90, 0x00, 0x00};
483         u8 dat_multi3[] = {0x8c, 0xa7, 0x00};
484         u8 dat_multi4[] = {0x90, 0x00, 0x00};
485         u8 dat_hvflip2[] = {0x90, 0x04, 0x6c};
486         u8 dat_hvflip4[] = {0x90, 0x00, 0x24};
487         u8 c;
488
489         sd->nbIm = -1;
490
491         dat_freq2[2] = freq ? 0xc0 : 0x80;
492         dat_multi1[2] = 0x9d;
493         dat_multi3[2] = dat_multi1[2] + 1;
494         dat_multi4[2] = dat_multi2[2] = backlight;
495         dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror);
496         dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror);
497
498         msleep(200);
499
500         ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
501         msleep(3); /* 35 * */
502
503         common(gspca_dev);
504
505         ctrl_out(gspca_dev, 0x40,  1, 0x0041, 0x0000,  0, NULL);
506         msleep(70);
507
508         if (_MI2020b_)
509                 ctrl_out(gspca_dev, 0x40,  1, 0x0040, 0x0000,  0, NULL);
510
511         ctrl_out(gspca_dev, 0x40,  1, 0x0010, 0x0010,  0, NULL);
512         ctrl_out(gspca_dev, 0x40,  1, 0x0003, 0x00c1,  0, NULL);
513         ctrl_out(gspca_dev, 0x40,  1, 0x0042, 0x00c2,  0, NULL);
514         ctrl_out(gspca_dev, 0x40,  1, 0x006a, 0x000d,  0, NULL);
515
516         switch (reso) {
517         case IMAGE_640:
518         case IMAGE_800:
519                 if (reso != IMAGE_800)
520                         ctrl_out(gspca_dev, 0x40,  3, 0x0000, 0x0200,
521                                 12, dat_640);
522                 else
523                         ctrl_out(gspca_dev, 0x40,  3, 0x0000, 0x0200,
524                                 12, dat_800);
525
526                 if (_MI2020c_)
527                         fetch_idxdata(gspca_dev, tbl_init_post_alt_low1,
528                                         ARRAY_SIZE(tbl_init_post_alt_low1));
529
530                 if (reso == IMAGE_800)
531                         fetch_idxdata(gspca_dev, tbl_init_post_alt_low2,
532                                         ARRAY_SIZE(tbl_init_post_alt_low2));
533
534                 fetch_idxdata(gspca_dev, tbl_init_post_alt_low3,
535                                 ARRAY_SIZE(tbl_init_post_alt_low3));
536
537                 if (_MI2020b_) {
538                         ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL);
539                         ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
540                         ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
541                         msleep(150);
542                 } else if (_MI2020c_) {
543                         ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
544                         ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
545                         ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
546                         msleep(120);
547                         ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
548                         msleep(30);
549                 } else if (_MI2020_) {
550                         ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL);
551                         ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
552                         ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
553                         msleep(120);
554                         ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
555                         msleep(30);
556                 }
557
558                 /* AC power frequency */
559                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
560                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
561                 msleep(20);
562                 /* backlight */
563                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
564                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
565                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
566                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
567                 /* at init time but not after */
568                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa2\x0c");
569                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x17");
570                 /* finish the backlight */
571                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
572                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
573                 msleep(5);/* " */
574
575                 if (_MI2020c_) {
576                         fetch_idxdata(gspca_dev, tbl_init_post_alt_low4,
577                                         ARRAY_SIZE(tbl_init_post_alt_low4));
578                 } else {
579                         ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c);
580                         msleep(14); /* 0xd8 */
581
582                         /* flip/mirror */
583                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
584                                         3, dat_hvflip1);
585                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
586                                         3, dat_hvflip2);
587                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
588                                         3, dat_hvflip3);
589                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
590                                         3, dat_hvflip4);
591                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
592                                         3, dat_hvflip5);
593                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
594                                         3, dat_hvflip6);
595                         msleep(21);
596                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
597                                         3, dat_dummy1);
598                         msleep(5);
599                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
600                                         3, dat_dummy1);
601                         msleep(5);
602                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
603                                         3, dat_dummy1);
604                         msleep(5);
605                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
606                                         3, dat_dummy1);
607                         msleep(5);
608                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
609                                         3, dat_dummy1);
610                         msleep(5);
611                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
612                                         3, dat_dummy1);
613                         /* end of flip/mirror main part */
614                         msleep(246); /* 146 */
615
616                         sd->nbIm = 0;
617                 }
618                 break;
619
620         case IMAGE_1280:
621         case IMAGE_1600:
622                 if (reso == IMAGE_1280) {
623                         ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
624                                         12, dat_1280);
625                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
626                                         3, "\x8c\x27\x07");
627                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
628                                         3, "\x90\x05\x04");
629                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
630                                         3, "\x8c\x27\x09");
631                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
632                                         3, "\x90\x04\x02");
633                 } else {
634                         ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
635                                         12, dat_1600);
636                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
637                                         3, "\x8c\x27\x07");
638                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
639                                         3, "\x90\x06\x40");
640                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
641                                         3, "\x8c\x27\x09");
642                         ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
643                                         3, "\x90\x04\xb0");
644                 }
645
646                 fetch_idxdata(gspca_dev, tbl_init_post_alt_big1,
647                                 ARRAY_SIZE(tbl_init_post_alt_big1));
648
649                 if (reso == IMAGE_1600)
650                         msleep(13); /* 1600 */
651                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\x27\x97");
652                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x01\x00");
653                 msleep(53);
654                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x20");
655                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x00");
656                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03");
657                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x01");
658                 if (reso == IMAGE_1600)
659                         msleep(13); /* 1600 */
660                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa7\x02");
661                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x00");
662                 msleep(53);
663                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x20");
664                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x72");
665                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03");
666                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x02");
667                 if (reso == IMAGE_1600)
668                         msleep(13); /* 1600 */
669                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa7\x02");
670                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x01");
671                 msleep(53);
672
673                 if (_MI2020b_) {
674                         ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL);
675                         if (reso == IMAGE_1600)
676                                 msleep(500); /* 1600 */
677                         ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
678                         ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
679                         msleep(1850);
680                 } else if (_MI2020c_ || _MI2020_) {
681                         ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL);
682                         ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
683                         ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
684                         msleep(1850);
685                         ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
686                         msleep(30);
687                 }
688
689                 /* AC power frequency */
690                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
691                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
692                 msleep(20);
693                 /* backlight */
694                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
695                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
696                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
697                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
698                 /* at init time but not after */
699                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa2\x0c");
700                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x17");
701                 /* finish the backlight */
702                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
703                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
704                 msleep(6); /* " */
705
706                 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c);
707                 msleep(14);
708
709                 if (_MI2020c_)
710                         fetch_idxdata(gspca_dev, tbl_init_post_alt_big2,
711                                         ARRAY_SIZE(tbl_init_post_alt_big2));
712
713                 /* flip/mirror */
714                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1);
715                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2);
716                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3);
717                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4);
718                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5);
719                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6);
720                 /* end of flip/mirror main part */
721                 msleep(16);
722                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03");
723                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x01");
724                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x20");
725                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x00");
726                 if (reso == IMAGE_1600)
727                         msleep(25); /* 1600 */
728                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa7\x02");
729                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x00");
730                 msleep(103);
731                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03");
732                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x02");
733                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x20");
734                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x72");
735                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa7\x02");
736                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x01");
737                 sd->nbIm = 0;
738
739                 if (_MI2020c_)
740                         fetch_idxdata(gspca_dev, tbl_init_post_alt_big3,
741                                         ARRAY_SIZE(tbl_init_post_alt_big3));
742         }
743
744         sd->vold.mirror    = mirror;
745         sd->vold.flip      = flip;
746         sd->vold.AC50Hz    = freq;
747         sd->vold.backlight = backlight;
748
749         mi2020_camera_settings(gspca_dev);
750
751         return 0;
752 }
753
754 static int mi2020_configure_alt(struct gspca_dev *gspca_dev)
755 {
756         s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
757
758         switch (reso) {
759         case IMAGE_640:
760                 gspca_dev->alt = 3 + 1;
761                 break;
762
763         case IMAGE_800:
764         case IMAGE_1280:
765         case IMAGE_1600:
766                 gspca_dev->alt = 1 + 1;
767                 break;
768         }
769         return 0;
770 }
771
772 static int mi2020_camera_settings(struct gspca_dev *gspca_dev)
773 {
774         struct sd *sd = (struct sd *) gspca_dev;
775
776         s32 backlight = sd->vcur.backlight;
777         s32 bright =  sd->vcur.brightness;
778         s32 sharp  =  sd->vcur.sharpness;
779         s32 cntr   =  sd->vcur.contrast;
780         s32 gam    =  sd->vcur.gamma;
781         s32 hue    = (sd->vcur.hue > 0);
782         s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
783         s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
784         s32 freq   = (sd->vcur.AC50Hz > 0);
785
786         u8 dat_sharp[] = {0x6c, 0x00, 0x08};
787         u8 dat_bright2[] = {0x90, 0x00, 0x00};
788         u8 dat_freq2[] = {0x90, 0x00, 0x80};
789         u8 dat_multi1[] = {0x8c, 0xa7, 0x00};
790         u8 dat_multi2[] = {0x90, 0x00, 0x00};
791         u8 dat_multi3[] = {0x8c, 0xa7, 0x00};
792         u8 dat_multi4[] = {0x90, 0x00, 0x00};
793         u8 dat_hvflip2[] = {0x90, 0x04, 0x6c};
794         u8 dat_hvflip4[] = {0x90, 0x00, 0x24};
795
796         /* Less than 4 images received -> too early to set the settings */
797         if (sd->nbIm < 4) {
798                 sd->waitSet = 1;
799                 return 0;
800         }
801         sd->waitSet = 0;
802
803         if (freq != sd->vold.AC50Hz) {
804                 sd->vold.AC50Hz = freq;
805
806                 dat_freq2[2] = freq ? 0xc0 : 0x80;
807                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
808                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
809                 msleep(20);
810         }
811
812         if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
813                 sd->vold.mirror = mirror;
814                 sd->vold.flip   = flip;
815
816                 dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror);
817                 dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror);
818                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1);
819                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2);
820                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3);
821                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4);
822                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5);
823                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6);
824                 msleep(130);
825                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_dummy1);
826                 msleep(6);
827                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_dummy1);
828                 msleep(6);
829                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_dummy1);
830                 msleep(6);
831                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_dummy1);
832                 msleep(6);
833                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_dummy1);
834                 msleep(6);
835                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_dummy1);
836                 msleep(6);
837
838                 /* Sometimes present, sometimes not, useful? */
839                 /* ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy2);
840                  * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy3);
841                  * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy2);
842                  * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy3);
843                  * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy2);
844                  * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy3);
845                  * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy2);
846                  * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy3);*/
847         }
848
849         if (backlight != sd->vold.backlight) {
850                 sd->vold.backlight = backlight;
851                 if (backlight < 0 || backlight > sd->vmax.backlight)
852                         backlight = 0;
853
854                 dat_multi1[2] = 0x9d;
855                 dat_multi3[2] = dat_multi1[2] + 1;
856                 dat_multi4[2] = dat_multi2[2] = backlight;
857                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
858                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
859                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
860                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
861                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
862                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
863         }
864
865         if (gam != sd->vold.gamma) {
866                 sd->vold.gamma = gam;
867                 if (gam < 0 || gam > sd->vmax.gamma)
868                         gam = 0;
869
870                 dat_multi1[2] = 0x6d;
871                 dat_multi3[2] = dat_multi1[2] + 1;
872                 dat_multi4[2] = dat_multi2[2] = 0x40 + gam;
873                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
874                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
875                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
876                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
877                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
878                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
879         }
880
881         if (cntr != sd->vold.contrast) {
882                 sd->vold.contrast = cntr;
883                 if (cntr < 0 || cntr > sd->vmax.contrast)
884                         cntr = 0;
885
886                 dat_multi1[2] = 0x6d;
887                 dat_multi3[2] = dat_multi1[2] + 1;
888                 dat_multi4[2] = dat_multi2[2] = 0x12 + 16 * cntr;
889                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
890                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
891                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
892                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
893                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
894                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
895         }
896
897         if (bright != sd->vold.brightness) {
898                 sd->vold.brightness = bright;
899                 if (bright < 0 || bright > sd->vmax.brightness)
900                         bright = 0;
901
902                 dat_bright2[2] = bright;
903                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright1);
904                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright2);
905                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright3);
906                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright4);
907                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright5);
908                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright6);
909         }
910
911         if (sharp != sd->vold.sharpness) {
912                 sd->vold.sharpness = sharp;
913                 if (sharp < 0 || sharp > sd->vmax.sharpness)
914                         sharp = 0;
915
916                 dat_sharp[1] = sharp;
917                 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0032, 3, dat_sharp);
918         }
919
920         if (hue != sd->vold.hue) {
921                 sd->swapRB = hue;
922                 sd->vold.hue = hue;
923         }
924
925         return 0;
926 }
927
928 static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev)
929 {
930         ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
931         msleep(20);
932         if (_MI2020c_ || _MI2020_)
933                 ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0000, 0, NULL);
934         else
935                 ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL);
936 }