dt-bindings: reset: imx7: Fix the spelling of 'indices'
[sfrench/cifs-2.6.git] / drivers / media / usb / gspca / m5602 / m5602_s5k4aa.c
1 /*
2  * Driver for the s5k4aa sensor
3  *
4  * Copyright (C) 2008 Erik AndrĂ©n
5  * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6  * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7  *
8  * Portions of code to USB interface and ALi driver software,
9  * Copyright (c) 2006 Willem Duinker
10  * v4l2 interface modeled after the V4L2 driver
11  * for SN9C10x PC Camera Controllers
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License as
15  * published by the Free Software Foundation, version 2.
16  *
17  */
18
19 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21 #include "m5602_s5k4aa.h"
22
23 static const unsigned char preinit_s5k4aa[][4] = {
24         {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
25         {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
26         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
27         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
28         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
29         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
30         {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
31
32         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
33         {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
34         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
35         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
36         {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
37         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
38         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
39         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
40         {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
41         {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
42         {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
43         {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
44         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
45         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
46         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
47         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
48
49         {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
50         {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
51         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
52         {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
53         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
54         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
55         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
56         {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
57         {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
58         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
59         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
60         {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
61         {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
62
63         {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00}
64 };
65
66 static const unsigned char init_s5k4aa[][4] = {
67         {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
68         {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
69         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
70         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
71         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
72         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
73         {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
74
75         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
76         {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
77         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
78         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
79         {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
80         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
81         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
82         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
83         {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
84         {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
85         {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
86         {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
87         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
88         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
89         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
90         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
91
92         {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
93         {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
94         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
95         {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
96         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
97         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
98         {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
99         {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
100         {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
101         {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
102         {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
103         {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
104         {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
105
106         {SENSOR, S5K4AA_PAGE_MAP, 0x07, 0x00},
107         {SENSOR, 0x36, 0x01, 0x00},
108         {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00},
109         {SENSOR, 0x7b, 0xff, 0x00},
110         {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
111         {SENSOR, 0x0c, 0x05, 0x00},
112         {SENSOR, 0x02, 0x0e, 0x00},
113         {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00},
114         {SENSOR, 0x37, 0x00, 0x00},
115 };
116
117 static const unsigned char VGA_s5k4aa[][4] = {
118         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
119         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
120         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
121         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
122         {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
123         {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
124         {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
125         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
126         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
127         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
128         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
129         /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */
130         {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
131         {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
132         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
133         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
134         {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
135         {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
136         {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
137         {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
138         /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */
139         {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
140         {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00},
141         {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
142         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
143         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
144
145         {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
146         {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X
147                 | S5K4AA_RM_COL_SKIP_2X, 0x00},
148         /* 0x37 : Fix image stability when light is too bright and improves
149          * image quality in 640x480, but worsens it in 1280x1024 */
150         {SENSOR, 0x37, 0x01, 0x00},
151         /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */
152         {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
153         {SENSOR, S5K4AA_ROWSTART_LO, 0x29, 0x00},
154         {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
155         {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00},
156         /* window_height_hi, window_height_lo : 960 = 0x03c0 */
157         {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
158         {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00},
159         /* window_width_hi, window_width_lo : 1280 = 0x0500 */
160         {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
161         {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
162         {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
163         {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */
164         {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
165         {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
166         {SENSOR, 0x11, 0x04, 0x00},
167         {SENSOR, 0x12, 0xc3, 0x00},
168         {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
169         {SENSOR, 0x02, 0x0e, 0x00},
170 };
171
172 static const unsigned char SXGA_s5k4aa[][4] = {
173         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
174         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
175         {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
176         {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
177         {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
178         {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
179         {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
180         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
181         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
182         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
183         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
184         /* VSYNC_PARA, VSYNC_PARA : img height 1024 = 0x0400 */
185         {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
186         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
187         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
188         {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
189         {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
190         {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
191         {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
192         {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
193         /* HSYNC_PARA, HSYNC_PARA : img width 1280 = 0x0500 */
194         {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
195         {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
196         {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
197         {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
198         {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
199
200         {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
201         {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP, 0x00},
202         {SENSOR, 0x37, 0x01, 0x00},
203         {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
204         {SENSOR, S5K4AA_ROWSTART_LO, 0x09, 0x00},
205         {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
206         {SENSOR, S5K4AA_COLSTART_LO, 0x0a, 0x00},
207         {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x04, 0x00},
208         {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0x00, 0x00},
209         {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
210         {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
211         {SENSOR, S5K4AA_H_BLANK_HI__, 0x01, 0x00},
212         {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00},
213         {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
214         {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
215         {SENSOR, 0x11, 0x04, 0x00},
216         {SENSOR, 0x12, 0xc3, 0x00},
217         {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
218         {SENSOR, 0x02, 0x0e, 0x00},
219 };
220
221
222 static int s5k4aa_s_ctrl(struct v4l2_ctrl *ctrl);
223 static void s5k4aa_dump_registers(struct sd *sd);
224
225 static const struct v4l2_ctrl_ops s5k4aa_ctrl_ops = {
226         .s_ctrl = s5k4aa_s_ctrl,
227 };
228
229 static
230     const
231         struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
232         {
233                 .ident = "BRUNEINIT",
234                 .matches = {
235                         DMI_MATCH(DMI_SYS_VENDOR, "BRUNENIT"),
236                         DMI_MATCH(DMI_PRODUCT_NAME, "BRUNENIT"),
237                         DMI_MATCH(DMI_BOARD_VERSION, "00030D0000000001")
238                 }
239         }, {
240                 .ident = "Fujitsu-Siemens Amilo Xa 2528",
241                 .matches = {
242                         DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
243                         DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
244                 }
245         }, {
246                 .ident = "Fujitsu-Siemens Amilo Xi 2428",
247                 .matches = {
248                         DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
249                         DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428")
250                 }
251         }, {
252                 .ident = "Fujitsu-Siemens Amilo Xi 2528",
253                 .matches = {
254                         DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
255                         DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2528")
256                 }
257         }, {
258                 .ident = "Fujitsu-Siemens Amilo Xi 2550",
259                 .matches = {
260                         DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
261                         DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
262                 }
263         }, {
264                 .ident = "Fujitsu-Siemens Amilo Pa 2548",
265                 .matches = {
266                         DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
267                         DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548")
268                 }
269         }, {
270                 .ident = "Fujitsu-Siemens Amilo Pi 2530",
271                 .matches = {
272                         DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
273                         DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 2530")
274                 }
275         }, {
276                 .ident = "MSI GX700",
277                 .matches = {
278                         DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
279                         DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
280                         DMI_MATCH(DMI_BIOS_DATE, "12/02/2008")
281                 }
282         }, {
283                 .ident = "MSI GX700",
284                 .matches = {
285                         DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
286                         DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
287                         DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
288                 }
289         }, {
290                 .ident = "MSI GX700",
291                 .matches = {
292                         DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
293                         DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
294                         DMI_MATCH(DMI_BIOS_DATE, "07/19/2007")
295                 }
296         }, {
297                 .ident = "MSI GX700/GX705/EX700",
298                 .matches = {
299                         DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
300                         DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
301                 }
302         }, {
303                 .ident = "MSI L735",
304                 .matches = {
305                         DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
306                         DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
307                 }
308         }, {
309                 .ident = "Lenovo Y300",
310                 .matches = {
311                         DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"),
312                         DMI_MATCH(DMI_PRODUCT_NAME, "Y300")
313                 }
314         },
315         { }
316 };
317
318 static struct v4l2_pix_format s5k4aa_modes[] = {
319         {
320                 640,
321                 480,
322                 V4L2_PIX_FMT_SBGGR8,
323                 V4L2_FIELD_NONE,
324                 .sizeimage =
325                         640 * 480,
326                 .bytesperline = 640,
327                 .colorspace = V4L2_COLORSPACE_SRGB,
328                 .priv = 0
329         },
330         {
331                 1280,
332                 1024,
333                 V4L2_PIX_FMT_SBGGR8,
334                 V4L2_FIELD_NONE,
335                 .sizeimage =
336                         1280 * 1024,
337                 .bytesperline = 1280,
338                 .colorspace = V4L2_COLORSPACE_SRGB,
339                 .priv = 0
340         }
341 };
342
343 int s5k4aa_probe(struct sd *sd)
344 {
345         u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
346         const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
347         struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
348         int i, err = 0;
349
350         if (force_sensor) {
351                 if (force_sensor == S5K4AA_SENSOR) {
352                         pr_info("Forcing a %s sensor\n", s5k4aa.name);
353                         goto sensor_found;
354                 }
355                 /* If we want to force another sensor, don't try to probe this
356                  * one */
357                 return -ENODEV;
358         }
359
360         gspca_dbg(gspca_dev, D_PROBE, "Probing for a s5k4aa sensor\n");
361
362         /* Preinit the sensor */
363         for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
364                 u8 data[2] = {0x00, 0x00};
365
366                 switch (preinit_s5k4aa[i][0]) {
367                 case BRIDGE:
368                         err = m5602_write_bridge(sd,
369                                                  preinit_s5k4aa[i][1],
370                                                  preinit_s5k4aa[i][2]);
371                         break;
372
373                 case SENSOR:
374                         data[0] = preinit_s5k4aa[i][2];
375                         err = m5602_write_sensor(sd,
376                                                   preinit_s5k4aa[i][1],
377                                                   data, 1);
378                         break;
379
380                 case SENSOR_LONG:
381                         data[0] = preinit_s5k4aa[i][2];
382                         data[1] = preinit_s5k4aa[i][3];
383                         err = m5602_write_sensor(sd,
384                                                   preinit_s5k4aa[i][1],
385                                                   data, 2);
386                         break;
387                 default:
388                         pr_info("Invalid stream command, exiting init\n");
389                         return -EINVAL;
390                 }
391         }
392
393         /* Test some registers, but we don't know their exact meaning yet */
394         if (m5602_read_sensor(sd, 0x00, prod_id, 2))
395                 return -ENODEV;
396         if (m5602_read_sensor(sd, 0x02, prod_id+2, 2))
397                 return -ENODEV;
398         if (m5602_read_sensor(sd, 0x04, prod_id+4, 2))
399                 return -ENODEV;
400
401         if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
402                 return -ENODEV;
403         else
404                 pr_info("Detected a s5k4aa sensor\n");
405
406 sensor_found:
407         sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
408         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
409
410         return 0;
411 }
412
413 int s5k4aa_start(struct sd *sd)
414 {
415         int i, err = 0;
416         u8 data[2];
417         struct cam *cam = &sd->gspca_dev.cam;
418         struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
419
420         switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
421         case 1280:
422                 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for SXGA mode\n");
423
424                 for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
425                         switch (SXGA_s5k4aa[i][0]) {
426                         case BRIDGE:
427                                 err = m5602_write_bridge(sd,
428                                                  SXGA_s5k4aa[i][1],
429                                                  SXGA_s5k4aa[i][2]);
430                         break;
431
432                         case SENSOR:
433                                 data[0] = SXGA_s5k4aa[i][2];
434                                 err = m5602_write_sensor(sd,
435                                                  SXGA_s5k4aa[i][1],
436                                                  data, 1);
437                         break;
438
439                         case SENSOR_LONG:
440                                 data[0] = SXGA_s5k4aa[i][2];
441                                 data[1] = SXGA_s5k4aa[i][3];
442                                 err = m5602_write_sensor(sd,
443                                                   SXGA_s5k4aa[i][1],
444                                                   data, 2);
445                         break;
446
447                         default:
448                                 pr_err("Invalid stream command, exiting init\n");
449                                 return -EINVAL;
450                         }
451                 }
452                 break;
453
454         case 640:
455                 gspca_dbg(gspca_dev, D_CONF, "Configuring camera for VGA mode\n");
456
457                 for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) {
458                         switch (VGA_s5k4aa[i][0]) {
459                         case BRIDGE:
460                                 err = m5602_write_bridge(sd,
461                                                  VGA_s5k4aa[i][1],
462                                                  VGA_s5k4aa[i][2]);
463                         break;
464
465                         case SENSOR:
466                                 data[0] = VGA_s5k4aa[i][2];
467                                 err = m5602_write_sensor(sd,
468                                                  VGA_s5k4aa[i][1],
469                                                  data, 1);
470                         break;
471
472                         case SENSOR_LONG:
473                                 data[0] = VGA_s5k4aa[i][2];
474                                 data[1] = VGA_s5k4aa[i][3];
475                                 err = m5602_write_sensor(sd,
476                                                   VGA_s5k4aa[i][1],
477                                                   data, 2);
478                         break;
479
480                         default:
481                                 pr_err("Invalid stream command, exiting init\n");
482                                 return -EINVAL;
483                         }
484                 }
485                 break;
486         }
487         if (err < 0)
488                 return err;
489
490         return 0;
491 }
492
493 int s5k4aa_init(struct sd *sd)
494 {
495         int i, err = 0;
496
497         for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
498                 u8 data[2] = {0x00, 0x00};
499
500                 switch (init_s5k4aa[i][0]) {
501                 case BRIDGE:
502                         err = m5602_write_bridge(sd,
503                                 init_s5k4aa[i][1],
504                                 init_s5k4aa[i][2]);
505                         break;
506
507                 case SENSOR:
508                         data[0] = init_s5k4aa[i][2];
509                         err = m5602_write_sensor(sd,
510                                 init_s5k4aa[i][1], data, 1);
511                         break;
512
513                 case SENSOR_LONG:
514                         data[0] = init_s5k4aa[i][2];
515                         data[1] = init_s5k4aa[i][3];
516                         err = m5602_write_sensor(sd,
517                                 init_s5k4aa[i][1], data, 2);
518                         break;
519                 default:
520                         pr_info("Invalid stream command, exiting init\n");
521                         return -EINVAL;
522                 }
523         }
524
525         if (dump_sensor)
526                 s5k4aa_dump_registers(sd);
527
528         return err;
529 }
530
531 int s5k4aa_init_controls(struct sd *sd)
532 {
533         struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
534
535         sd->gspca_dev.vdev.ctrl_handler = hdl;
536         v4l2_ctrl_handler_init(hdl, 6);
537
538         v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_BRIGHTNESS,
539                           0, 0x1f, 1, S5K4AA_DEFAULT_BRIGHTNESS);
540
541         v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_EXPOSURE,
542                           13, 0xfff, 1, 0x100);
543
544         v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_GAIN,
545                           0, 127, 1, S5K4AA_DEFAULT_GAIN);
546
547         v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_SHARPNESS,
548                           0, 1, 1, 1);
549
550         sd->hflip = v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_HFLIP,
551                                       0, 1, 1, 0);
552         sd->vflip = v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_VFLIP,
553                                       0, 1, 1, 0);
554
555         if (hdl->error) {
556                 pr_err("Could not initialize controls\n");
557                 return hdl->error;
558         }
559
560         v4l2_ctrl_cluster(2, &sd->hflip);
561
562         return 0;
563 }
564
565 static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
566 {
567         struct sd *sd = (struct sd *) gspca_dev;
568         u8 data = S5K4AA_PAGE_MAP_2;
569         int err;
570
571         gspca_dbg(gspca_dev, D_CONF, "Set exposure to %d\n", val);
572         err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
573         if (err < 0)
574                 return err;
575         data = (val >> 8) & 0xff;
576         err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
577         if (err < 0)
578                 return err;
579         data = val & 0xff;
580         err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
581
582         return err;
583 }
584
585 static int s5k4aa_set_hvflip(struct gspca_dev *gspca_dev)
586 {
587         struct sd *sd = (struct sd *) gspca_dev;
588         u8 data = S5K4AA_PAGE_MAP_2;
589         int err;
590         int hflip = sd->hflip->val;
591         int vflip = sd->vflip->val;
592
593         gspca_dbg(gspca_dev, D_CONF, "Set hvflip %d %d\n", hflip, vflip);
594         err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
595         if (err < 0)
596                 return err;
597
598         err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
599         if (err < 0)
600                 return err;
601
602         if (dmi_check_system(s5k4aa_vflip_dmi_table)) {
603                 hflip = !hflip;
604                 vflip = !vflip;
605         }
606
607         data = (data & 0x7f) | (vflip << 7) | (hflip << 6);
608         err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
609         if (err < 0)
610                 return err;
611
612         err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
613         if (err < 0)
614                 return err;
615         if (hflip)
616                 data &= 0xfe;
617         else
618                 data |= 0x01;
619         err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
620         if (err < 0)
621                 return err;
622
623         err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
624         if (err < 0)
625                 return err;
626         if (vflip)
627                 data &= 0xfe;
628         else
629                 data |= 0x01;
630         err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
631         if (err < 0)
632                 return err;
633
634         return 0;
635 }
636
637 static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
638 {
639         struct sd *sd = (struct sd *) gspca_dev;
640         u8 data = S5K4AA_PAGE_MAP_2;
641         int err;
642
643         gspca_dbg(gspca_dev, D_CONF, "Set gain to %d\n", val);
644         err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
645         if (err < 0)
646                 return err;
647
648         data = val & 0xff;
649         err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1);
650
651         return err;
652 }
653
654 static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
655 {
656         struct sd *sd = (struct sd *) gspca_dev;
657         u8 data = S5K4AA_PAGE_MAP_2;
658         int err;
659
660         gspca_dbg(gspca_dev, D_CONF, "Set brightness to %d\n", val);
661         err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
662         if (err < 0)
663                 return err;
664
665         data = val & 0xff;
666         return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
667 }
668
669 static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
670 {
671         struct sd *sd = (struct sd *) gspca_dev;
672         u8 data = S5K4AA_PAGE_MAP_2;
673         int err;
674
675         gspca_dbg(gspca_dev, D_CONF, "Set noise to %d\n", val);
676         err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
677         if (err < 0)
678                 return err;
679
680         data = val & 0x01;
681         return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
682 }
683
684 static int s5k4aa_s_ctrl(struct v4l2_ctrl *ctrl)
685 {
686         struct gspca_dev *gspca_dev =
687                 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
688         int err;
689
690         if (!gspca_dev->streaming)
691                 return 0;
692
693         switch (ctrl->id) {
694         case V4L2_CID_BRIGHTNESS:
695                 err = s5k4aa_set_brightness(gspca_dev, ctrl->val);
696                 break;
697         case V4L2_CID_EXPOSURE:
698                 err = s5k4aa_set_exposure(gspca_dev, ctrl->val);
699                 break;
700         case V4L2_CID_GAIN:
701                 err = s5k4aa_set_gain(gspca_dev, ctrl->val);
702                 break;
703         case V4L2_CID_SHARPNESS:
704                 err = s5k4aa_set_noise(gspca_dev, ctrl->val);
705                 break;
706         case V4L2_CID_HFLIP:
707                 err = s5k4aa_set_hvflip(gspca_dev);
708                 break;
709         default:
710                 return -EINVAL;
711         }
712
713         return err;
714 }
715
716 void s5k4aa_disconnect(struct sd *sd)
717 {
718         sd->sensor = NULL;
719 }
720
721 static void s5k4aa_dump_registers(struct sd *sd)
722 {
723         int address;
724         u8 page, old_page;
725         m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
726         for (page = 0; page < 16; page++) {
727                 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
728                 pr_info("Dumping the s5k4aa register state for page 0x%x\n",
729                         page);
730                 for (address = 0; address <= 0xff; address++) {
731                         u8 value = 0;
732                         m5602_read_sensor(sd, address, &value, 1);
733                         pr_info("register 0x%x contains 0x%x\n",
734                                 address, value);
735                 }
736         }
737         pr_info("s5k4aa register state dump complete\n");
738
739         for (page = 0; page < 16; page++) {
740                 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
741                 pr_info("Probing for which registers that are read/write for page 0x%x\n",
742                         page);
743                 for (address = 0; address <= 0xff; address++) {
744                         u8 old_value, ctrl_value, test_value = 0xff;
745
746                         m5602_read_sensor(sd, address, &old_value, 1);
747                         m5602_write_sensor(sd, address, &test_value, 1);
748                         m5602_read_sensor(sd, address, &ctrl_value, 1);
749
750                         if (ctrl_value == test_value)
751                                 pr_info("register 0x%x is writeable\n",
752                                         address);
753                         else
754                                 pr_info("register 0x%x is read only\n",
755                                         address);
756
757                         /* Restore original value */
758                         m5602_write_sensor(sd, address, &old_value, 1);
759                 }
760         }
761         pr_info("Read/write register probing complete\n");
762         m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
763 }