1 /* Subdriver for the GL860 chip with the MI2020 sensor
2 * Author Olivier LORIN, from logs by Iceman/Soro2005 + Fret_saw/Hulkie/Tricid
3 * with the help of Kytrix/BUGabundo/Blazercist.
4 * Driver achieved thanks to a webcam gift by Kytrix.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 static u8 dat_wbal1
[] = {0x8c, 0xa2, 0x0c};
26 static u8 dat_bright1
[] = {0x8c, 0xa2, 0x06};
27 static u8 dat_bright3
[] = {0x8c, 0xa1, 0x02};
28 static u8 dat_bright4
[] = {0x90, 0x00, 0x0f};
29 static u8 dat_bright5
[] = {0x8c, 0xa1, 0x03};
30 static u8 dat_bright6
[] = {0x90, 0x00, 0x05};
32 static u8 dat_hvflip1
[] = {0x8c, 0x27, 0x19};
33 static u8 dat_hvflip3
[] = {0x8c, 0x27, 0x3b};
34 static u8 dat_hvflip5
[] = {0x8c, 0xa1, 0x03};
35 static u8 dat_hvflip6
[] = {0x90, 0x00, 0x06};
37 static struct idxdata tbl_middle_hvflip_low
[] = {
38 {0x33, "\x90\x00\x06"},
40 {0x33, "\x90\x00\x06"},
42 {0x33, "\x90\x00\x06"},
44 {0x33, "\x90\x00\x06"},
48 static struct idxdata tbl_middle_hvflip_big
[] = {
49 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa1\x20"},
50 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
51 {102, "\xff\xff\xff"},
52 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa1\x20"},
53 {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
56 static struct idxdata tbl_end_hvflip
[] = {
57 {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
59 {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
61 {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
63 {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
66 static u8 dat_freq1
[] = { 0x8c, 0xa4, 0x04 };
68 static u8 dat_multi5
[] = { 0x8c, 0xa1, 0x03 };
69 static u8 dat_multi6
[] = { 0x90, 0x00, 0x05 };
71 static struct validx tbl_init_at_startup
[] = {
72 {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1},
73 {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d},
75 {0x0040, 0x0000}, {0x0063, 0x0006},
78 static struct validx tbl_common_0B
[] = {
79 {0x0002, 0x0004}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d},
80 {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2},
81 {0x0004, 0x00d8}, {0x0000, 0x0058}, {0x0041, 0x0000},
84 static struct idxdata tbl_common_3B
[] = {
85 {0x33, "\x86\x25\x01"}, {0x33, "\x86\x25\x00"},
87 {0x30, "\x1a\x0a\xcc"}, {0x32, "\x02\x00\x08"}, {0x33, "\xf4\x03\x1d"},
88 {6, "\xff\xff\xff"}, /* 12 */
89 {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
90 {2, "\xff\xff\xff"}, /* - */
91 {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\x22\x23"},
92 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0f"}, {0x33, "\x90\x00\x0d"},
93 {0x33, "\x8c\xa2\x10"}, {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x11"},
94 {0x33, "\x90\x00\x07"}, {0x33, "\xf4\x03\x1d"}, {0x35, "\xa2\x00\xe2"},
95 {0x33, "\x8c\xab\x05"}, {0x33, "\x90\x00\x01"}, {0x32, "\x6e\x00\x86"},
96 {0x32, "\x70\x0f\xaa"}, {0x32, "\x72\x0f\xe4"}, {0x33, "\x8c\xa3\x4a"},
97 {0x33, "\x90\x00\x5a"}, {0x33, "\x8c\xa3\x4b"}, {0x33, "\x90\x00\xa6"},
98 {0x33, "\x8c\xa3\x61"}, {0x33, "\x90\x00\xc8"}, {0x33, "\x8c\xa3\x62"},
99 {0x33, "\x90\x00\xe1"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"},
100 {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"},
101 {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"},
102 {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"},
103 {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"},
104 {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"},
105 {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"},
106 {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"},
107 {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"},
108 {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"},
109 {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"},
110 {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"},
111 {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"},
112 {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"},
113 {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"},
114 {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"},
115 {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"},
116 {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"},
117 {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"},
118 {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"},
119 {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"},
120 {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"},
121 {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"},
122 {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"},
123 {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"},
124 {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"},
125 {0x33, "\x78\x00\x00"},
127 {0x35, "\xb8\x1f\x20"}, {0x33, "\x8c\xa2\x06"}, {0x33, "\x90\x00\x10"},
128 {0x33, "\x8c\xa2\x07"}, {0x33, "\x90\x00\x08"}, {0x33, "\x8c\xa2\x42"},
129 {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x4a"}, {0x33, "\x90\x00\x8c"},
130 {0x35, "\xba\xfa\x08"}, {0x33, "\x8c\xa2\x02"}, {0x33, "\x90\x00\x22"},
131 {0x33, "\x8c\xa2\x03"}, {0x33, "\x90\x00\xbb"}, {0x33, "\x8c\xa4\x04"},
132 {0x33, "\x90\x00\x80"}, {0x33, "\x8c\xa7\x9d"}, {0x33, "\x90\x00\x00"},
133 {0x33, "\x8c\xa7\x9e"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0c"},
134 {0x33, "\x90\x00\x17"}, {0x33, "\x8c\xa2\x15"}, {0x33, "\x90\x00\x04"},
135 {0x33, "\x8c\xa2\x14"}, {0x33, "\x90\x00\x20"}, {0x33, "\x8c\xa1\x03"},
136 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, {0x33, "\x90\x21\x11"},
137 {0x33, "\x8c\x27\x1b"}, {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x25"},
138 {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x39"}, {0x33, "\x90\x21\x11"},
139 {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, {0x33, "\x8c\x27\x47"},
140 {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x02\x84"},
141 {0x33, "\x8c\x27\x05"}, {0x33, "\x90\x01\xe2"}, {0x33, "\x8c\x27\x07"},
142 {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x09"}, {0x33, "\x90\x04\xb0"},
143 {0x33, "\x8c\x27\x0d"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x0f"},
144 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x11"}, {0x33, "\x90\x04\xbd"},
145 {0x33, "\x8c\x27\x13"}, {0x33, "\x90\x06\x4d"}, {0x33, "\x8c\x27\x15"},
146 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, {0x33, "\x90\x21\x11"},
147 {0x33, "\x8c\x27\x19"}, {0x33, "\x90\x04\x6c"}, {0x33, "\x8c\x27\x1b"},
148 {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x1d"}, {0x33, "\x90\x01\x02"},
149 {0x33, "\x8c\x27\x1f"}, {0x33, "\x90\x02\x79"}, {0x33, "\x8c\x27\x21"},
150 {0x33, "\x90\x01\x55"}, {0x33, "\x8c\x27\x23"}, {0x33, "\x90\x02\x85"},
151 {0x33, "\x8c\x27\x25"}, {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x27"},
152 {0x33, "\x90\x20\x20"}, {0x33, "\x8c\x27\x29"}, {0x33, "\x90\x20\x20"},
153 {0x33, "\x8c\x27\x2b"}, {0x33, "\x90\x10\x20"}, {0x33, "\x8c\x27\x2d"},
154 {0x33, "\x90\x20\x07"}, {0x33, "\x8c\x27\x2f"}, {0x33, "\x90\x00\x04"},
155 {0x33, "\x8c\x27\x31"}, {0x33, "\x90\x00\x04"}, {0x33, "\x8c\x27\x33"},
156 {0x33, "\x90\x04\xbb"}, {0x33, "\x8c\x27\x35"}, {0x33, "\x90\x06\x4b"},
157 {0x33, "\x8c\x27\x37"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x39"},
158 {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x3b"}, {0x33, "\x90\x00\x24"},
159 {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, {0x33, "\x8c\x27\x41"},
160 {0x33, "\x90\x01\x69"}, {0x33, "\x8c\x27\x45"}, {0x33, "\x90\x04\xed"},
161 {0x33, "\x8c\x27\x47"}, {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x51"},
162 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x53"}, {0x33, "\x90\x03\x20"},
163 {0x33, "\x8c\x27\x55"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x57"},
164 {0x33, "\x90\x02\x58"}, {0x33, "\x8c\x27\x5f"}, {0x33, "\x90\x00\x00"},
165 {0x33, "\x8c\x27\x61"}, {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x63"},
166 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x65"}, {0x33, "\x90\x04\xb0"},
167 {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa1"}, {0x33, "\x8c\xa4\x08"},
168 {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x21"},
169 {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\xa4\x0b"},
170 {0x33, "\x90\x00\x27"}, {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\xa1"},
171 {0x33, "\x8c\x24\x13"}, {0x33, "\x90\x00\xc1"}, {0x33, "\x8c\x24\x15"},
172 {0x33, "\x90\x00\x6a"}, {0x33, "\x8c\x24\x17"}, {0x33, "\x90\x00\x80"},
173 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
175 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
179 static struct idxdata tbl_init_post_alt_low1
[] = {
180 {0x33, "\x8c\x27\x15"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\x22\x2e"},
181 {0x33, "\x90\x00\x81"}, {0x33, "\x8c\xa4\x08"}, {0x33, "\x90\x00\x17"},
182 {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x1a"}, {0x33, "\x8c\xa4\x0a"},
183 {0x33, "\x90\x00\x1d"}, {0x33, "\x8c\xa4\x0b"}, {0x33, "\x90\x00\x20"},
184 {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\x81"}, {0x33, "\x8c\x24\x13"},
185 {0x33, "\x90\x00\x9b"},
188 static struct idxdata tbl_init_post_alt_low2
[] = {
189 {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x03\x24"}, {0x33, "\x8c\x27\x05"},
190 {0x33, "\x90\x02\x58"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
192 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
196 static struct idxdata tbl_init_post_alt_low3
[] = {
197 {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
199 {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x20"},
200 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x01"},
201 {0x33, "\x2e\x01\x00"}, {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"},
202 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x95"}, {0x33, "\x90\x01\x00"},
204 {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x03"},
205 {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
207 {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"},
208 {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
210 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
212 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
214 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
216 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
219 static struct idxdata tbl_init_post_alt_big
[] = {
220 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
222 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
224 {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
226 {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x03"},
227 {0x33, "\x90\x00\x05"},
229 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
231 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
233 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, {0x33, "\x8c\xa1\x20"},
234 {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x30"}, {0x33, "\x90\x00\x03"},
235 {0x33, "\x8c\xa1\x31"}, {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa1\x32"},
236 {0x33, "\x90\x00\x03"}, {0x33, "\x8c\xa1\x34"}, {0x33, "\x90\x00\x03"},
237 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x2e\x01\x00"},
238 {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
239 {0x33, "\x8c\x27\x97"}, {0x33, "\x90\x01\x00"},
240 {51, "\xff\xff\xff"},
241 {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"},
242 {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
243 {51, "\xff\xff\xff"},
244 {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x03"},
245 {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
246 {51, "\xff\xff\xff"},
249 static struct idxdata tbl_init_post_alt_3B
[] = {
250 {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"},
251 {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"},
252 {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"},
253 {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"},
254 {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"},
255 {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"},
256 {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"},
257 {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"},
258 {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"},
259 {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"},
260 {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"},
261 {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"},
262 {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"},
263 {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"},
264 {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"},
265 {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"},
266 {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"},
267 {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"},
268 {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"},
269 {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"},
270 {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"},
271 {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"},
272 {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"},
273 {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"},
274 {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"},
275 {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"},
278 static u8
*dat_640
= "\xd0\x02\xd1\x08\xd2\xe1\xd3\x02\xd4\x10\xd5\x81";
279 static u8
*dat_800
= "\xd0\x02\xd1\x10\xd2\x57\xd3\x02\xd4\x18\xd5\x21";
280 static u8
*dat_1280
= "\xd0\x02\xd1\x20\xd2\x01\xd3\x02\xd4\x28\xd5\x01";
281 static u8
*dat_1600
= "\xd0\x02\xd1\x20\xd2\xaf\xd3\x02\xd4\x30\xd5\x41";
283 static int mi2020_init_at_startup(struct gspca_dev
*gspca_dev
);
284 static int mi2020_configure_alt(struct gspca_dev
*gspca_dev
);
285 static int mi2020_init_pre_alt(struct gspca_dev
*gspca_dev
);
286 static int mi2020_init_post_alt(struct gspca_dev
*gspca_dev
);
287 static void mi2020_post_unset_alt(struct gspca_dev
*gspca_dev
);
288 static int mi2020_camera_settings(struct gspca_dev
*gspca_dev
);
289 /*==========================================================================*/
291 void mi2020_init_settings(struct gspca_dev
*gspca_dev
)
293 struct sd
*sd
= (struct sd
*) gspca_dev
;
295 sd
->vcur
.backlight
= 0;
296 sd
->vcur
.brightness
= 70;
297 sd
->vcur
.sharpness
= 20;
298 sd
->vcur
.contrast
= 0;
301 sd
->vcur
.saturation
= 60;
302 sd
->vcur
.whitebal
= 0; /* 50, not done by hardware */
307 sd
->vmax
.backlight
= 64;
308 sd
->vmax
.brightness
= 128;
309 sd
->vmax
.sharpness
= 40;
310 sd
->vmax
.contrast
= 3;
312 sd
->vmax
.hue
= 0 + 1; /* 200, not done by hardware */
313 sd
->vmax
.saturation
= 0; /* 100, not done by hardware */
314 sd
->vmax
.whitebal
= 2; /* 100, not done by hardware */
319 sd
->dev_camera_settings
= mi2020_camera_settings
;
320 sd
->dev_init_at_startup
= mi2020_init_at_startup
;
321 sd
->dev_configure_alt
= mi2020_configure_alt
;
322 sd
->dev_init_pre_alt
= mi2020_init_pre_alt
;
323 sd
->dev_post_unset_alt
= mi2020_post_unset_alt
;
326 /*==========================================================================*/
328 static void common(struct gspca_dev
*gspca_dev
)
330 fetch_validx(gspca_dev
, tbl_common_0B
, ARRAY_SIZE(tbl_common_0B
));
331 fetch_idxdata(gspca_dev
, tbl_common_3B
, ARRAY_SIZE(tbl_common_3B
));
332 ctrl_out(gspca_dev
, 0x40, 1, 0x0041, 0x0000, 0, NULL
);
335 static int mi2020_init_at_startup(struct gspca_dev
*gspca_dev
)
339 ctrl_in(gspca_dev
, 0xc0, 2, 0x0000, 0x0004, 1, &c
);
340 ctrl_in(gspca_dev
, 0xc0, 2, 0x0000, 0x0004, 1, &c
);
342 fetch_validx(gspca_dev
, tbl_init_at_startup
,
343 ARRAY_SIZE(tbl_init_at_startup
));
345 ctrl_out(gspca_dev
, 0x40, 1, 0x7a00, 0x8030, 0, NULL
);
346 ctrl_in(gspca_dev
, 0xc0, 2, 0x7a00, 0x8030, 1, &c
);
351 /* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */
353 ctrl_out(gspca_dev
, 0x40, 1, 0x0001, 0x0000, 0, NULL
);
358 static int mi2020_init_pre_alt(struct gspca_dev
*gspca_dev
)
360 struct sd
*sd
= (struct sd
*) gspca_dev
;
365 /* These controls need to be reset */
366 sd
->vold
.brightness
= -1;
367 sd
->vold
.sharpness
= -1;
369 /* If not different from default, they do not need to be set */
370 sd
->vold
.contrast
= 0;
372 sd
->vold
.backlight
= 0;
374 mi2020_init_post_alt(gspca_dev
);
379 static int mi2020_init_post_alt(struct gspca_dev
*gspca_dev
)
381 struct sd
*sd
= (struct sd
*) gspca_dev
;
382 s32 reso
= gspca_dev
->cam
.cam_mode
[(s32
) gspca_dev
->curr_mode
].priv
;
384 s32 mirror
= (((sd
->vcur
.mirror
> 0) ^ sd
->mirrorMask
) > 0);
385 s32 flip
= (((sd
->vcur
.flip
> 0) ^ sd
->mirrorMask
) > 0);
386 s32 freq
= (sd
->vcur
.AC50Hz
> 0);
387 s32 wbal
= sd
->vcur
.whitebal
;
389 u8 dat_freq2
[] = {0x90, 0x00, 0x80};
390 u8 dat_multi1
[] = {0x8c, 0xa7, 0x00};
391 u8 dat_multi2
[] = {0x90, 0x00, 0x00};
392 u8 dat_multi3
[] = {0x8c, 0xa7, 0x00};
393 u8 dat_multi4
[] = {0x90, 0x00, 0x00};
394 u8 dat_hvflip2
[] = {0x90, 0x04, 0x6c};
395 u8 dat_hvflip4
[] = {0x90, 0x00, 0x24};
396 u8 dat_wbal2
[] = {0x90, 0x00, 0x00};
401 dat_freq2
[2] = freq
? 0xc0 : 0x80;
402 dat_multi1
[2] = 0x9d;
403 dat_multi3
[2] = dat_multi1
[2] + 1;
405 dat_multi4
[2] = dat_multi2
[2] = 0;
407 } else if (wbal
== 1) {
408 dat_multi4
[2] = dat_multi2
[2] = 0;
410 } else if (wbal
== 2) {
411 dat_multi4
[2] = dat_multi2
[2] = 0x20;
414 dat_hvflip2
[2] = 0x6c + 2 * (1 - flip
) + (1 - mirror
);
415 dat_hvflip4
[2] = 0x24 + 2 * (1 - flip
) + (1 - mirror
);
418 ctrl_out(gspca_dev
, 0x40, 5, 0x0001, 0x0000, 0, NULL
);
424 ctrl_out(gspca_dev
, 0x40, 1, 0x0010, 0x0010, 0, NULL
);
425 ctrl_out(gspca_dev
, 0x40, 1, 0x0003, 0x00c1, 0, NULL
);
426 ctrl_out(gspca_dev
, 0x40, 1, 0x0042, 0x00c2, 0, NULL
);
427 ctrl_out(gspca_dev
, 0x40, 1, 0x006a, 0x000d, 0, NULL
);
432 if (reso
!= IMAGE_800
)
433 ctrl_out(gspca_dev
, 0x40, 3, 0x0000, 0x0200,
436 ctrl_out(gspca_dev
, 0x40, 3, 0x0000, 0x0200,
439 fetch_idxdata(gspca_dev
, tbl_init_post_alt_low1
,
440 ARRAY_SIZE(tbl_init_post_alt_low1
));
442 if (reso
== IMAGE_800
)
443 fetch_idxdata(gspca_dev
, tbl_init_post_alt_low2
,
444 ARRAY_SIZE(tbl_init_post_alt_low2
));
446 fetch_idxdata(gspca_dev
, tbl_init_post_alt_low3
,
447 ARRAY_SIZE(tbl_init_post_alt_low3
));
449 ctrl_out(gspca_dev
, 0x40, 1, 0x0010, 0x0010, 0, NULL
);
450 ctrl_out(gspca_dev
, 0x40, 1, 0x0000, 0x00c1, 0, NULL
);
451 ctrl_out(gspca_dev
, 0x40, 1, 0x0041, 0x00c2, 0, NULL
);
457 if (reso
== IMAGE_1280
) {
458 ctrl_out(gspca_dev
, 0x40, 3, 0x0000, 0x0200,
460 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033,
462 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033,
464 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033,
466 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033,
469 ctrl_out(gspca_dev
, 0x40, 3, 0x0000, 0x0200,
471 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033,
473 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033,
475 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033,
477 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033,
481 fetch_idxdata(gspca_dev
, tbl_init_post_alt_big
,
482 ARRAY_SIZE(tbl_init_post_alt_big
));
484 ctrl_out(gspca_dev
, 0x40, 1, 0x0001, 0x0010, 0, NULL
);
485 ctrl_out(gspca_dev
, 0x40, 1, 0x0000, 0x00c1, 0, NULL
);
486 ctrl_out(gspca_dev
, 0x40, 1, 0x0041, 0x00c2, 0, NULL
);
490 ctrl_out(gspca_dev
, 0x40, 1, 0x0040, 0x0000, 0, NULL
);
493 /* AC power frequency */
494 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1
);
495 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2
);
498 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1
);
499 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2
);
500 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3
);
501 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4
);
502 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1
);
503 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2
);
504 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5
);
505 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6
);
507 ctrl_in(gspca_dev
, 0xc0, 2, 0x0000, 0x0000, 1, &c
);
509 fetch_idxdata(gspca_dev
, tbl_init_post_alt_3B
,
510 ARRAY_SIZE(tbl_init_post_alt_3B
));
513 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1
);
514 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2
);
515 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3
);
516 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4
);
517 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5
);
518 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6
);
521 if (reso
== IMAGE_640
|| reso
== IMAGE_800
)
522 fetch_idxdata(gspca_dev
, tbl_middle_hvflip_low
,
523 ARRAY_SIZE(tbl_middle_hvflip_low
));
525 fetch_idxdata(gspca_dev
, tbl_middle_hvflip_big
,
526 ARRAY_SIZE(tbl_middle_hvflip_big
));
528 fetch_idxdata(gspca_dev
, tbl_end_hvflip
,
529 ARRAY_SIZE(tbl_end_hvflip
));
533 sd
->vold
.mirror
= mirror
;
534 sd
->vold
.flip
= flip
;
535 sd
->vold
.AC50Hz
= freq
;
536 sd
->vold
.whitebal
= wbal
;
538 mi2020_camera_settings(gspca_dev
);
543 static int mi2020_configure_alt(struct gspca_dev
*gspca_dev
)
545 s32 reso
= gspca_dev
->cam
.cam_mode
[(s32
) gspca_dev
->curr_mode
].priv
;
549 gspca_dev
->alt
= 3 + 1;
555 gspca_dev
->alt
= 1 + 1;
561 static int mi2020_camera_settings(struct gspca_dev
*gspca_dev
)
563 struct sd
*sd
= (struct sd
*) gspca_dev
;
564 s32 reso
= gspca_dev
->cam
.cam_mode
[(s32
) gspca_dev
->curr_mode
].priv
;
566 s32 backlight
= sd
->vcur
.backlight
;
567 s32 bright
= sd
->vcur
.brightness
;
568 s32 sharp
= sd
->vcur
.sharpness
;
569 s32 cntr
= sd
->vcur
.contrast
;
570 s32 gam
= sd
->vcur
.gamma
;
571 s32 hue
= (sd
->vcur
.hue
> 0);
572 s32 mirror
= (((sd
->vcur
.mirror
> 0) ^ sd
->mirrorMask
) > 0);
573 s32 flip
= (((sd
->vcur
.flip
> 0) ^ sd
->mirrorMask
) > 0);
574 s32 freq
= (sd
->vcur
.AC50Hz
> 0);
575 s32 wbal
= sd
->vcur
.whitebal
;
577 u8 dat_sharp
[] = {0x6c, 0x00, 0x08};
578 u8 dat_bright2
[] = {0x90, 0x00, 0x00};
579 u8 dat_freq2
[] = {0x90, 0x00, 0x80};
580 u8 dat_multi1
[] = {0x8c, 0xa7, 0x00};
581 u8 dat_multi2
[] = {0x90, 0x00, 0x00};
582 u8 dat_multi3
[] = {0x8c, 0xa7, 0x00};
583 u8 dat_multi4
[] = {0x90, 0x00, 0x00};
584 u8 dat_hvflip2
[] = {0x90, 0x04, 0x6c};
585 u8 dat_hvflip4
[] = {0x90, 0x00, 0x24};
586 u8 dat_wbal2
[] = {0x90, 0x00, 0x00};
588 /* Less than 4 images received -> too early to set the settings */
595 if (freq
!= sd
->vold
.AC50Hz
) {
596 sd
->vold
.AC50Hz
= freq
;
598 dat_freq2
[2] = freq
? 0xc0 : 0x80;
599 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1
);
600 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2
);
604 if (wbal
!= sd
->vold
.whitebal
) {
605 sd
->vold
.whitebal
= wbal
;
606 if (wbal
< 0 || wbal
> sd
->vmax
.whitebal
)
609 dat_multi1
[2] = 0x9d;
610 dat_multi3
[2] = dat_multi1
[2] + 1;
612 dat_multi4
[2] = dat_multi2
[2] = 0;
614 } else if (wbal
== 1) {
615 dat_multi4
[2] = dat_multi2
[2] = 0;
617 } else if (wbal
== 2) {
618 dat_multi4
[2] = dat_multi2
[2] = 0x20;
621 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1
);
622 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2
);
623 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3
);
624 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4
);
625 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1
);
626 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2
);
627 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5
);
628 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6
);
631 if (mirror
!= sd
->vold
.mirror
|| flip
!= sd
->vold
.flip
) {
632 sd
->vold
.mirror
= mirror
;
633 sd
->vold
.flip
= flip
;
635 dat_hvflip2
[2] = 0x6c + 2 * (1 - flip
) + (1 - mirror
);
636 dat_hvflip4
[2] = 0x24 + 2 * (1 - flip
) + (1 - mirror
);
638 fetch_idxdata(gspca_dev
, tbl_init_post_alt_3B
,
639 ARRAY_SIZE(tbl_init_post_alt_3B
));
641 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1
);
642 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2
);
643 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3
);
644 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4
);
645 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5
);
646 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6
);
649 if (reso
== IMAGE_640
|| reso
== IMAGE_800
)
650 fetch_idxdata(gspca_dev
, tbl_middle_hvflip_low
,
651 ARRAY_SIZE(tbl_middle_hvflip_low
));
653 fetch_idxdata(gspca_dev
, tbl_middle_hvflip_big
,
654 ARRAY_SIZE(tbl_middle_hvflip_big
));
656 fetch_idxdata(gspca_dev
, tbl_end_hvflip
,
657 ARRAY_SIZE(tbl_end_hvflip
));
660 if (bright
!= sd
->vold
.brightness
) {
661 sd
->vold
.brightness
= bright
;
662 if (bright
< 0 || bright
> sd
->vmax
.brightness
)
665 dat_bright2
[2] = bright
;
666 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright1
);
667 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright2
);
668 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright3
);
669 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright4
);
670 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright5
);
671 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright6
);
674 if (cntr
!= sd
->vold
.contrast
|| gam
!= sd
->vold
.gamma
) {
675 sd
->vold
.contrast
= cntr
;
676 if (cntr
< 0 || cntr
> sd
->vmax
.contrast
)
678 sd
->vold
.gamma
= gam
;
679 if (gam
< 0 || gam
> sd
->vmax
.gamma
)
682 dat_multi1
[2] = 0x6d;
683 dat_multi3
[2] = dat_multi1
[2] + 1;
686 dat_multi4
[2] = dat_multi2
[2] = cntr
* 0x10 + 2 - gam
;
687 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1
);
688 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2
);
689 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3
);
690 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4
);
691 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5
);
692 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6
);
695 if (backlight
!= sd
->vold
.backlight
) {
696 sd
->vold
.backlight
= backlight
;
697 if (backlight
< 0 || backlight
> sd
->vmax
.backlight
)
700 dat_multi1
[2] = 0x9d;
701 dat_multi3
[2] = dat_multi1
[2] + 1;
702 dat_multi4
[2] = dat_multi2
[2] = backlight
;
703 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1
);
704 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2
);
705 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3
);
706 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4
);
707 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5
);
708 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6
);
711 if (sharp
!= sd
->vold
.sharpness
) {
712 sd
->vold
.sharpness
= sharp
;
713 if (sharp
< 0 || sharp
> sd
->vmax
.sharpness
)
716 dat_sharp
[1] = sharp
;
717 ctrl_out(gspca_dev
, 0x40, 3, 0x7a00, 0x0032, 3, dat_sharp
);
720 if (hue
!= sd
->vold
.hue
) {
728 static void mi2020_post_unset_alt(struct gspca_dev
*gspca_dev
)
730 ctrl_out(gspca_dev
, 0x40, 5, 0x0000, 0x0000, 0, NULL
);
732 ctrl_out(gspca_dev
, 0x40, 1, 0x0001, 0x0000, 0, NULL
);