]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/media/video/gspca/m5602/m5602_mt9m111.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
[linux-2.6-omap-h63xx.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 int mt9m111_probe(struct sd *sd)
22 {
23         u8 data[2] = {0x00, 0x00};
24         int i;
25
26         if (force_sensor) {
27                 if (force_sensor == MT9M111_SENSOR) {
28                         info("Forcing a %s sensor", mt9m111.name);
29                         goto sensor_found;
30                 }
31                 /* If we want to force another sensor, don't try to probe this
32                  * one */
33                 return -ENODEV;
34         }
35
36         info("Probing for a mt9m111 sensor");
37
38         /* Do the preinit */
39         for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
40                 if (preinit_mt9m111[i][0] == BRIDGE) {
41                         m5602_write_bridge(sd,
42                                 preinit_mt9m111[i][1],
43                                 preinit_mt9m111[i][2]);
44                 } else {
45                         data[0] = preinit_mt9m111[i][2];
46                         data[1] = preinit_mt9m111[i][3];
47                         mt9m111_write_sensor(sd,
48                                 preinit_mt9m111[i][1], data, 2);
49                 }
50         }
51
52         if (mt9m111_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
53                 return -ENODEV;
54
55         if ((data[0] == 0x14) && (data[1] == 0x3a)) {
56                 info("Detected a mt9m111 sensor");
57                 goto sensor_found;
58         }
59
60         return -ENODEV;
61
62 sensor_found:
63         sd->gspca_dev.cam.cam_mode = mt9m111.modes;
64         sd->gspca_dev.cam.nmodes = mt9m111.nmodes;
65         sd->desc->ctrls = mt9m111.ctrls;
66         sd->desc->nctrls = mt9m111.nctrls;
67         return 0;
68 }
69
70 int mt9m111_init(struct sd *sd)
71 {
72         int i, err = 0;
73
74         /* Init the sensor */
75         for (i = 0; i < ARRAY_SIZE(init_mt9m111); i++) {
76                 u8 data[2];
77
78                 if (init_mt9m111[i][0] == BRIDGE) {
79                         err = m5602_write_bridge(sd,
80                                 init_mt9m111[i][1],
81                                 init_mt9m111[i][2]);
82                 } else {
83                         data[0] = init_mt9m111[i][2];
84                         data[1] = init_mt9m111[i][3];
85                         err = mt9m111_write_sensor(sd,
86                                 init_mt9m111[i][1], data, 2);
87                 }
88         }
89
90         if (dump_sensor)
91                 mt9m111_dump_registers(sd);
92
93         return (err < 0) ? err : 0;
94 }
95
96 int mt9m111_power_down(struct sd *sd)
97 {
98         return 0;
99 }
100
101 int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
102 {
103         int err;
104         u8 data[2] = {0x00, 0x00};
105         struct sd *sd = (struct sd *) gspca_dev;
106
107         err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
108                                   data, 2);
109         *val = data[0] & MT9M111_RMB_MIRROR_ROWS;
110         PDEBUG(D_V4L2, "Read vertical flip %d", *val);
111
112         return (err < 0) ? err : 0;
113 }
114
115 int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
116 {
117         int err;
118         u8 data[2] = {0x00, 0x00};
119         struct sd *sd = (struct sd *) gspca_dev;
120
121         PDEBUG(D_V4L2, "Set vertical flip to %d", val);
122
123         /* Set the correct page map */
124         err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
125         if (err < 0)
126                 goto out;
127
128         err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
129         if (err < 0)
130                 goto out;
131
132         data[0] = (data[0] & 0xfe) | val;
133         err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
134                                    data, 2);
135 out:
136         return (err < 0) ? err : 0;
137 }
138
139 int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
140 {
141         int err;
142         u8 data[2] = {0x00, 0x00};
143         struct sd *sd = (struct sd *) gspca_dev;
144
145         err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
146                                   data, 2);
147         *val = data[0] & MT9M111_RMB_MIRROR_COLS;
148         PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
149
150         return (err < 0) ? err : 0;
151 }
152
153 int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
154 {
155         int err;
156         u8 data[2] = {0x00, 0x00};
157         struct sd *sd = (struct sd *) gspca_dev;
158
159         PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
160
161         /* Set the correct page map */
162         err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
163         if (err < 0)
164                 goto out;
165
166         err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
167         if (err < 0)
168                 goto out;
169
170         data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
171         err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
172                                         data, 2);
173 out:
174         return (err < 0) ? err : 0;
175 }
176
177 int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
178 {
179         int err, tmp;
180         u8 data[2] = {0x00, 0x00};
181         struct sd *sd = (struct sd *) gspca_dev;
182
183         err = mt9m111_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
184         tmp = ((data[1] << 8) | data[0]);
185
186         *val = ((tmp & (1 << 10)) * 2) |
187               ((tmp & (1 <<  9)) * 2) |
188               ((tmp & (1 <<  8)) * 2) |
189                (tmp & 0x7f);
190
191         PDEBUG(D_V4L2, "Read gain %d", *val);
192
193         return (err < 0) ? err : 0;
194 }
195
196 int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
197 {
198         int err, tmp;
199         u8 data[2] = {0x00, 0x00};
200         struct sd *sd = (struct sd *) gspca_dev;
201
202         /* Set the correct page map */
203         err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
204         if (err < 0)
205                 goto out;
206
207         if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
208                 return -EINVAL;
209
210         if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
211             (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
212                 tmp = (1 << 10) | (val << 9) |
213                                 (val << 8) | (val / 8);
214         else if ((val >= INITIAL_MAX_GAIN * 2) &&
215                  (val <  INITIAL_MAX_GAIN * 2 * 2))
216                 tmp = (1 << 9) | (1 << 8) | (val / 4);
217         else if ((val >= INITIAL_MAX_GAIN) &&
218                  (val < INITIAL_MAX_GAIN * 2))
219                 tmp = (1 << 8) | (val / 2);
220         else
221                 tmp = val;
222
223         data[1] = (tmp & 0xff00) >> 8;
224         data[0] = (tmp & 0xff);
225         PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
226                data[1], data[0]);
227
228         err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
229                                    data, 2);
230 out:
231         return (err < 0) ? err : 0;
232 }
233
234 int mt9m111_read_sensor(struct sd *sd, const u8 address,
235                         u8 *i2c_data, const u8 len) {
236         int err, i;
237
238         do {
239                 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
240         } while ((*i2c_data & I2C_BUSY) && !err);
241         if (err < 0)
242                 goto out;
243
244         err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
245                                  sd->sensor->i2c_slave_id);
246         if (err < 0)
247                 goto out;
248
249         err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
250         if (err < 0)
251                 goto out;
252
253         err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x1a);
254         if (err < 0)
255                 goto out;
256
257         for (i = 0; i < len && !err; i++) {
258                 err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
259
260                 PDEBUG(D_CONF, "Reading sensor register "
261                        "0x%x contains 0x%x ", address, *i2c_data);
262         }
263 out:
264         return (err < 0) ? err : 0;
265 }
266
267 int mt9m111_write_sensor(struct sd *sd, const u8 address,
268                                 u8 *i2c_data, const u8 len)
269 {
270         int err, i;
271         u8 *p;
272         struct usb_device *udev = sd->gspca_dev.dev;
273         __u8 *buf = sd->gspca_dev.usb_buf;
274
275         /* No sensor with a data width larger
276            than 16 bits has yet been seen, nor with 0 :p*/
277         if (len > 2 || !len)
278                 return -EINVAL;
279
280         memcpy(buf, sensor_urb_skeleton,
281                sizeof(sensor_urb_skeleton));
282
283         buf[11] = sd->sensor->i2c_slave_id;
284         buf[15] = address;
285
286         p = buf + 16;
287
288         /* Copy a four byte write sequence for each byte to be written to */
289         for (i = 0; i < len; i++) {
290                 memcpy(p, sensor_urb_skeleton + 16, 4);
291                 p[3] = i2c_data[i];
292                 p += 4;
293                 PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
294                        address, i2c_data[i]);
295         }
296
297         /* Copy the tailer */
298         memcpy(p, sensor_urb_skeleton + 20, 4);
299
300         /* Set the total length */
301         p[3] = 0x10 + len;
302
303         err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
304                               0x04, 0x40, 0x19,
305                               0x0000, buf,
306                               20 + len * 4, M5602_URB_MSG_TIMEOUT);
307
308         return (err < 0) ? err : 0;
309 }
310
311 void mt9m111_dump_registers(struct sd *sd)
312 {
313         u8 address, value[2] = {0x00, 0x00};
314
315         info("Dumping the mt9m111 register state");
316
317         info("Dumping the mt9m111 sensor core registers");
318         value[1] = MT9M111_SENSOR_CORE;
319         mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
320         for (address = 0; address < 0xff; address++) {
321                 mt9m111_read_sensor(sd, address, value, 2);
322                 info("register 0x%x contains 0x%x%x",
323                      address, value[0], value[1]);
324         }
325
326         info("Dumping the mt9m111 color pipeline registers");
327         value[1] = MT9M111_COLORPIPE;
328         mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
329         for (address = 0; address < 0xff; address++) {
330                 mt9m111_read_sensor(sd, address, value, 2);
331                 info("register 0x%x contains 0x%x%x",
332                      address, value[0], value[1]);
333         }
334
335         info("Dumping the mt9m111 camera control registers");
336         value[1] = MT9M111_CAMERA_CONTROL;
337         mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
338         for (address = 0; address < 0xff; address++) {
339                 mt9m111_read_sensor(sd, address, value, 2);
340                 info("register 0x%x contains 0x%x%x",
341                      address, value[0], value[1]);
342         }
343
344         info("mt9m111 register state dump complete");
345 }