Revert "module: remove the SHF_ALLOC flag on the __versions section."
[cascardo/linux.git] / drivers / media / video / gspca / m5602 / m5602_mt9m111.c
1 /*
2  * Driver for the mt9m111 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 #include "m5602_mt9m111.h"
20
21 static void mt9m111_dump_registers(struct sd *sd);
22
23 int mt9m111_probe(struct sd *sd)
24 {
25         u8 data[2] = {0x00, 0x00};
26         int i;
27
28         if (force_sensor) {
29                 if (force_sensor == MT9M111_SENSOR) {
30                         info("Forcing a %s sensor", mt9m111.name);
31                         goto sensor_found;
32                 }
33                 /* If we want to force another sensor, don't try to probe this
34                  * one */
35                 return -ENODEV;
36         }
37
38         info("Probing for a mt9m111 sensor");
39
40         /* Do the preinit */
41         for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
42                 if (preinit_mt9m111[i][0] == BRIDGE) {
43                         m5602_write_bridge(sd,
44                                 preinit_mt9m111[i][1],
45                                 preinit_mt9m111[i][2]);
46                 } else {
47                         data[0] = preinit_mt9m111[i][2];
48                         data[1] = preinit_mt9m111[i][3];
49                         m5602_write_sensor(sd,
50                                 preinit_mt9m111[i][1], data, 2);
51                 }
52         }
53
54         if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
55                 return -ENODEV;
56
57         if ((data[0] == 0x14) && (data[1] == 0x3a)) {
58                 info("Detected a mt9m111 sensor");
59                 goto sensor_found;
60         }
61
62         return -ENODEV;
63
64 sensor_found:
65         sd->gspca_dev.cam.cam_mode = mt9m111.modes;
66         sd->gspca_dev.cam.nmodes = mt9m111.nmodes;
67         sd->desc->ctrls = mt9m111.ctrls;
68         sd->desc->nctrls = mt9m111.nctrls;
69         return 0;
70 }
71
72 int mt9m111_init(struct sd *sd)
73 {
74         int i, err = 0;
75
76         /* Init the sensor */
77         for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
78                 u8 data[2];
79
80                 if (init_mt9m111[i][0] == BRIDGE) {
81                         err = m5602_write_bridge(sd,
82                                 init_mt9m111[i][1],
83                                 init_mt9m111[i][2]);
84                 } else {
85                         data[0] = init_mt9m111[i][2];
86                         data[1] = init_mt9m111[i][3];
87                         err = m5602_write_sensor(sd,
88                                 init_mt9m111[i][1], data, 2);
89                 }
90         }
91
92         if (dump_sensor)
93                 mt9m111_dump_registers(sd);
94
95         return (err < 0) ? err : 0;
96 }
97
98 int mt9m111_power_down(struct sd *sd)
99 {
100         return 0;
101 }
102
103 int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
104 {
105         int err;
106         u8 data[2] = {0x00, 0x00};
107         struct sd *sd = (struct sd *) gspca_dev;
108
109         err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
110                                   data, 2);
111         *val = data[0] & MT9M111_RMB_MIRROR_ROWS;
112         PDEBUG(D_V4L2, "Read vertical flip %d", *val);
113
114         return err;
115 }
116
117 int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
118 {
119         int err;
120         u8 data[2] = {0x00, 0x00};
121         struct sd *sd = (struct sd *) gspca_dev;
122
123         PDEBUG(D_V4L2, "Set vertical flip to %d", val);
124
125         /* Set the correct page map */
126         err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
127         if (err < 0)
128                 goto out;
129
130         err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
131         if (err < 0)
132                 goto out;
133
134         data[0] = (data[0] & 0xfe) | val;
135         err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
136                                    data, 2);
137 out:
138         return err;
139 }
140
141 int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
142 {
143         int err;
144         u8 data[2] = {0x00, 0x00};
145         struct sd *sd = (struct sd *) gspca_dev;
146
147         err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
148                                   data, 2);
149         *val = data[0] & MT9M111_RMB_MIRROR_COLS;
150         PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
151
152         return err;
153 }
154
155 int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
156 {
157         int err;
158         u8 data[2] = {0x00, 0x00};
159         struct sd *sd = (struct sd *) gspca_dev;
160
161         PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
162
163         /* Set the correct page map */
164         err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
165         if (err < 0)
166                 goto out;
167
168         err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
169         if (err < 0)
170                 goto out;
171
172         data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
173         err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
174                                         data, 2);
175 out:
176         return err;
177 }
178
179 int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
180 {
181         int err, tmp;
182         u8 data[2] = {0x00, 0x00};
183         struct sd *sd = (struct sd *) gspca_dev;
184
185         err = m5602_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
186         tmp = ((data[1] << 8) | data[0]);
187
188         *val = ((tmp & (1 << 10)) * 2) |
189               ((tmp & (1 <<  9)) * 2) |
190               ((tmp & (1 <<  8)) * 2) |
191                (tmp & 0x7f);
192
193         PDEBUG(D_V4L2, "Read gain %d", *val);
194
195         return err;
196 }
197
198 int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
199 {
200         int err, tmp;
201         u8 data[2] = {0x00, 0x00};
202         struct sd *sd = (struct sd *) gspca_dev;
203
204         /* Set the correct page map */
205         err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
206         if (err < 0)
207                 goto out;
208
209         if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
210                 return -EINVAL;
211
212         if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
213             (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
214                 tmp = (1 << 10) | (val << 9) |
215                                 (val << 8) | (val / 8);
216         else if ((val >= INITIAL_MAX_GAIN * 2) &&
217                  (val <  INITIAL_MAX_GAIN * 2 * 2))
218                 tmp = (1 << 9) | (1 << 8) | (val / 4);
219         else if ((val >= INITIAL_MAX_GAIN) &&
220                  (val < INITIAL_MAX_GAIN * 2))
221                 tmp = (1 << 8) | (val / 2);
222         else
223                 tmp = val;
224
225         data[1] = (tmp & 0xff00) >> 8;
226         data[0] = (tmp & 0xff);
227         PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
228                data[1], data[0]);
229
230         err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
231                                    data, 2);
232 out:
233         return err;
234 }
235
236 static void mt9m111_dump_registers(struct sd *sd)
237 {
238         u8 address, value[2] = {0x00, 0x00};
239
240         info("Dumping the mt9m111 register state");
241
242         info("Dumping the mt9m111 sensor core registers");
243         value[1] = MT9M111_SENSOR_CORE;
244         m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
245         for (address = 0; address < 0xff; address++) {
246                 m5602_read_sensor(sd, address, value, 2);
247                 info("register 0x%x contains 0x%x%x",
248                      address, value[0], value[1]);
249         }
250
251         info("Dumping the mt9m111 color pipeline registers");
252         value[1] = MT9M111_COLORPIPE;
253         m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
254         for (address = 0; address < 0xff; address++) {
255                 m5602_read_sensor(sd, address, value, 2);
256                 info("register 0x%x contains 0x%x%x",
257                      address, value[0], value[1]);
258         }
259
260         info("Dumping the mt9m111 camera control registers");
261         value[1] = MT9M111_CAMERA_CONTROL;
262         m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
263         for (address = 0; address < 0xff; address++) {
264                 m5602_read_sensor(sd, address, value, 2);
265                 info("register 0x%x contains 0x%x%x",
266                      address, value[0], value[1]);
267         }
268
269         info("mt9m111 register state dump complete");
270 }