V4L/DVB (11466): gspca - m5602: Let all ctrls on all sensors be static
[linux-2.6-xlnx.git] / drivers / media / video / gspca / m5602 / m5602_mt9m111.c
blob8017782efee92b5706ac762aa86a9a64c814c659
1 /*
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 int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
22 static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
23 static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
24 static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
25 static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
26 static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
28 static struct v4l2_pix_format mt9m111_modes[] = {
30 640,
31 480,
32 V4L2_PIX_FMT_SBGGR8,
33 V4L2_FIELD_NONE,
34 .sizeimage = 640 * 480,
35 .bytesperline = 640,
36 .colorspace = V4L2_COLORSPACE_SRGB,
37 .priv = 0
41 const static struct ctrl mt9m111_ctrls[] = {
42 #define VFLIP_IDX 0
45 .id = V4L2_CID_VFLIP,
46 .type = V4L2_CTRL_TYPE_BOOLEAN,
47 .name = "vertical flip",
48 .minimum = 0,
49 .maximum = 1,
50 .step = 1,
51 .default_value = 0
53 .set = mt9m111_set_vflip,
54 .get = mt9m111_get_vflip
56 #define HFLIP_IDX 1
59 .id = V4L2_CID_HFLIP,
60 .type = V4L2_CTRL_TYPE_BOOLEAN,
61 .name = "horizontal flip",
62 .minimum = 0,
63 .maximum = 1,
64 .step = 1,
65 .default_value = 0
67 .set = mt9m111_set_hflip,
68 .get = mt9m111_get_hflip
70 #define GAIN_IDX 2
73 .id = V4L2_CID_GAIN,
74 .type = V4L2_CTRL_TYPE_INTEGER,
75 .name = "gain",
76 .minimum = 0,
77 .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
78 .step = 1,
79 .default_value = DEFAULT_GAIN,
80 .flags = V4L2_CTRL_FLAG_SLIDER
82 .set = mt9m111_set_gain,
83 .get = mt9m111_get_gain
88 static void mt9m111_dump_registers(struct sd *sd);
90 int mt9m111_probe(struct sd *sd)
92 u8 data[2] = {0x00, 0x00};
93 int i;
94 s32 *sensor_settings;
96 if (force_sensor) {
97 if (force_sensor == MT9M111_SENSOR) {
98 info("Forcing a %s sensor", mt9m111.name);
99 goto sensor_found;
101 /* If we want to force another sensor, don't try to probe this
102 * one */
103 return -ENODEV;
106 info("Probing for a mt9m111 sensor");
108 /* Do the preinit */
109 for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
110 if (preinit_mt9m111[i][0] == BRIDGE) {
111 m5602_write_bridge(sd,
112 preinit_mt9m111[i][1],
113 preinit_mt9m111[i][2]);
114 } else {
115 data[0] = preinit_mt9m111[i][2];
116 data[1] = preinit_mt9m111[i][3];
117 m5602_write_sensor(sd,
118 preinit_mt9m111[i][1], data, 2);
122 if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
123 return -ENODEV;
125 if ((data[0] == 0x14) && (data[1] == 0x3a)) {
126 info("Detected a mt9m111 sensor");
127 goto sensor_found;
130 return -ENODEV;
132 sensor_found:
133 sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32),
134 GFP_KERNEL);
135 if (!sensor_settings)
136 return -ENOMEM;
138 sd->gspca_dev.cam.cam_mode = mt9m111_modes;
139 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
140 sd->desc->ctrls = mt9m111_ctrls;
141 sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
143 for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++)
144 sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value;
145 sd->sensor_priv = sensor_settings;
147 if (dump_sensor)
148 mt9m111_dump_registers(sd);
150 return 0;
153 int mt9m111_init(struct sd *sd)
155 int i, err = 0;
156 s32 *sensor_settings = sd->sensor_priv;
158 /* Init the sensor */
159 for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
160 u8 data[2];
162 if (init_mt9m111[i][0] == BRIDGE) {
163 err = m5602_write_bridge(sd,
164 init_mt9m111[i][1],
165 init_mt9m111[i][2]);
166 } else {
167 data[0] = init_mt9m111[i][2];
168 data[1] = init_mt9m111[i][3];
169 err = m5602_write_sensor(sd,
170 init_mt9m111[i][1], data, 2);
174 err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
175 if (err < 0)
176 return err;
178 err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
179 if (err < 0)
180 return err;
182 err = mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
184 return err;
187 void mt9m111_disconnect(struct sd *sd)
189 sd->sensor = NULL;
190 kfree(sd->sensor_priv);
193 static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
195 struct sd *sd = (struct sd *) gspca_dev;
196 s32 *sensor_settings = sd->sensor_priv;
198 *val = sensor_settings[VFLIP_IDX];
199 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
201 return 0;
204 static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
206 int err;
207 u8 data[2] = {0x00, 0x00};
208 struct sd *sd = (struct sd *) gspca_dev;
209 s32 *sensor_settings = sd->sensor_priv;
211 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
213 sensor_settings[VFLIP_IDX] = val;
215 /* Set the correct page map */
216 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
217 if (err < 0)
218 return err;
220 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
221 if (err < 0)
222 return err;
224 data[0] = (data[0] & 0xfe) | val;
225 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
226 data, 2);
227 return err;
230 static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
232 struct sd *sd = (struct sd *) gspca_dev;
233 s32 *sensor_settings = sd->sensor_priv;
235 *val = sensor_settings[HFLIP_IDX];
236 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
238 return 0;
241 static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
243 int err;
244 u8 data[2] = {0x00, 0x00};
245 struct sd *sd = (struct sd *) gspca_dev;
246 s32 *sensor_settings = sd->sensor_priv;
248 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
250 sensor_settings[HFLIP_IDX] = val;
251 /* Set the correct page map */
252 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
253 if (err < 0)
254 return err;
256 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
257 if (err < 0)
258 return err;
260 data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
261 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
262 data, 2);
263 return err;
266 static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
268 struct sd *sd = (struct sd *) gspca_dev;
269 s32 *sensor_settings = sd->sensor_priv;
271 *val = sensor_settings[GAIN_IDX];
272 PDEBUG(D_V4L2, "Read gain %d", *val);
274 return 0;
277 static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
279 int err, tmp;
280 u8 data[2] = {0x00, 0x00};
281 struct sd *sd = (struct sd *) gspca_dev;
282 s32 *sensor_settings = sd->sensor_priv;
284 sensor_settings[GAIN_IDX] = val;
286 /* Set the correct page map */
287 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
288 if (err < 0)
289 return err;
291 if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
292 return -EINVAL;
294 if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
295 (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
296 tmp = (1 << 10) | (val << 9) |
297 (val << 8) | (val / 8);
298 else if ((val >= INITIAL_MAX_GAIN * 2) &&
299 (val < INITIAL_MAX_GAIN * 2 * 2))
300 tmp = (1 << 9) | (1 << 8) | (val / 4);
301 else if ((val >= INITIAL_MAX_GAIN) &&
302 (val < INITIAL_MAX_GAIN * 2))
303 tmp = (1 << 8) | (val / 2);
304 else
305 tmp = val;
307 data[1] = (tmp & 0xff00) >> 8;
308 data[0] = (tmp & 0xff);
309 PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
310 data[1], data[0]);
312 err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
313 data, 2);
315 return err;
318 static void mt9m111_dump_registers(struct sd *sd)
320 u8 address, value[2] = {0x00, 0x00};
322 info("Dumping the mt9m111 register state");
324 info("Dumping the mt9m111 sensor core registers");
325 value[1] = MT9M111_SENSOR_CORE;
326 m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
327 for (address = 0; address < 0xff; address++) {
328 m5602_read_sensor(sd, address, value, 2);
329 info("register 0x%x contains 0x%x%x",
330 address, value[0], value[1]);
333 info("Dumping the mt9m111 color pipeline registers");
334 value[1] = MT9M111_COLORPIPE;
335 m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
336 for (address = 0; address < 0xff; address++) {
337 m5602_read_sensor(sd, address, value, 2);
338 info("register 0x%x contains 0x%x%x",
339 address, value[0], value[1]);
342 info("Dumping the mt9m111 camera control registers");
343 value[1] = MT9M111_CAMERA_CONTROL;
344 m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
345 for (address = 0; address < 0xff; address++) {
346 m5602_read_sensor(sd, address, value, 2);
347 info("register 0x%x contains 0x%x%x",
348 address, value[0], value[1]);
351 info("mt9m111 register state dump complete");