]>
Commit | Line | Data |
---|---|---|
be9904bd OL |
1 | /* Subdriver for the GL860 chip with the OV2640 sensor |
2 | * Author Olivier LORIN, from Malmostoso's logs | |
4f7cb883 OL |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | */ | |
17 | ||
18 | /* Sensor : OV2640 */ | |
19 | ||
20 | #include "gl860.h" | |
21 | ||
22 | static u8 dat_init1[] = "\x00\x41\x07\x6a\x06\x61\x0d\x6a" "\x10\x10\xc1\x01"; | |
fdd1dd1d OL |
23 | |
24 | static u8 c61[] = {0x61}; /* expected */ | |
25 | static u8 c51[] = {0x51}; /* expected */ | |
26 | static u8 c50[] = {0x50}; /* expected */ | |
27 | static u8 c28[] = {0x28}; /* expected */ | |
28 | static u8 ca8[] = {0xa8}; /* expected */ | |
4f7cb883 OL |
29 | |
30 | static u8 dat_post[] = | |
31 | "\x00\x41\x07\x6a\x06\xef\x0d\x6a" "\x10\x10\xc1\x01"; | |
32 | ||
33 | static u8 dat_640[] = "\xd0\x01\xd1\x08\xd2\xe0\xd3\x02\xd4\x10\xd5\x81"; | |
34 | static u8 dat_800[] = "\xd0\x01\xd1\x10\xd2\x58\xd3\x02\xd4\x18\xd5\x21"; | |
35 | static u8 dat_1280[] = "\xd0\x01\xd1\x18\xd2\xc0\xd3\x02\xd4\x28\xd5\x01"; | |
36 | static u8 dat_1600[] = "\xd0\x01\xd1\x20\xd2\xb0\xd3\x02\xd4\x30\xd5\x41"; | |
37 | ||
4f7cb883 OL |
38 | static struct validx tbl_init_at_startup[] = { |
39 | {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1}, | |
40 | {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d}, | |
41 | {0x0050, 0x0000}, {0x0041, 0x0000}, {0x006a, 0x0007}, {0x0061, 0x0006}, | |
42 | {0x006a, 0x000d}, {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, | |
43 | {0x0041, 0x00c2}, {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, | |
44 | {0x0041, 0x0000}, {0x0061, 0x0000}, | |
45 | }; | |
46 | ||
47 | static struct validx tbl_common[] = { | |
48 | {0x6000, 0x00ff}, {0x60ff, 0x002c}, {0x60df, 0x002e}, {0x6001, 0x00ff}, | |
49 | {0x6080, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045}, {0x6000, 0x0010}, | |
50 | {0x6035, 0x003c}, {0x6000, 0x0011}, {0x6028, 0x0004}, {0x60e5, 0x0013}, | |
51 | {0x6088, 0x0014}, {0x600c, 0x002c}, {0x6078, 0x0033}, {0x60f7, 0x003b}, | |
52 | {0x6000, 0x003e}, {0x6011, 0x0043}, {0x6010, 0x0016}, {0x6082, 0x0039}, | |
53 | {0x6088, 0x0035}, {0x600a, 0x0022}, {0x6040, 0x0037}, {0x6000, 0x0023}, | |
54 | {0x60a0, 0x0034}, {0x601a, 0x0036}, {0x6002, 0x0006}, {0x60c0, 0x0007}, | |
55 | {0x60b7, 0x000d}, {0x6001, 0x000e}, {0x6000, 0x004c}, {0x6081, 0x004a}, | |
56 | {0x6099, 0x0021}, {0x6002, 0x0009}, {0x603e, 0x0024}, {0x6034, 0x0025}, | |
57 | {0x6081, 0x0026}, {0x6000, 0x0000}, {0x6000, 0x0045}, {0x6000, 0x0010}, | |
58 | {0x6000, 0x005c}, {0x6000, 0x0063}, {0x6000, 0x007c}, {0x6070, 0x0061}, | |
59 | {0x6080, 0x0062}, {0x6080, 0x0020}, {0x6030, 0x0028}, {0x6000, 0x006c}, | |
60 | {0x6000, 0x006e}, {0x6002, 0x0070}, {0x6094, 0x0071}, {0x60c1, 0x0073}, | |
61 | {0x6034, 0x003d}, {0x6057, 0x005a}, {0x60bb, 0x004f}, {0x609c, 0x0050}, | |
62 | {0x6080, 0x006d}, {0x6002, 0x0039}, {0x6033, 0x003a}, {0x60f1, 0x003b}, | |
63 | {0x6031, 0x003c}, {0x6000, 0x00ff}, {0x6014, 0x00e0}, {0x60ff, 0x0076}, | |
64 | {0x60a0, 0x0033}, {0x6020, 0x0042}, {0x6018, 0x0043}, {0x6000, 0x004c}, | |
65 | {0x60d0, 0x0087}, {0x600f, 0x0088}, {0x6003, 0x00d7}, {0x6010, 0x00d9}, | |
66 | {0x6005, 0x00da}, {0x6082, 0x00d3}, {0x60c0, 0x00f9}, {0x6006, 0x0044}, | |
67 | {0x6007, 0x00d1}, {0x6002, 0x00d2}, {0x6000, 0x00d2}, {0x6011, 0x00d8}, | |
68 | {0x6008, 0x00c8}, {0x6080, 0x00c9}, {0x6008, 0x007c}, {0x6020, 0x007d}, | |
69 | {0x6020, 0x007d}, {0x6000, 0x0090}, {0x600e, 0x0091}, {0x601a, 0x0091}, | |
70 | {0x6031, 0x0091}, {0x605a, 0x0091}, {0x6069, 0x0091}, {0x6075, 0x0091}, | |
71 | {0x607e, 0x0091}, {0x6088, 0x0091}, {0x608f, 0x0091}, {0x6096, 0x0091}, | |
72 | {0x60a3, 0x0091}, {0x60af, 0x0091}, {0x60c4, 0x0091}, {0x60d7, 0x0091}, | |
73 | {0x60e8, 0x0091}, {0x6020, 0x0091}, {0x6000, 0x0092}, {0x6006, 0x0093}, | |
74 | {0x60e3, 0x0093}, {0x6005, 0x0093}, {0x6005, 0x0093}, {0x6000, 0x0093}, | |
75 | {0x6004, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, | |
76 | {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, | |
77 | {0x6000, 0x0096}, {0x6008, 0x0097}, {0x6019, 0x0097}, {0x6002, 0x0097}, | |
78 | {0x600c, 0x0097}, {0x6024, 0x0097}, {0x6030, 0x0097}, {0x6028, 0x0097}, | |
79 | {0x6026, 0x0097}, {0x6002, 0x0097}, {0x6098, 0x0097}, {0x6080, 0x0097}, | |
80 | {0x6000, 0x0097}, {0x6000, 0x0097}, {0x60ed, 0x00c3}, {0x609a, 0x00c4}, | |
81 | {0x6000, 0x00a4}, {0x6011, 0x00c5}, {0x6051, 0x00c6}, {0x6010, 0x00c7}, | |
82 | {0x6066, 0x00b6}, {0x60a5, 0x00b8}, {0x6064, 0x00b7}, {0x607c, 0x00b9}, | |
83 | {0x60af, 0x00b3}, {0x6097, 0x00b4}, {0x60ff, 0x00b5}, {0x60c5, 0x00b0}, | |
84 | {0x6094, 0x00b1}, {0x600f, 0x00b2}, {0x605c, 0x00c4}, {0x6000, 0x00a8}, | |
85 | {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x601d, 0x0086}, {0x6000, 0x0050}, | |
86 | {0x6090, 0x0051}, {0x6018, 0x0052}, {0x6000, 0x0053}, {0x6000, 0x0054}, | |
87 | {0x6088, 0x0055}, {0x6000, 0x0057}, {0x6090, 0x005a}, {0x6018, 0x005b}, | |
88 | {0x6005, 0x005c}, {0x60ed, 0x00c3}, {0x6000, 0x007f}, {0x6005, 0x00da}, | |
89 | {0x601f, 0x00e5}, {0x6067, 0x00e1}, {0x6000, 0x00e0}, {0x60ff, 0x00dd}, | |
90 | {0x6000, 0x0005}, {0x6001, 0x00ff}, {0x6000, 0x0000}, {0x6000, 0x0045}, | |
91 | {0x6000, 0x0010}, | |
92 | }; | |
93 | ||
be9904bd | 94 | static struct validx tbl_sensor_settings_common1[] = { |
4f7cb883 OL |
95 | {0x0041, 0x0000}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d}, |
96 | {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2}, | |
97 | {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0041, 0x0000}, | |
98 | {50, 0xffff}, | |
99 | {0x0061, 0x0000}, | |
100 | {0xffff, 0xffff}, | |
101 | {0x6000, 0x00ff}, {0x6000, 0x007c}, {0x6007, 0x007d}, | |
102 | {30, 0xffff}, | |
103 | {0x0040, 0x0000}, | |
104 | }; | |
105 | ||
be9904bd | 106 | static struct validx tbl_sensor_settings_common2[] = { |
4f7cb883 OL |
107 | {0x6001, 0x00ff}, {0x6038, 0x000c}, |
108 | {10, 0xffff}, | |
109 | {0x6000, 0x0011}, | |
4f7cb883 OL |
110 | }; |
111 | ||
112 | static struct validx tbl_640[] = { | |
113 | {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, {0x6067, 0x00e1}, | |
114 | {0x6004, 0x00da}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, | |
115 | {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0011}, {0x6011, 0x0017}, | |
116 | {0x6075, 0x0018}, {0x6001, 0x0019}, {0x6097, 0x001a}, {0x6036, 0x0032}, | |
117 | {0x60bb, 0x004f}, {0x6057, 0x005a}, {0x609c, 0x0050}, {0x6080, 0x006d}, | |
118 | {0x6092, 0x0026}, {0x60ff, 0x0020}, {0x6000, 0x0027}, {0x6000, 0x00ff}, | |
119 | {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c}, {0x603d, 0x0086}, | |
120 | {0x6089, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052}, {0x6000, 0x0053}, | |
121 | {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057}, {0x60a0, 0x005a}, | |
122 | {0x6078, 0x005b}, {0x6000, 0x005c}, {0x6004, 0x00d3}, {0x6000, 0x00e0}, | |
123 | {0x60ff, 0x00dd}, {0x60a1, 0x005a}, | |
124 | }; | |
125 | ||
126 | static struct validx tbl_800[] = { | |
127 | {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, {0x6067, 0x00e1}, | |
128 | {0x6004, 0x00da}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, | |
129 | {0x6001, 0x00ff}, {0x6040, 0x0012}, {0x6000, 0x0011}, {0x6011, 0x0017}, | |
130 | {0x6043, 0x0018}, {0x6000, 0x0019}, {0x604b, 0x001a}, {0x6009, 0x0032}, | |
131 | {0x60ca, 0x004f}, {0x60a8, 0x0050}, {0x6000, 0x006d}, {0x6038, 0x003d}, | |
132 | {0x60c8, 0x0035}, {0x6000, 0x0022}, {0x6092, 0x0026}, {0x60ff, 0x0020}, | |
133 | {0x6000, 0x0027}, {0x6000, 0x00ff}, {0x6064, 0x00c0}, {0x604b, 0x00c1}, | |
134 | {0x6000, 0x008c}, {0x601d, 0x0086}, {0x6082, 0x00d3}, {0x6000, 0x00e0}, | |
135 | {0x60ff, 0x00dd}, {0x6020, 0x008c}, {0x6001, 0x00ff}, {0x6044, 0x0018}, | |
136 | }; | |
137 | ||
be9904bd | 138 | static struct validx tbl_big1[] = { |
4f7cb883 OL |
139 | {0x0002, 0x00c1}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, |
140 | {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045}, | |
141 | {0x6000, 0x0010}, {0x6000, 0x0011}, {0x6011, 0x0017}, {0x6075, 0x0018}, | |
142 | {0x6001, 0x0019}, {0x6097, 0x001a}, {0x6036, 0x0032}, {0x60bb, 0x004f}, | |
143 | {0x609c, 0x0050}, {0x6057, 0x005a}, {0x6080, 0x006d}, {0x6043, 0x000f}, | |
144 | {0x608f, 0x0003}, {0x6005, 0x007c}, {0x6081, 0x0026}, {0x6000, 0x00ff}, | |
145 | {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c}, | |
146 | }; | |
147 | ||
be9904bd | 148 | static struct validx tbl_big2[] = { |
4f7cb883 OL |
149 | {0x603d, 0x0086}, {0x6000, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052}, |
150 | {0x6000, 0x0053}, {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057}, | |
151 | {0x6040, 0x005a}, {0x60f0, 0x005b}, {0x6001, 0x005c}, {0x6082, 0x00d3}, | |
152 | {0x6000, 0x008e}, | |
153 | }; | |
154 | ||
be9904bd | 155 | static struct validx tbl_big3[] = { |
4f7cb883 OL |
156 | {0x6004, 0x00da}, {0x6000, 0x00e0}, {0x6067, 0x00e1}, {0x60ff, 0x00dd}, |
157 | {0x6001, 0x00ff}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, | |
158 | {0x6001, 0x00ff}, {0x6000, 0x0011}, {0x6000, 0x00ff}, {0x6010, 0x00c7}, | |
159 | {0x6000, 0x0092}, {0x6006, 0x0093}, {0x60e3, 0x0093}, {0x6005, 0x0093}, | |
160 | {0x6005, 0x0093}, {0x60ed, 0x00c3}, {0x6000, 0x00a4}, {0x60d0, 0x0087}, | |
161 | {0x6003, 0x0096}, {0x600c, 0x0097}, {0x6024, 0x0097}, {0x6030, 0x0097}, | |
162 | {0x6028, 0x0097}, {0x6026, 0x0097}, {0x6002, 0x0097}, {0x6001, 0x00ff}, | |
163 | {0x6043, 0x000f}, {0x608f, 0x0003}, {0x6000, 0x002d}, {0x6000, 0x002e}, | |
164 | {0x600a, 0x0022}, {0x6002, 0x0070}, {0x6008, 0x0014}, {0x6048, 0x0014}, | |
165 | {0x6000, 0x00ff}, {0x6000, 0x00e0}, {0x60ff, 0x00dd}, | |
166 | }; | |
167 | ||
168 | static struct validx tbl_post_unset_alt[] = { | |
169 | {0x006a, 0x000d}, {0x6001, 0x00ff}, {0x6081, 0x0026}, {0x6000, 0x0000}, | |
170 | {0x6000, 0x0045}, {0x6000, 0x0010}, {0x6068, 0x000d}, | |
171 | {50, 0xffff}, | |
172 | {0x0021, 0x0000}, | |
173 | }; | |
174 | ||
175 | static int ov2640_init_at_startup(struct gspca_dev *gspca_dev); | |
176 | static int ov2640_configure_alt(struct gspca_dev *gspca_dev); | |
177 | static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev); | |
178 | static int ov2640_init_post_alt(struct gspca_dev *gspca_dev); | |
179 | static void ov2640_post_unset_alt(struct gspca_dev *gspca_dev); | |
180 | static int ov2640_camera_settings(struct gspca_dev *gspca_dev); | |
181 | /*==========================================================================*/ | |
182 | ||
183 | void ov2640_init_settings(struct gspca_dev *gspca_dev) | |
184 | { | |
185 | struct sd *sd = (struct sd *) gspca_dev; | |
186 | ||
187 | sd->vcur.backlight = 32; | |
188 | sd->vcur.brightness = 0; | |
189 | sd->vcur.sharpness = 6; | |
190 | sd->vcur.contrast = 0; | |
191 | sd->vcur.gamma = 32; | |
192 | sd->vcur.hue = 0; | |
193 | sd->vcur.saturation = 128; | |
194 | sd->vcur.whitebal = 64; | |
fdd1dd1d OL |
195 | sd->vcur.mirror = 0; |
196 | sd->vcur.flip = 0; | |
4f7cb883 OL |
197 | |
198 | sd->vmax.backlight = 64; | |
199 | sd->vmax.brightness = 255; | |
200 | sd->vmax.sharpness = 31; | |
201 | sd->vmax.contrast = 255; | |
202 | sd->vmax.gamma = 64; | |
fdd1dd1d | 203 | sd->vmax.hue = 254 + 2; |
4f7cb883 OL |
204 | sd->vmax.saturation = 255; |
205 | sd->vmax.whitebal = 128; | |
fdd1dd1d OL |
206 | sd->vmax.mirror = 1; |
207 | sd->vmax.flip = 1; | |
4f7cb883 OL |
208 | sd->vmax.AC50Hz = 0; |
209 | ||
210 | sd->dev_camera_settings = ov2640_camera_settings; | |
211 | sd->dev_init_at_startup = ov2640_init_at_startup; | |
212 | sd->dev_configure_alt = ov2640_configure_alt; | |
213 | sd->dev_init_pre_alt = ov2640_init_pre_alt; | |
214 | sd->dev_post_unset_alt = ov2640_post_unset_alt; | |
215 | } | |
216 | ||
217 | /*==========================================================================*/ | |
218 | ||
219 | static void common(struct gspca_dev *gspca_dev) | |
220 | { | |
221 | fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common)); | |
222 | } | |
223 | ||
224 | static int ov2640_init_at_startup(struct gspca_dev *gspca_dev) | |
225 | { | |
226 | fetch_validx(gspca_dev, tbl_init_at_startup, | |
227 | ARRAY_SIZE(tbl_init_at_startup)); | |
228 | ||
229 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_init1); | |
230 | ||
231 | common(gspca_dev); | |
232 | ||
fdd1dd1d | 233 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0006, 1, c61); |
4f7cb883 OL |
234 | |
235 | ctrl_out(gspca_dev, 0x40, 1, 0x00ef, 0x0006, 0, NULL); | |
236 | ||
fdd1dd1d | 237 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c51); |
4f7cb883 OL |
238 | |
239 | ctrl_out(gspca_dev, 0x40, 1, 0x0051, 0x0000, 0, NULL); | |
240 | /* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */ | |
241 | ||
242 | return 0; | |
243 | } | |
244 | ||
245 | static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev) | |
246 | { | |
247 | struct sd *sd = (struct sd *) gspca_dev; | |
248 | ||
be9904bd OL |
249 | sd->mirrorMask = 0; |
250 | ||
4f7cb883 OL |
251 | sd->vold.backlight = -1; |
252 | sd->vold.brightness = -1; | |
253 | sd->vold.sharpness = -1; | |
254 | sd->vold.contrast = -1; | |
255 | sd->vold.saturation = -1; | |
256 | sd->vold.gamma = -1; | |
257 | sd->vold.hue = -1; | |
258 | sd->vold.whitebal = -1; | |
fdd1dd1d OL |
259 | sd->vold.mirror = -1; |
260 | sd->vold.flip = -1; | |
4f7cb883 OL |
261 | |
262 | ov2640_init_post_alt(gspca_dev); | |
263 | ||
264 | return 0; | |
265 | } | |
266 | ||
267 | static int ov2640_init_post_alt(struct gspca_dev *gspca_dev) | |
268 | { | |
269 | s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; | |
be9904bd | 270 | s32 n; /* reserved for FETCH functions */ |
4f7cb883 OL |
271 | |
272 | ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL); | |
273 | ||
be9904bd OL |
274 | n = fetch_validx(gspca_dev, tbl_sensor_settings_common1, |
275 | ARRAY_SIZE(tbl_sensor_settings_common1)); | |
4f7cb883 OL |
276 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_post); |
277 | common(gspca_dev); | |
be9904bd OL |
278 | keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common1, |
279 | ARRAY_SIZE(tbl_sensor_settings_common1), n); | |
4f7cb883 OL |
280 | |
281 | switch (reso) { | |
282 | case IMAGE_640: | |
283 | n = fetch_validx(gspca_dev, tbl_640, ARRAY_SIZE(tbl_640)); | |
284 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_640); | |
285 | break; | |
286 | ||
287 | case IMAGE_800: | |
288 | n = fetch_validx(gspca_dev, tbl_800, ARRAY_SIZE(tbl_800)); | |
289 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_800); | |
290 | break; | |
291 | ||
292 | case IMAGE_1600: | |
293 | case IMAGE_1280: | |
be9904bd | 294 | n = fetch_validx(gspca_dev, tbl_big1, ARRAY_SIZE(tbl_big1)); |
4f7cb883 OL |
295 | |
296 | if (reso == IMAGE_1280) { | |
be9904bd OL |
297 | n = fetch_validx(gspca_dev, tbl_big2, |
298 | ARRAY_SIZE(tbl_big2)); | |
4f7cb883 OL |
299 | } else { |
300 | ctrl_out(gspca_dev, 0x40, 1, 0x601d, 0x0086, 0, NULL); | |
301 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00d7, 0, NULL); | |
302 | ctrl_out(gspca_dev, 0x40, 1, 0x6082, 0x00d3, 0, NULL); | |
303 | } | |
304 | ||
be9904bd | 305 | n = fetch_validx(gspca_dev, tbl_big3, ARRAY_SIZE(tbl_big3)); |
4f7cb883 OL |
306 | |
307 | if (reso == IMAGE_1280) { | |
308 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); | |
309 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, | |
310 | 12, dat_1280); | |
311 | } else { | |
312 | ctrl_out(gspca_dev, 0x40, 1, 0x6020, 0x008c, 0, NULL); | |
313 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); | |
314 | ctrl_out(gspca_dev, 0x40, 1, 0x6076, 0x0018, 0, NULL); | |
315 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, | |
316 | 12, dat_1600); | |
317 | } | |
318 | break; | |
319 | } | |
320 | ||
be9904bd OL |
321 | n = fetch_validx(gspca_dev, tbl_sensor_settings_common2, |
322 | ARRAY_SIZE(tbl_sensor_settings_common2)); | |
4f7cb883 OL |
323 | |
324 | ov2640_camera_settings(gspca_dev); | |
325 | ||
326 | return 0; | |
327 | } | |
328 | ||
329 | static int ov2640_configure_alt(struct gspca_dev *gspca_dev) | |
330 | { | |
331 | s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; | |
332 | ||
333 | switch (reso) { | |
334 | case IMAGE_640: | |
335 | gspca_dev->alt = 3 + 1; | |
336 | break; | |
337 | ||
338 | case IMAGE_800: | |
339 | case IMAGE_1280: | |
340 | case IMAGE_1600: | |
341 | gspca_dev->alt = 1 + 1; | |
342 | break; | |
343 | } | |
344 | return 0; | |
345 | } | |
346 | ||
347 | static int ov2640_camera_settings(struct gspca_dev *gspca_dev) | |
348 | { | |
349 | struct sd *sd = (struct sd *) gspca_dev; | |
350 | ||
351 | s32 backlight = sd->vcur.backlight; | |
352 | s32 bright = sd->vcur.brightness; | |
353 | s32 sharp = sd->vcur.sharpness; | |
354 | s32 gam = sd->vcur.gamma; | |
355 | s32 cntr = sd->vcur.contrast; | |
356 | s32 sat = sd->vcur.saturation; | |
357 | s32 hue = sd->vcur.hue; | |
358 | s32 wbal = sd->vcur.whitebal; | |
fdd1dd1d OL |
359 | s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) == 0); |
360 | s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) == 0); | |
4f7cb883 OL |
361 | |
362 | if (backlight != sd->vold.backlight) { | |
be9904bd | 363 | /* No sd->vold.backlight=backlight; (to be done again later) */ |
4f7cb883 OL |
364 | if (backlight < 0 || backlight > sd->vmax.backlight) |
365 | backlight = 0; | |
366 | ||
367 | ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, | |
368 | 0, NULL); | |
fdd1dd1d | 369 | ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight , 0x0024, |
4f7cb883 | 370 | 0, NULL); |
fdd1dd1d | 371 | ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025, |
4f7cb883 | 372 | 0, NULL); |
4f7cb883 OL |
373 | } |
374 | ||
375 | if (bright != sd->vold.brightness) { | |
376 | sd->vold.brightness = bright; | |
377 | if (bright < 0 || bright > sd->vmax.brightness) | |
378 | bright = 0; | |
379 | ||
380 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); | |
381 | ctrl_out(gspca_dev, 0x40, 1, 0x6009 , 0x007c, 0, NULL); | |
382 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + bright, 0x007d, 0, NULL); | |
383 | } | |
384 | ||
385 | if (wbal != sd->vold.whitebal) { | |
386 | sd->vold.whitebal = wbal; | |
387 | if (wbal < 0 || wbal > sd->vmax.whitebal) | |
388 | wbal = 0; | |
389 | ||
390 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); | |
391 | ctrl_out(gspca_dev, 0x40, 1, 0x6003 , 0x007c, 0, NULL); | |
392 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + wbal, 0x007d, 0, NULL); | |
393 | } | |
394 | ||
395 | if (cntr != sd->vold.contrast) { | |
396 | sd->vold.contrast = cntr; | |
397 | if (cntr < 0 || cntr > sd->vmax.contrast) | |
398 | cntr = 0; | |
399 | ||
400 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); | |
401 | ctrl_out(gspca_dev, 0x40, 1, 0x6007 , 0x007c, 0, NULL); | |
402 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + cntr, 0x007d, 0, NULL); | |
403 | } | |
404 | ||
405 | if (sat != sd->vold.saturation) { | |
406 | sd->vold.saturation = sat; | |
407 | if (sat < 0 || sat > sd->vmax.saturation) | |
408 | sat = 0; | |
409 | ||
410 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); | |
411 | ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x007c, 0, NULL); | |
412 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + sat, 0x007d, 0, NULL); | |
413 | } | |
414 | ||
415 | if (sharp != sd->vold.sharpness) { | |
416 | sd->vold.sharpness = sharp; | |
417 | if (sharp < 0 || sharp > sd->vmax.sharpness) | |
418 | sharp = 0; | |
419 | ||
420 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); | |
421 | ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x0092, 0, NULL); | |
422 | ctrl_out(gspca_dev, 0x40, 1, 0x60c0 + sharp, 0x0093, 0, NULL); | |
423 | } | |
424 | ||
425 | if (hue != sd->vold.hue) { | |
426 | sd->vold.hue = hue; | |
427 | if (hue < 0 || hue > sd->vmax.hue) | |
428 | hue = 0; | |
429 | ||
430 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); | |
431 | ctrl_out(gspca_dev, 0x40, 1, 0x6002 , 0x007c, 0, NULL); | |
432 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + hue * (hue < 255), 0x007d, | |
433 | 0, NULL); | |
fdd1dd1d | 434 | if (hue >= 255) |
4f7cb883 OL |
435 | sd->swapRB = 1; |
436 | else | |
437 | sd->swapRB = 0; | |
438 | } | |
439 | ||
440 | if (gam != sd->vold.gamma) { | |
441 | sd->vold.gamma = gam; | |
442 | if (gam < 0 || gam > sd->vmax.gamma) | |
443 | gam = 0; | |
444 | ||
445 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); | |
446 | ctrl_out(gspca_dev, 0x40, 1, 0x6008 , 0x007c, 0, NULL); | |
447 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + gam, 0x007d, 0, NULL); | |
448 | } | |
449 | ||
fdd1dd1d OL |
450 | if (mirror != sd->vold.mirror || flip != sd->vold.flip) { |
451 | sd->vold.mirror = mirror; | |
452 | sd->vold.flip = flip; | |
453 | ||
454 | mirror = 0x80 * mirror; | |
455 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); | |
456 | ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL); | |
457 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28); | |
458 | ctrl_out(gspca_dev, 0x40, 1, 0x6028 + mirror, 0x0004, 0, NULL); | |
459 | ||
460 | flip = 0x50 * flip + mirror; | |
461 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); | |
462 | ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL); | |
463 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8); | |
464 | ctrl_out(gspca_dev, 0x40, 1, 0x6028 + flip, 0x0004, 0, NULL); | |
465 | ||
466 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); | |
467 | } | |
468 | ||
4f7cb883 OL |
469 | if (backlight != sd->vold.backlight) { |
470 | sd->vold.backlight = backlight; | |
471 | ||
472 | ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, | |
473 | 0, NULL); | |
fdd1dd1d | 474 | ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight , 0x0024, |
4f7cb883 | 475 | 0, NULL); |
fdd1dd1d | 476 | ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025, |
4f7cb883 OL |
477 | 0, NULL); |
478 | } | |
479 | ||
480 | return 0; | |
481 | } | |
482 | ||
483 | static void ov2640_post_unset_alt(struct gspca_dev *gspca_dev) | |
484 | { | |
485 | ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL); | |
486 | msleep(20); | |
487 | fetch_validx(gspca_dev, tbl_post_unset_alt, | |
488 | ARRAY_SIZE(tbl_post_unset_alt)); | |
489 | } |