Merge commit 'v2.6.30-rc1' into x86/urgent
[pandora-kernel.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 struct v4l2_pix_format mt9m111_modes[] = {
22         {
23                 640,
24                 480,
25                 V4L2_PIX_FMT_SBGGR8,
26                 V4L2_FIELD_NONE,
27                 .sizeimage = 640 * 480,
28                 .bytesperline = 640,
29                 .colorspace = V4L2_COLORSPACE_SRGB,
30                 .priv = 0
31         }
32 };
33
34 const static struct ctrl mt9m111_ctrls[] = {
35         {
36                 {
37                         .id             = V4L2_CID_VFLIP,
38                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
39                         .name           = "vertical flip",
40                         .minimum        = 0,
41                         .maximum        = 1,
42                         .step           = 1,
43                         .default_value  = 0
44                 },
45                 .set = mt9m111_set_vflip,
46                 .get = mt9m111_get_vflip
47         }, {
48                 {
49                         .id             = V4L2_CID_HFLIP,
50                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
51                         .name           = "horizontal flip",
52                         .minimum        = 0,
53                         .maximum        = 1,
54                         .step           = 1,
55                         .default_value  = 0
56                 },
57                 .set = mt9m111_set_hflip,
58                 .get = mt9m111_get_hflip
59         }, {
60                 {
61                         .id             = V4L2_CID_GAIN,
62                         .type           = V4L2_CTRL_TYPE_INTEGER,
63                         .name           = "gain",
64                         .minimum        = 0,
65                         .maximum        = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
66                         .step           = 1,
67                         .default_value  = DEFAULT_GAIN,
68                         .flags          = V4L2_CTRL_FLAG_SLIDER
69                 },
70                 .set = mt9m111_set_gain,
71                 .get = mt9m111_get_gain
72         }
73 };
74
75
76 static void mt9m111_dump_registers(struct sd *sd);
77
78 int mt9m111_probe(struct sd *sd)
79 {
80         u8 data[2] = {0x00, 0x00};
81         int i;
82
83         if (force_sensor) {
84                 if (force_sensor == MT9M111_SENSOR) {
85                         info("Forcing a %s sensor", mt9m111.name);
86                         goto sensor_found;
87                 }
88                 /* If we want to force another sensor, don't try to probe this
89                  * one */
90                 return -ENODEV;
91         }
92
93         info("Probing for a mt9m111 sensor");
94
95         /* Do the preinit */
96         for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
97                 if (preinit_mt9m111[i][0] == BRIDGE) {
98                         m5602_write_bridge(sd,
99                                 preinit_mt9m111[i][1],
100                                 preinit_mt9m111[i][2]);
101                 } else {
102                         data[0] = preinit_mt9m111[i][2];
103                         data[1] = preinit_mt9m111[i][3];
104                         m5602_write_sensor(sd,
105                                 preinit_mt9m111[i][1], data, 2);
106                 }
107         }
108
109         if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
110                 return -ENODEV;
111
112         if ((data[0] == 0x14) && (data[1] == 0x3a)) {
113                 info("Detected a mt9m111 sensor");
114                 goto sensor_found;
115         }
116
117         return -ENODEV;
118
119 sensor_found:
120         sd->gspca_dev.cam.cam_mode = mt9m111_modes;
121         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
122         sd->desc->ctrls = mt9m111_ctrls;
123         sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
124         return 0;
125 }
126
127 int mt9m111_init(struct sd *sd)
128 {
129         int i, err = 0;
130
131         /* Init the sensor */
132         for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
133                 u8 data[2];
134
135                 if (init_mt9m111[i][0] == BRIDGE) {
136                         err = m5602_write_bridge(sd,
137                                 init_mt9m111[i][1],
138                                 init_mt9m111[i][2]);
139                 } else {
140                         data[0] = init_mt9m111[i][2];
141                         data[1] = init_mt9m111[i][3];
142                         err = m5602_write_sensor(sd,
143                                 init_mt9m111[i][1], data, 2);
144                 }
145         }
146
147         if (dump_sensor)
148                 mt9m111_dump_registers(sd);
149
150         return (err < 0) ? err : 0;
151 }
152
153 int mt9m111_power_down(struct sd *sd)
154 {
155         return 0;
156 }
157
158 int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
159 {
160         int err;
161         u8 data[2] = {0x00, 0x00};
162         struct sd *sd = (struct sd *) gspca_dev;
163
164         err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
165                                   data, 2);
166         *val = data[0] & MT9M111_RMB_MIRROR_ROWS;
167         PDEBUG(D_V4L2, "Read vertical flip %d", *val);
168
169         return err;
170 }
171
172 int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
173 {
174         int err;
175         u8 data[2] = {0x00, 0x00};
176         struct sd *sd = (struct sd *) gspca_dev;
177
178         PDEBUG(D_V4L2, "Set vertical flip to %d", val);
179
180         /* Set the correct page map */
181         err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
182         if (err < 0)
183                 return err;
184
185         err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
186         if (err < 0)
187                 return err;
188
189         data[0] = (data[0] & 0xfe) | val;
190         err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
191                                    data, 2);
192         return err;
193 }
194
195 int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
196 {
197         int err;
198         u8 data[2] = {0x00, 0x00};
199         struct sd *sd = (struct sd *) gspca_dev;
200
201         err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
202                                   data, 2);
203         *val = data[0] & MT9M111_RMB_MIRROR_COLS;
204         PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
205
206         return err;
207 }
208
209 int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
210 {
211         int err;
212         u8 data[2] = {0x00, 0x00};
213         struct sd *sd = (struct sd *) gspca_dev;
214
215         PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
216
217         /* Set the correct page map */
218         err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
219         if (err < 0)
220                 return err;
221
222         err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
223         if (err < 0)
224                 return err;
225
226         data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
227         err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
228                                         data, 2);
229         return err;
230 }
231
232 int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
233 {
234         int err, tmp;
235         u8 data[2] = {0x00, 0x00};
236         struct sd *sd = (struct sd *) gspca_dev;
237
238         err = m5602_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
239         tmp = ((data[1] << 8) | data[0]);
240
241         *val = ((tmp & (1 << 10)) * 2) |
242               ((tmp & (1 <<  9)) * 2) |
243               ((tmp & (1 <<  8)) * 2) |
244                (tmp & 0x7f);
245
246         PDEBUG(D_V4L2, "Read gain %d", *val);
247
248         return err;
249 }
250
251 int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
252 {
253         int err, tmp;
254         u8 data[2] = {0x00, 0x00};
255         struct sd *sd = (struct sd *) gspca_dev;
256
257         /* Set the correct page map */
258         err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
259         if (err < 0)
260                 return err;
261
262         if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
263                 return -EINVAL;
264
265         if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
266             (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
267                 tmp = (1 << 10) | (val << 9) |
268                                 (val << 8) | (val / 8);
269         else if ((val >= INITIAL_MAX_GAIN * 2) &&
270                  (val <  INITIAL_MAX_GAIN * 2 * 2))
271                 tmp = (1 << 9) | (1 << 8) | (val / 4);
272         else if ((val >= INITIAL_MAX_GAIN) &&
273                  (val < INITIAL_MAX_GAIN * 2))
274                 tmp = (1 << 8) | (val / 2);
275         else
276                 tmp = val;
277
278         data[1] = (tmp & 0xff00) >> 8;
279         data[0] = (tmp & 0xff);
280         PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
281                data[1], data[0]);
282
283         err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
284                                    data, 2);
285
286         return err;
287 }
288
289 static void mt9m111_dump_registers(struct sd *sd)
290 {
291         u8 address, value[2] = {0x00, 0x00};
292
293         info("Dumping the mt9m111 register state");
294
295         info("Dumping the mt9m111 sensor core registers");
296         value[1] = MT9M111_SENSOR_CORE;
297         m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
298         for (address = 0; address < 0xff; address++) {
299                 m5602_read_sensor(sd, address, value, 2);
300                 info("register 0x%x contains 0x%x%x",
301                      address, value[0], value[1]);
302         }
303
304         info("Dumping the mt9m111 color pipeline registers");
305         value[1] = MT9M111_COLORPIPE;
306         m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
307         for (address = 0; address < 0xff; address++) {
308                 m5602_read_sensor(sd, address, value, 2);
309                 info("register 0x%x contains 0x%x%x",
310                      address, value[0], value[1]);
311         }
312
313         info("Dumping the mt9m111 camera control registers");
314         value[1] = MT9M111_CAMERA_CONTROL;
315         m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
316         for (address = 0; address < 0xff; address++) {
317                 m5602_read_sensor(sd, address, value, 2);
318                 info("register 0x%x contains 0x%x%x",
319                      address, value[0], value[1]);
320         }
321
322         info("mt9m111 register state dump complete");
323 }