2 * Driver for the mt9m111 sensor
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>
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
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.
19 #include "m5602_mt9m111.h"
21 static struct v4l2_pix_format mt9m111_modes[] = {
27 .sizeimage = 640 * 480,
29 .colorspace = V4L2_COLORSPACE_SRGB,
34 const static struct ctrl mt9m111_ctrls[] = {
38 .type = V4L2_CTRL_TYPE_BOOLEAN,
39 .name = "vertical flip",
45 .set = mt9m111_set_vflip,
46 .get = mt9m111_get_vflip
50 .type = V4L2_CTRL_TYPE_BOOLEAN,
51 .name = "horizontal flip",
57 .set = mt9m111_set_hflip,
58 .get = mt9m111_get_hflip
62 .type = V4L2_CTRL_TYPE_INTEGER,
65 .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
67 .default_value = DEFAULT_GAIN,
68 .flags = V4L2_CTRL_FLAG_SLIDER
70 .set = mt9m111_set_gain,
71 .get = mt9m111_get_gain
76 static void mt9m111_dump_registers(struct sd *sd);
78 int mt9m111_probe(struct sd *sd)
80 u8 data[2] = {0x00, 0x00};
84 if (force_sensor == MT9M111_SENSOR) {
85 info("Forcing a %s sensor", mt9m111.name);
88 /* If we want to force another sensor, don't try to probe this
93 info("Probing for a mt9m111 sensor");
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]);
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);
109 if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
112 if ((data[0] == 0x14) && (data[1] == 0x3a)) {
113 info("Detected a mt9m111 sensor");
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);
127 int mt9m111_init(struct sd *sd)
131 /* Init the sensor */
132 for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
135 if (init_mt9m111[i][0] == BRIDGE) {
136 err = m5602_write_bridge(sd,
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);
148 mt9m111_dump_registers(sd);
150 return (err < 0) ? err : 0;
153 int mt9m111_power_down(struct sd *sd)
158 int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
161 u8 data[2] = {0x00, 0x00};
162 struct sd *sd = (struct sd *) gspca_dev;
164 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
166 *val = data[0] & MT9M111_RMB_MIRROR_ROWS;
167 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
172 int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
175 u8 data[2] = {0x00, 0x00};
176 struct sd *sd = (struct sd *) gspca_dev;
178 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
180 /* Set the correct page map */
181 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
185 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
189 data[0] = (data[0] & 0xfe) | val;
190 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
195 int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
198 u8 data[2] = {0x00, 0x00};
199 struct sd *sd = (struct sd *) gspca_dev;
201 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
203 *val = data[0] & MT9M111_RMB_MIRROR_COLS;
204 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
209 int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
212 u8 data[2] = {0x00, 0x00};
213 struct sd *sd = (struct sd *) gspca_dev;
215 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
217 /* Set the correct page map */
218 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
222 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
226 data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
227 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
232 int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
235 u8 data[2] = {0x00, 0x00};
236 struct sd *sd = (struct sd *) gspca_dev;
238 err = m5602_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
239 tmp = ((data[1] << 8) | data[0]);
241 *val = ((tmp & (1 << 10)) * 2) |
242 ((tmp & (1 << 9)) * 2) |
243 ((tmp & (1 << 8)) * 2) |
246 PDEBUG(D_V4L2, "Read gain %d", *val);
251 int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
254 u8 data[2] = {0x00, 0x00};
255 struct sd *sd = (struct sd *) gspca_dev;
257 /* Set the correct page map */
258 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
262 if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
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);
278 data[1] = (tmp & 0xff00) >> 8;
279 data[0] = (tmp & 0xff);
280 PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
283 err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
289 static void mt9m111_dump_registers(struct sd *sd)
291 u8 address, value[2] = {0x00, 0x00};
293 info("Dumping the mt9m111 register state");
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]);
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]);
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]);
322 info("mt9m111 register state dump complete");