Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-module-and-param
[linux-2.6] / drivers / media / video / gspca / m5602 / m5602_po1030.c
1 /*
2  * Driver for the po1030 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_po1030.h"
20
21 static struct v4l2_pix_format po1030_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 po1030_ctrls[] = {
35         {
36                 {
37                         .id             = V4L2_CID_GAIN,
38                         .type           = V4L2_CTRL_TYPE_INTEGER,
39                         .name           = "gain",
40                         .minimum        = 0x00,
41                         .maximum        = 0x4f,
42                         .step           = 0x1,
43                         .default_value  = PO1030_GLOBAL_GAIN_DEFAULT,
44                         .flags          = V4L2_CTRL_FLAG_SLIDER
45                 },
46                 .set = po1030_set_gain,
47                 .get = po1030_get_gain
48         }, {
49                 {
50                         .id             = V4L2_CID_EXPOSURE,
51                         .type           = V4L2_CTRL_TYPE_INTEGER,
52                         .name           = "exposure",
53                         .minimum        = 0x00,
54                         .maximum        = 0x02ff,
55                         .step           = 0x1,
56                         .default_value  = PO1030_EXPOSURE_DEFAULT,
57                         .flags          = V4L2_CTRL_FLAG_SLIDER
58                 },
59                 .set = po1030_set_exposure,
60                 .get = po1030_get_exposure
61         }, {
62                 {
63                         .id             = V4L2_CID_RED_BALANCE,
64                         .type           = V4L2_CTRL_TYPE_INTEGER,
65                         .name           = "red balance",
66                         .minimum        = 0x00,
67                         .maximum        = 0xff,
68                         .step           = 0x1,
69                         .default_value  = PO1030_RED_GAIN_DEFAULT,
70                         .flags          = V4L2_CTRL_FLAG_SLIDER
71                 },
72                 .set = po1030_set_red_balance,
73                 .get = po1030_get_red_balance
74         }, {
75                 {
76                         .id             = V4L2_CID_BLUE_BALANCE,
77                         .type           = V4L2_CTRL_TYPE_INTEGER,
78                         .name           = "blue balance",
79                         .minimum        = 0x00,
80                         .maximum        = 0xff,
81                         .step           = 0x1,
82                         .default_value  = PO1030_BLUE_GAIN_DEFAULT,
83                         .flags          = V4L2_CTRL_FLAG_SLIDER
84                 },
85                 .set = po1030_set_blue_balance,
86                 .get = po1030_get_blue_balance
87         }, {
88                 {
89                         .id             = V4L2_CID_HFLIP,
90                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
91                         .name           = "horizontal flip",
92                         .minimum        = 0,
93                         .maximum        = 1,
94                         .step           = 1,
95                         .default_value  = 0,
96                 },
97                 .set = po1030_set_hflip,
98                 .get = po1030_get_hflip
99         }, {
100                 {
101                         .id             = V4L2_CID_VFLIP,
102                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
103                         .name           = "vertical flip",
104                         .minimum        = 0,
105                         .maximum        = 1,
106                         .step           = 1,
107                         .default_value  = 0,
108                 },
109                 .set = po1030_set_vflip,
110                 .get = po1030_get_vflip
111         }
112 };
113
114 static void po1030_dump_registers(struct sd *sd);
115
116 int po1030_probe(struct sd *sd)
117 {
118         u8 prod_id = 0, ver_id = 0, i;
119
120         if (force_sensor) {
121                 if (force_sensor == PO1030_SENSOR) {
122                         info("Forcing a %s sensor", po1030.name);
123                         goto sensor_found;
124                 }
125                 /* If we want to force another sensor, don't try to probe this
126                  * one */
127                 return -ENODEV;
128         }
129
130         info("Probing for a po1030 sensor");
131
132         /* Run the pre-init to actually probe the unit */
133         for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
134                 u8 data = preinit_po1030[i][2];
135                 if (preinit_po1030[i][0] == SENSOR)
136                         m5602_write_sensor(sd,
137                                 preinit_po1030[i][1], &data, 1);
138                 else
139                         m5602_write_bridge(sd, preinit_po1030[i][1], data);
140         }
141
142         if (m5602_read_sensor(sd, 0x3, &prod_id, 1))
143                 return -ENODEV;
144
145         if (m5602_read_sensor(sd, 0x4, &ver_id, 1))
146                 return -ENODEV;
147
148         if ((prod_id == 0x02) && (ver_id == 0xef)) {
149                 info("Detected a po1030 sensor");
150                 goto sensor_found;
151         }
152         return -ENODEV;
153
154 sensor_found:
155         sd->gspca_dev.cam.cam_mode = po1030_modes;
156         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
157         sd->desc->ctrls = po1030_ctrls;
158         sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
159         return 0;
160 }
161
162 int po1030_init(struct sd *sd)
163 {
164         int i, err = 0;
165
166         /* Init the sensor */
167         for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) {
168                 u8 data[2] = {0x00, 0x00};
169
170                 switch (init_po1030[i][0]) {
171                 case BRIDGE:
172                         err = m5602_write_bridge(sd,
173                                 init_po1030[i][1],
174                                 init_po1030[i][2]);
175                         break;
176
177                 case SENSOR:
178                         data[0] = init_po1030[i][2];
179                         err = m5602_write_sensor(sd,
180                                 init_po1030[i][1], data, 1);
181                         break;
182
183                 default:
184                         info("Invalid stream command, exiting init");
185                         return -EINVAL;
186                 }
187         }
188
189         if (dump_sensor)
190                 po1030_dump_registers(sd);
191
192         return err;
193 }
194
195 int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
196 {
197         struct sd *sd = (struct sd *) gspca_dev;
198         u8 i2c_data;
199         int err;
200
201         err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_H,
202                                  &i2c_data, 1);
203         if (err < 0)
204                 return err;
205         *val = (i2c_data << 8);
206
207         err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_M,
208                                  &i2c_data, 1);
209         *val |= i2c_data;
210
211         PDEBUG(D_V4L2, "Exposure read as %d", *val);
212
213         return err;
214 }
215
216 int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
217 {
218         struct sd *sd = (struct sd *) gspca_dev;
219         u8 i2c_data;
220         int err;
221
222         PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
223
224         i2c_data = ((val & 0xff00) >> 8);
225         PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
226                i2c_data);
227
228         err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_H,
229                                   &i2c_data, 1);
230         if (err < 0)
231                 return err;
232
233         i2c_data = (val & 0xff);
234         PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
235                i2c_data);
236         err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_M,
237                                   &i2c_data, 1);
238
239         return err;
240 }
241
242 int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
243 {
244         struct sd *sd = (struct sd *) gspca_dev;
245         u8 i2c_data;
246         int err;
247
248         err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN,
249                                  &i2c_data, 1);
250         *val = i2c_data;
251         PDEBUG(D_V4L2, "Read global gain %d", *val);
252
253         return err;
254 }
255
256 int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
257 {
258         struct sd *sd = (struct sd *) gspca_dev;
259         u8 i2c_data;
260         int err;
261
262         err = m5602_read_sensor(sd, PO1030_REG_CONTROL2,
263                                  &i2c_data, 1);
264
265         *val = (i2c_data >> 7) & 0x01 ;
266
267         PDEBUG(D_V4L2, "Read hflip %d", *val);
268
269         return err;
270 }
271
272 int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
273 {
274         struct sd *sd = (struct sd *) gspca_dev;
275         u8 i2c_data;
276         int err;
277
278         PDEBUG(D_V4L2, "Set hflip %d", val);
279         err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1);
280         if (err < 0)
281                 return err;
282
283         i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
284
285         err = m5602_write_sensor(sd, PO1030_REG_CONTROL2,
286                                  &i2c_data, 1);
287
288         return err;
289 }
290
291 int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
292 {
293         struct sd *sd = (struct sd *) gspca_dev;
294         u8 i2c_data;
295         int err;
296
297         err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN,
298                                  &i2c_data, 1);
299
300         *val = (i2c_data >> 6) & 0x01;
301
302         PDEBUG(D_V4L2, "Read vflip %d", *val);
303
304         return err;
305 }
306
307 int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
308 {
309         struct sd *sd = (struct sd *) gspca_dev;
310         u8 i2c_data;
311         int err;
312
313         PDEBUG(D_V4L2, "Set vflip %d", val);
314         err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1);
315         if (err < 0)
316                 return err;
317
318         i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
319
320         err = m5602_write_sensor(sd, PO1030_REG_CONTROL2,
321                                  &i2c_data, 1);
322
323         return err;
324 }
325
326 int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
327 {
328         struct sd *sd = (struct sd *) gspca_dev;
329         u8 i2c_data;
330         int err;
331
332         i2c_data = val & 0xff;
333         PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
334         err = m5602_write_sensor(sd, PO1030_REG_GLOBALGAIN,
335                                   &i2c_data, 1);
336         return err;
337 }
338
339 int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
340 {
341         struct sd *sd = (struct sd *) gspca_dev;
342         u8 i2c_data;
343         int err;
344
345         err = m5602_read_sensor(sd, PO1030_REG_RED_GAIN,
346                                  &i2c_data, 1);
347         *val = i2c_data;
348         PDEBUG(D_V4L2, "Read red gain %d", *val);
349         return err;
350 }
351
352 int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
353 {
354         struct sd *sd = (struct sd *) gspca_dev;
355         u8 i2c_data;
356         int err;
357
358         i2c_data = val & 0xff;
359         PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
360         err = m5602_write_sensor(sd, PO1030_REG_RED_GAIN,
361                                   &i2c_data, 1);
362         return err;
363 }
364
365 int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
366 {
367         struct sd *sd = (struct sd *) gspca_dev;
368         u8 i2c_data;
369         int err;
370
371         err = m5602_read_sensor(sd, PO1030_REG_BLUE_GAIN,
372                                  &i2c_data, 1);
373         *val = i2c_data;
374         PDEBUG(D_V4L2, "Read blue gain %d", *val);
375
376         return err;
377 }
378
379 int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
380 {
381         struct sd *sd = (struct sd *) gspca_dev;
382         u8 i2c_data;
383         int err;
384         i2c_data = val & 0xff;
385         PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
386         err = m5602_write_sensor(sd, PO1030_REG_BLUE_GAIN,
387                                   &i2c_data, 1);
388
389         return err;
390 }
391
392 int po1030_power_down(struct sd *sd)
393 {
394         return 0;
395 }
396
397 static void po1030_dump_registers(struct sd *sd)
398 {
399         int address;
400         u8 value = 0;
401
402         info("Dumping the po1030 sensor core registers");
403         for (address = 0; address < 0x7f; address++) {
404                 m5602_read_sensor(sd, address, &value, 1);
405                 info("register 0x%x contains 0x%x",
406                      address, value);
407         }
408
409         info("po1030 register state dump complete");
410
411         info("Probing for which registers that are read/write");
412         for (address = 0; address < 0xff; address++) {
413                 u8 old_value, ctrl_value;
414                 u8 test_value[2] = {0xff, 0xff};
415
416                 m5602_read_sensor(sd, address, &old_value, 1);
417                 m5602_write_sensor(sd, address, test_value, 1);
418                 m5602_read_sensor(sd, address, &ctrl_value, 1);
419
420                 if (ctrl_value == test_value[0])
421                         info("register 0x%x is writeable", address);
422                 else
423                         info("register 0x%x is read only", address);
424
425                 /* Restore original value */
426                 m5602_write_sensor(sd, address, &old_value, 1);
427         }
428 }