]> Pileus Git - ~andy/linux/blob - drivers/media/usb/gspca/m5602/m5602_mt9m111.c
[media] gscpa_m5602: Convert to the control framework
[~andy/linux] / drivers / media / usb / 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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21 #include "m5602_mt9m111.h"
22
23 static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl);
24 static void mt9m111_dump_registers(struct sd *sd);
25
26 static struct v4l2_pix_format mt9m111_modes[] = {
27         {
28                 640,
29                 480,
30                 V4L2_PIX_FMT_SBGGR8,
31                 V4L2_FIELD_NONE,
32                 .sizeimage = 640 * 480,
33                 .bytesperline = 640,
34                 .colorspace = V4L2_COLORSPACE_SRGB,
35                 .priv = 0
36         }
37 };
38
39 static const struct v4l2_ctrl_ops mt9m111_ctrl_ops = {
40         .s_ctrl = mt9m111_s_ctrl,
41 };
42
43 static const struct v4l2_ctrl_config mt9m111_greenbal_cfg = {
44         .ops    = &mt9m111_ctrl_ops,
45         .id     = M5602_V4L2_CID_GREEN_BALANCE,
46         .name   = "Green Balance",
47         .type   = V4L2_CTRL_TYPE_INTEGER,
48         .min    = 0,
49         .max    = 0x7ff,
50         .step   = 1,
51         .def    = MT9M111_GREEN_GAIN_DEFAULT,
52         .flags  = V4L2_CTRL_FLAG_SLIDER,
53 };
54
55 int mt9m111_probe(struct sd *sd)
56 {
57         u8 data[2] = {0x00, 0x00};
58         int i;
59
60         if (force_sensor) {
61                 if (force_sensor == MT9M111_SENSOR) {
62                         pr_info("Forcing a %s sensor\n", mt9m111.name);
63                         goto sensor_found;
64                 }
65                 /* If we want to force another sensor, don't try to probe this
66                  * one */
67                 return -ENODEV;
68         }
69
70         PDEBUG(D_PROBE, "Probing for a mt9m111 sensor");
71
72         /* Do the preinit */
73         for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
74                 if (preinit_mt9m111[i][0] == BRIDGE) {
75                         m5602_write_bridge(sd,
76                                 preinit_mt9m111[i][1],
77                                 preinit_mt9m111[i][2]);
78                 } else {
79                         data[0] = preinit_mt9m111[i][2];
80                         data[1] = preinit_mt9m111[i][3];
81                         m5602_write_sensor(sd,
82                                 preinit_mt9m111[i][1], data, 2);
83                 }
84         }
85
86         if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
87                 return -ENODEV;
88
89         if ((data[0] == 0x14) && (data[1] == 0x3a)) {
90                 pr_info("Detected a mt9m111 sensor\n");
91                 goto sensor_found;
92         }
93
94         return -ENODEV;
95
96 sensor_found:
97         sd->gspca_dev.cam.cam_mode = mt9m111_modes;
98         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
99
100         return 0;
101 }
102
103 int mt9m111_init(struct sd *sd)
104 {
105         int i, err = 0;
106
107         /* Init the sensor */
108         for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
109                 u8 data[2];
110
111                 if (init_mt9m111[i][0] == BRIDGE) {
112                         err = m5602_write_bridge(sd,
113                                 init_mt9m111[i][1],
114                                 init_mt9m111[i][2]);
115                 } else {
116                         data[0] = init_mt9m111[i][2];
117                         data[1] = init_mt9m111[i][3];
118                         err = m5602_write_sensor(sd,
119                                 init_mt9m111[i][1], data, 2);
120                 }
121         }
122
123         if (dump_sensor)
124                 mt9m111_dump_registers(sd);
125
126         return 0;
127 }
128
129 int mt9m111_init_controls(struct sd *sd)
130 {
131         struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
132
133         sd->gspca_dev.vdev.ctrl_handler = hdl;
134         v4l2_ctrl_handler_init(hdl, 7);
135
136         sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
137                                                V4L2_CID_AUTO_WHITE_BALANCE,
138                                                0, 1, 1, 0);
139         sd->green_bal = v4l2_ctrl_new_custom(hdl, &mt9m111_greenbal_cfg, NULL);
140         sd->red_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
141                                         V4L2_CID_RED_BALANCE, 0, 0x7ff, 1,
142                                         MT9M111_RED_GAIN_DEFAULT);
143         sd->blue_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
144                                         V4L2_CID_BLUE_BALANCE, 0, 0x7ff, 1,
145                                         MT9M111_BLUE_GAIN_DEFAULT);
146
147         v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_GAIN, 0,
148                           (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, 1,
149                           MT9M111_DEFAULT_GAIN);
150
151         sd->hflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_HFLIP,
152                                       0, 1, 1, 0);
153         sd->vflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_VFLIP,
154                                       0, 1, 1, 0);
155
156         if (hdl->error) {
157                 pr_err("Could not initialize controls\n");
158                 return hdl->error;
159         }
160
161         v4l2_ctrl_auto_cluster(4, &sd->auto_white_bal, 0, false);
162         v4l2_ctrl_cluster(2, &sd->hflip);
163
164         return 0;
165 }
166
167 int mt9m111_start(struct sd *sd)
168 {
169         int i, err = 0;
170         u8 data[2];
171         struct cam *cam = &sd->gspca_dev.cam;
172
173         int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
174         int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
175
176         for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) {
177                 if (start_mt9m111[i][0] == BRIDGE) {
178                         err = m5602_write_bridge(sd,
179                                 start_mt9m111[i][1],
180                                 start_mt9m111[i][2]);
181                 } else {
182                         data[0] = start_mt9m111[i][2];
183                         data[1] = start_mt9m111[i][3];
184                         err = m5602_write_sensor(sd,
185                                 start_mt9m111[i][1], data, 2);
186                 }
187         }
188         if (err < 0)
189                 return err;
190
191         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
192         if (err < 0)
193                 return err;
194
195         err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
196         if (err < 0)
197                 return err;
198
199         for (i = 0; i < 2 && !err; i++)
200                 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
201         if (err < 0)
202                 return err;
203
204         err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
205         if (err < 0)
206                 return err;
207
208         err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
209         if (err < 0)
210                 return err;
211
212         for (i = 0; i < 2 && !err; i++)
213                 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
214         if (err < 0)
215                 return err;
216
217         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
218                                  (width >> 8) & 0xff);
219         if (err < 0)
220                 return err;
221
222         err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff);
223         if (err < 0)
224                 return err;
225
226         err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
227         if (err < 0)
228                 return err;
229
230         switch (width) {
231         case 640:
232                 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
233                 break;
234
235         case 320:
236                 PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
237                 break;
238         }
239         return err;
240 }
241
242 void mt9m111_disconnect(struct sd *sd)
243 {
244         sd->sensor = NULL;
245 }
246
247 static int mt9m111_set_hvflip(struct gspca_dev *gspca_dev)
248 {
249         int err;
250         u8 data[2] = {0x00, 0x00};
251         struct sd *sd = (struct sd *) gspca_dev;
252         int hflip;
253         int vflip;
254
255         PDEBUG(D_V4L2, "Set hvflip to %d %d", sd->hflip->val, sd->vflip->val);
256
257         /* The mt9m111 is flipped by default */
258         hflip = !sd->hflip->val;
259         vflip = !sd->vflip->val;
260
261         /* Set the correct page map */
262         err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
263         if (err < 0)
264                 return err;
265
266         data[0] = MT9M111_RMB_OVER_SIZED;
267         if (gspca_dev->width == 640) {
268                 data[1] = MT9M111_RMB_ROW_SKIP_2X |
269                           MT9M111_RMB_COLUMN_SKIP_2X |
270                           (hflip << 1) | vflip;
271         } else {
272                 data[1] = MT9M111_RMB_ROW_SKIP_4X |
273                           MT9M111_RMB_COLUMN_SKIP_4X |
274                           (hflip << 1) | vflip;
275         }
276         err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
277                                         data, 2);
278         return err;
279 }
280
281 static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
282                                           __s32 val)
283 {
284         struct sd *sd = (struct sd *) gspca_dev;
285         int err;
286         u8 data[2];
287
288         err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
289         if (err < 0)
290                 return err;
291
292         data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
293
294         err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
295
296         PDEBUG(D_V4L2, "Set auto white balance %d", val);
297         return err;
298 }
299
300 static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
301 {
302         int err, tmp;
303         u8 data[2] = {0x00, 0x00};
304         struct sd *sd = (struct sd *) gspca_dev;
305
306         /* Set the correct page map */
307         err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
308         if (err < 0)
309                 return err;
310
311         if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
312                 return -EINVAL;
313
314         if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
315             (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
316                 tmp = (1 << 10) | (val << 9) |
317                                 (val << 8) | (val / 8);
318         else if ((val >= INITIAL_MAX_GAIN * 2) &&
319                  (val <  INITIAL_MAX_GAIN * 2 * 2))
320                 tmp = (1 << 9) | (1 << 8) | (val / 4);
321         else if ((val >= INITIAL_MAX_GAIN) &&
322                  (val < INITIAL_MAX_GAIN * 2))
323                 tmp = (1 << 8) | (val / 2);
324         else
325                 tmp = val;
326
327         data[1] = (tmp & 0xff);
328         data[0] = (tmp & 0xff00) >> 8;
329         PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
330                data[1], data[0]);
331
332         err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
333                                    data, 2);
334
335         return err;
336 }
337
338 static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
339 {
340         int err;
341         u8 data[2];
342         struct sd *sd = (struct sd *) gspca_dev;
343
344         data[1] = (val & 0xff);
345         data[0] = (val & 0xff00) >> 8;
346
347         PDEBUG(D_V4L2, "Set green balance %d", val);
348         err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
349                                  data, 2);
350         if (err < 0)
351                 return err;
352
353         return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN,
354                                   data, 2);
355 }
356
357 static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
358 {
359         u8 data[2];
360         struct sd *sd = (struct sd *) gspca_dev;
361
362         data[1] = (val & 0xff);
363         data[0] = (val & 0xff00) >> 8;
364
365         PDEBUG(D_V4L2, "Set blue balance %d", val);
366
367         return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
368                                   data, 2);
369 }
370
371 static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
372 {
373         u8 data[2];
374         struct sd *sd = (struct sd *) gspca_dev;
375
376         data[1] = (val & 0xff);
377         data[0] = (val & 0xff00) >> 8;
378
379         PDEBUG(D_V4L2, "Set red balance %d", val);
380
381         return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
382                                   data, 2);
383 }
384
385 static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)
386 {
387         struct gspca_dev *gspca_dev =
388                 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
389         struct sd *sd = (struct sd *) gspca_dev;
390         int err;
391
392         if (!gspca_dev->streaming)
393                 return 0;
394
395         switch (ctrl->id) {
396         case V4L2_CID_AUTO_WHITE_BALANCE:
397                 err = mt9m111_set_auto_white_balance(gspca_dev, ctrl->val);
398                 if (err || ctrl->val)
399                         return err;
400                 err = mt9m111_set_green_balance(gspca_dev, sd->green_bal->val);
401                 if (err)
402                         return err;
403                 err = mt9m111_set_red_balance(gspca_dev, sd->red_bal->val);
404                 if (err)
405                         return err;
406                 err = mt9m111_set_blue_balance(gspca_dev, sd->blue_bal->val);
407                 break;
408         case V4L2_CID_GAIN:
409                 err = mt9m111_set_gain(gspca_dev, ctrl->val);
410                 break;
411         case V4L2_CID_HFLIP:
412                 err = mt9m111_set_hvflip(gspca_dev);
413                 break;
414         default:
415                 return -EINVAL;
416         }
417
418         return err;
419 }
420
421 static void mt9m111_dump_registers(struct sd *sd)
422 {
423         u8 address, value[2] = {0x00, 0x00};
424
425         pr_info("Dumping the mt9m111 register state\n");
426
427         pr_info("Dumping the mt9m111 sensor core registers\n");
428         value[1] = MT9M111_SENSOR_CORE;
429         m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
430         for (address = 0; address < 0xff; address++) {
431                 m5602_read_sensor(sd, address, value, 2);
432                 pr_info("register 0x%x contains 0x%x%x\n",
433                         address, value[0], value[1]);
434         }
435
436         pr_info("Dumping the mt9m111 color pipeline registers\n");
437         value[1] = MT9M111_COLORPIPE;
438         m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
439         for (address = 0; address < 0xff; address++) {
440                 m5602_read_sensor(sd, address, value, 2);
441                 pr_info("register 0x%x contains 0x%x%x\n",
442                         address, value[0], value[1]);
443         }
444
445         pr_info("Dumping the mt9m111 camera control registers\n");
446         value[1] = MT9M111_CAMERA_CONTROL;
447         m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
448         for (address = 0; address < 0xff; address++) {
449                 m5602_read_sensor(sd, address, value, 2);
450                 pr_info("register 0x%x contains 0x%x%x\n",
451                         address, value[0], value[1]);
452         }
453
454         pr_info("mt9m111 register state dump complete\n");
455 }