GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / media / usb / gspca / gl860 / gl860-ov9655.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Subdriver for the GL860 chip with the OV9655 sensor
3  * Author Olivier LORIN, from logs done by Simon (Sur3) and Almighurt
4  * on dsd's weblog
5  */
6
7 /* Sensor : OV9655 */
8
9 #include "gl860.h"
10
11 static struct validx tbl_init_at_startup[] = {
12         {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1},
13         {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d},
14
15         {0x0040, 0x0000},
16 };
17
18 static struct validx tbl_commmon[] = {
19         {0x0041, 0x0000}, {0x006a, 0x0007}, {0x0063, 0x0006}, {0x006a, 0x000d},
20         {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2},
21         {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0040, 0x0000},
22         {0x00f3, 0x0006}, {0x0058, 0x0000}, {0x0048, 0x0000}, {0x0061, 0x0000},
23 };
24
25 static s32 tbl_length[] = {12, 56, 52, 54, 56, 42, 32, 12};
26
27 static u8 *tbl_640[] = {
28         (u8[]){
29                 0x00, 0x40, 0x07, 0x6a, 0x06, 0xf3, 0x0d, 0x6a,
30                 0x10, 0x10, 0xc1, 0x01
31         }, (u8[]){
32                 0x12, 0x80, 0x00, 0x00, 0x01, 0x98, 0x02, 0x80,
33                 0x03, 0x12, 0x04, 0x03, 0x0b, 0x57, 0x0e, 0x61,
34                 0x0f, 0x42, 0x11, 0x01, 0x12, 0x60, 0x13, 0x00,
35                 0x14, 0x3a, 0x16, 0x24, 0x17, 0x14, 0x18, 0x00,
36                 0x19, 0x01, 0x1a, 0x3d, 0x1e, 0x04, 0x24, 0x3c,
37                 0x25, 0x36, 0x26, 0x72, 0x27, 0x08, 0x28, 0x08,
38                 0x29, 0x15, 0x2a, 0x00, 0x2b, 0x00, 0x2c, 0x08
39         }, (u8[]){
40                 0x32, 0xff, 0x33, 0x00, 0x34, 0x3d, 0x35, 0x00,
41                 0x36, 0xfa, 0x38, 0x72, 0x39, 0x57, 0x3a, 0x00,
42                 0x3b, 0x0c, 0x3d, 0x99, 0x3e, 0x0c, 0x3f, 0xc1,
43                 0x40, 0xc0, 0x41, 0x00, 0x42, 0xc0, 0x43, 0x0a,
44                 0x44, 0xf0, 0x45, 0x46, 0x46, 0x62, 0x47, 0x2a,
45                 0x48, 0x3c, 0x4a, 0xee, 0x4b, 0xe7, 0x4c, 0xe7,
46                 0x4d, 0xe7, 0x4e, 0xe7
47         }, (u8[]){
48                 0x4f, 0x98, 0x50, 0x98, 0x51, 0x00, 0x52, 0x28,
49                 0x53, 0x70, 0x54, 0x98, 0x58, 0x1a, 0x59, 0x85,
50                 0x5a, 0xa9, 0x5b, 0x64, 0x5c, 0x84, 0x5d, 0x53,
51                 0x5e, 0x0e, 0x5f, 0xf0, 0x60, 0xf0, 0x61, 0xf0,
52                 0x62, 0x00, 0x63, 0x00, 0x64, 0x02, 0x65, 0x20,
53                 0x66, 0x00, 0x69, 0x0a, 0x6b, 0x5a, 0x6c, 0x04,
54                 0x6d, 0x55, 0x6e, 0x00, 0x6f, 0x9d
55         }, (u8[]){
56                 0x70, 0x15, 0x71, 0x78, 0x72, 0x00, 0x73, 0x00,
57                 0x74, 0x3a, 0x75, 0x35, 0x76, 0x01, 0x77, 0x02,
58                 0x7a, 0x24, 0x7b, 0x04, 0x7c, 0x07, 0x7d, 0x10,
59                 0x7e, 0x28, 0x7f, 0x36, 0x80, 0x44, 0x81, 0x52,
60                 0x82, 0x60, 0x83, 0x6c, 0x84, 0x78, 0x85, 0x8c,
61                 0x86, 0x9e, 0x87, 0xbb, 0x88, 0xd2, 0x89, 0xe5,
62                 0x8a, 0x23, 0x8c, 0x8d, 0x90, 0x7c, 0x91, 0x7b
63         }, (u8[]){
64                 0x9d, 0x02, 0x9e, 0x02, 0x9f, 0x74, 0xa0, 0x73,
65                 0xa1, 0x40, 0xa4, 0x50, 0xa5, 0x68, 0xa6, 0x70,
66                 0xa8, 0xc1, 0xa9, 0xef, 0xaa, 0x92, 0xab, 0x04,
67                 0xac, 0x80, 0xad, 0x80, 0xae, 0x80, 0xaf, 0x80,
68                 0xb2, 0xf2, 0xb3, 0x20, 0xb4, 0x20, 0xb5, 0x00,
69                 0xb6, 0xaf
70         }, (u8[]){
71                 0xbb, 0xae, 0xbc, 0x4f, 0xbd, 0x4e, 0xbe, 0x6a,
72                 0xbf, 0x68, 0xc0, 0xaa, 0xc1, 0xc0, 0xc2, 0x01,
73                 0xc3, 0x4e, 0xc6, 0x85, 0xc7, 0x81, 0xc9, 0xe0,
74                 0xca, 0xe8, 0xcb, 0xf0, 0xcc, 0xd8, 0xcd, 0x93
75         }, (u8[]){
76                 0xd0, 0x01, 0xd1, 0x08, 0xd2, 0xe0, 0xd3, 0x01,
77                 0xd4, 0x10, 0xd5, 0x80
78         }
79 };
80
81 static u8 *tbl_1280[] = {
82         (u8[]){
83                 0x00, 0x40, 0x07, 0x6a, 0x06, 0xf3, 0x0d, 0x6a,
84                 0x10, 0x10, 0xc1, 0x01
85         },
86         (u8[]){
87                 0x12, 0x80, 0x00, 0x00, 0x01, 0x98, 0x02, 0x80,
88                 0x03, 0x12, 0x04, 0x01, 0x0b, 0x57, 0x0e, 0x61,
89                 0x0f, 0x42, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00,
90                 0x14, 0x3a, 0x16, 0x24, 0x17, 0x1b, 0x18, 0xbb,
91                 0x19, 0x01, 0x1a, 0x81, 0x1e, 0x04, 0x24, 0x3c,
92                 0x25, 0x36, 0x26, 0x72, 0x27, 0x08, 0x28, 0x08,
93                 0x29, 0x15, 0x2a, 0x00, 0x2b, 0x00, 0x2c, 0x08
94         },
95         (u8[]){
96                 0x32, 0xa4, 0x33, 0x00, 0x34, 0x3d, 0x35, 0x00,
97                 0x36, 0xf8, 0x38, 0x72, 0x39, 0x57, 0x3a, 0x00,
98                 0x3b, 0x0c, 0x3d, 0x99, 0x3e, 0x0c, 0x3f, 0xc2,
99                 0x40, 0xc0, 0x41, 0x00, 0x42, 0xc0, 0x43, 0x0a,
100                 0x44, 0xf0, 0x45, 0x46, 0x46, 0x62, 0x47, 0x2a,
101                 0x48, 0x3c, 0x4a, 0xec, 0x4b, 0xe8, 0x4c, 0xe8,
102                 0x4d, 0xe8, 0x4e, 0xe8
103         },
104         (u8[]){
105                 0x4f, 0x98, 0x50, 0x98, 0x51, 0x00, 0x52, 0x28,
106                 0x53, 0x70, 0x54, 0x98, 0x58, 0x1a, 0x59, 0x85,
107                 0x5a, 0xa9, 0x5b, 0x64, 0x5c, 0x84, 0x5d, 0x53,
108                 0x5e, 0x0e, 0x5f, 0xf0, 0x60, 0xf0, 0x61, 0xf0,
109                 0x62, 0x00, 0x63, 0x00, 0x64, 0x02, 0x65, 0x20,
110                 0x66, 0x00, 0x69, 0x02, 0x6b, 0x5a, 0x6c, 0x04,
111                 0x6d, 0x55, 0x6e, 0x00, 0x6f, 0x9d
112         },
113         (u8[]){
114                 0x70, 0x08, 0x71, 0x78, 0x72, 0x00, 0x73, 0x01,
115                 0x74, 0x3a, 0x75, 0x35, 0x76, 0x01, 0x77, 0x02,
116                 0x7a, 0x24, 0x7b, 0x04, 0x7c, 0x07, 0x7d, 0x10,
117                 0x7e, 0x28, 0x7f, 0x36, 0x80, 0x44, 0x81, 0x52,
118                 0x82, 0x60, 0x83, 0x6c, 0x84, 0x78, 0x85, 0x8c,
119                 0x86, 0x9e, 0x87, 0xbb, 0x88, 0xd2, 0x89, 0xe5,
120                 0x8a, 0x23, 0x8c, 0x0d, 0x90, 0x90, 0x91, 0x90
121         },
122         (u8[]){
123                 0x9d, 0x02, 0x9e, 0x02, 0x9f, 0x94, 0xa0, 0x94,
124                 0xa1, 0x01, 0xa4, 0x50, 0xa5, 0x68, 0xa6, 0x70,
125                 0xa8, 0xc1, 0xa9, 0xef, 0xaa, 0x92, 0xab, 0x04,
126                 0xac, 0x80, 0xad, 0x80, 0xae, 0x80, 0xaf, 0x80,
127                 0xb2, 0xf2, 0xb3, 0x20, 0xb4, 0x20, 0xb5, 0x00,
128                 0xb6, 0xaf
129         },
130         (u8[]){
131                 0xbb, 0xae, 0xbc, 0x38, 0xbd, 0x39, 0xbe, 0x01,
132                 0xbf, 0x01, 0xc0, 0xe2, 0xc1, 0xc0, 0xc2, 0x01,
133                 0xc3, 0x4e, 0xc6, 0x85, 0xc7, 0x81, 0xc9, 0xe0,
134                 0xca, 0xe8, 0xcb, 0xf0, 0xcc, 0xd8, 0xcd, 0x93
135         },
136         (u8[]){
137                 0xd0, 0x21, 0xd1, 0x18, 0xd2, 0xe0, 0xd3, 0x01,
138                 0xd4, 0x28, 0xd5, 0x00
139         }
140 };
141
142 static u8 c04[] = {0x04};
143 static u8 dat_post1[] = "\x04\x00\x10\x20\xa1\x00\x00\x02";
144 static u8 dat_post2[] = "\x10\x10\xc1\x02";
145 static u8 dat_post3[] = "\x04\x00\x10\x7c\xa1\x00\x00\x04";
146 static u8 dat_post4[] = "\x10\x02\xc1\x06";
147 static u8 dat_post5[] = "\x04\x00\x10\x7b\xa1\x00\x00\x08";
148 static u8 dat_post6[] = "\x10\x10\xc1\x05";
149 static u8 dat_post7[] = "\x04\x00\x10\x7c\xa1\x00\x00\x08";
150 static u8 dat_post8[] = "\x04\x00\x10\x7c\xa1\x00\x00\x09";
151
152 static struct validx tbl_init_post_alt[] = {
153         {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x603c, 0x00ff},
154         {0x6003, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6001, 0x00ff},
155         {0x6000, 0x801e},
156         {0xffff, 0xffff},
157         {0x6004, 0x001e}, {0x6000, 0x801e},
158         {0xffff, 0xffff},
159         {0x6004, 0x001e}, {0x6012, 0x0003}, {0x6000, 0x801e},
160         {0xffff, 0xffff},
161         {0x6004, 0x001e}, {0x6000, 0x801e},
162         {0xffff, 0xffff},
163         {0x6004, 0x001e}, {0x6012, 0x0003},
164         {0xffff, 0xffff},
165         {0x6000, 0x801e},
166         {0xffff, 0xffff},
167         {0x6004, 0x001e}, {0x6000, 0x801e},
168         {0xffff, 0xffff},
169         {0x6004, 0x001e}, {0x6012, 0x0003}, {0x6000, 0x801e},
170         {0xffff, 0xffff},
171         {0x6004, 0x001e}, {0x6000, 0x801e},
172         {0xffff, 0xffff},
173         {0x6004, 0x001e}, {0x6012, 0x0003},
174         {0xffff, 0xffff},
175         {0x6000, 0x801e},
176         {0xffff, 0xffff},
177         {0x6004, 0x001e}, {0x6000, 0x801e},
178         {0xffff, 0xffff},
179         {0x6004, 0x001e}, {0x6012, 0x0003},
180 };
181
182 static int  ov9655_init_at_startup(struct gspca_dev *gspca_dev);
183 static int  ov9655_configure_alt(struct gspca_dev *gspca_dev);
184 static int  ov9655_init_pre_alt(struct gspca_dev *gspca_dev);
185 static int  ov9655_init_post_alt(struct gspca_dev *gspca_dev);
186 static void ov9655_post_unset_alt(struct gspca_dev *gspca_dev);
187 static int  ov9655_camera_settings(struct gspca_dev *gspca_dev);
188 /*==========================================================================*/
189
190 void ov9655_init_settings(struct gspca_dev *gspca_dev)
191 {
192         struct sd *sd = (struct sd *) gspca_dev;
193
194         sd->vcur.backlight  =   0;
195         sd->vcur.brightness = 128;
196         sd->vcur.sharpness  =   0;
197         sd->vcur.contrast   =   0;
198         sd->vcur.gamma      =   0;
199         sd->vcur.hue        =   0;
200         sd->vcur.saturation =   0;
201         sd->vcur.whitebal   =   0;
202
203         sd->vmax.backlight  =   0;
204         sd->vmax.brightness = 255;
205         sd->vmax.sharpness  =   0;
206         sd->vmax.contrast   =   0;
207         sd->vmax.gamma      =   0;
208         sd->vmax.hue        =   0 + 1;
209         sd->vmax.saturation =   0;
210         sd->vmax.whitebal   =   0;
211         sd->vmax.mirror     = 0;
212         sd->vmax.flip       = 0;
213         sd->vmax.AC50Hz     = 0;
214
215         sd->dev_camera_settings = ov9655_camera_settings;
216         sd->dev_init_at_startup = ov9655_init_at_startup;
217         sd->dev_configure_alt   = ov9655_configure_alt;
218         sd->dev_init_pre_alt    = ov9655_init_pre_alt;
219         sd->dev_post_unset_alt  = ov9655_post_unset_alt;
220 }
221
222 /*==========================================================================*/
223
224 static int ov9655_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         fetch_validx(gspca_dev, tbl_commmon, ARRAY_SIZE(tbl_commmon));
229 /*      ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL);*/
230
231         return 0;
232 }
233
234 static int ov9655_init_pre_alt(struct gspca_dev *gspca_dev)
235 {
236         struct sd *sd = (struct sd *) gspca_dev;
237
238         sd->vold.brightness = -1;
239         sd->vold.hue = -1;
240
241         fetch_validx(gspca_dev, tbl_commmon, ARRAY_SIZE(tbl_commmon));
242
243         ov9655_init_post_alt(gspca_dev);
244
245         return 0;
246 }
247
248 static int ov9655_init_post_alt(struct gspca_dev *gspca_dev)
249 {
250         s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
251         s32 n; /* reserved for FETCH functions */
252         s32 i;
253         u8 **tbl;
254
255         ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
256
257         tbl = (reso == IMAGE_640) ? tbl_640 : tbl_1280;
258
259         ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
260                         tbl_length[0], tbl[0]);
261         for (i = 1; i < 7; i++)
262                 ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200,
263                                 tbl_length[i], tbl[i]);
264         ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
265                         tbl_length[7], tbl[7]);
266
267         n = fetch_validx(gspca_dev, tbl_init_post_alt,
268                         ARRAY_SIZE(tbl_init_post_alt));
269
270         ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
271         keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
272                                         ARRAY_SIZE(tbl_init_post_alt), n);
273         ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
274         keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
275                                         ARRAY_SIZE(tbl_init_post_alt), n);
276         ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
277         keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
278                                         ARRAY_SIZE(tbl_init_post_alt), n);
279         ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
280         keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
281                                         ARRAY_SIZE(tbl_init_post_alt), n);
282         ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1);
283         keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
284                                         ARRAY_SIZE(tbl_init_post_alt), n);
285
286         ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
287         keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
288                                         ARRAY_SIZE(tbl_init_post_alt), n);
289         ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
290         keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
291                                         ARRAY_SIZE(tbl_init_post_alt), n);
292         ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
293         keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
294                                         ARRAY_SIZE(tbl_init_post_alt), n);
295         ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
296         keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
297                                         ARRAY_SIZE(tbl_init_post_alt), n);
298         ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1);
299         keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
300                                         ARRAY_SIZE(tbl_init_post_alt), n);
301
302         ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
303         keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
304                                         ARRAY_SIZE(tbl_init_post_alt), n);
305         ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
306         keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
307                                         ARRAY_SIZE(tbl_init_post_alt), n);
308
309         ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1);
310
311         ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post2);
312         ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post3);
313
314         ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post4);
315         ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post5);
316
317         ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post6);
318         ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post7);
319
320         ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post8);
321
322         ov9655_camera_settings(gspca_dev);
323
324         return 0;
325 }
326
327 static int ov9655_configure_alt(struct gspca_dev *gspca_dev)
328 {
329         s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
330
331         switch (reso) {
332         case IMAGE_640:
333                 gspca_dev->alt = 1 + 1;
334                 break;
335
336         default:
337                 gspca_dev->alt = 1 + 1;
338                 break;
339         }
340         return 0;
341 }
342
343 static int ov9655_camera_settings(struct gspca_dev *gspca_dev)
344 {
345         struct sd *sd = (struct sd *) gspca_dev;
346
347         u8 dat_bright[] = "\x04\x00\x10\x7c\xa1\x00\x00\x70";
348
349         s32 bright = sd->vcur.brightness;
350         s32 hue    = sd->vcur.hue;
351
352         if (bright != sd->vold.brightness) {
353                 sd->vold.brightness = bright;
354                 if (bright < 0 || bright > sd->vmax.brightness)
355                         bright = 0;
356
357                 dat_bright[3] = bright;
358                 ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_bright);
359         }
360
361         if (hue != sd->vold.hue) {
362                 sd->vold.hue = hue;
363                 sd->swapRB = (hue != 0);
364         }
365
366         return 0;
367 }
368
369 static void ov9655_post_unset_alt(struct gspca_dev *gspca_dev)
370 {
371         ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
372         ctrl_out(gspca_dev, 0x40, 1, 0x0061, 0x0000, 0, NULL);
373 }