~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/media/video/gspca/m5602/m5602_ov9650.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Driver for the ov9650 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_ov9650.h"
 
22
 
 
23
static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
 
24
static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
 
25
static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
 
26
static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
 
27
static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
 
28
static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
 
29
static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
 
30
static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
 
31
static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
 
32
static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
 
33
static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
 
34
static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
 
35
static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
 
36
                                         __s32 *val);
 
37
static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
 
38
                                         __s32 val);
 
39
static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
 
40
static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
 
41
static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
 
42
static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
 
43
 
 
44
/* Vertically and horizontally flips the image if matched, needed for machines
 
45
   where the sensor is mounted upside down */
 
46
static
 
47
    const
 
48
        struct dmi_system_id ov9650_flip_dmi_table[] = {
 
49
        {
 
50
                .ident = "ASUS A6Ja",
 
51
                .matches = {
 
52
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 
53
                        DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
 
54
                }
 
55
        },
 
56
        {
 
57
                .ident = "ASUS A6JC",
 
58
                .matches = {
 
59
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 
60
                        DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
 
61
                }
 
62
        },
 
63
        {
 
64
                .ident = "ASUS A6K",
 
65
                .matches = {
 
66
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 
67
                        DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
 
68
                }
 
69
        },
 
70
        {
 
71
                .ident = "ASUS A6Kt",
 
72
                .matches = {
 
73
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 
74
                        DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
 
75
                }
 
76
        },
 
77
        {
 
78
                .ident = "ASUS A6VA",
 
79
                .matches = {
 
80
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 
81
                        DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
 
82
                }
 
83
        },
 
84
        {
 
85
 
 
86
                .ident = "ASUS A6VC",
 
87
                .matches = {
 
88
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 
89
                        DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
 
90
                }
 
91
        },
 
92
        {
 
93
                .ident = "ASUS A6VM",
 
94
                .matches = {
 
95
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 
96
                        DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
 
97
                }
 
98
        },
 
99
        {
 
100
                .ident = "ASUS A7V",
 
101
                .matches = {
 
102
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 
103
                        DMI_MATCH(DMI_PRODUCT_NAME, "A7V")
 
104
                }
 
105
        },
 
106
        {
 
107
                .ident = "Alienware Aurora m9700",
 
108
                .matches = {
 
109
                        DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
 
110
                        DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700")
 
111
                }
 
112
        },
 
113
        {}
 
114
};
 
115
 
 
116
static const struct ctrl ov9650_ctrls[] = {
 
117
#define EXPOSURE_IDX 0
 
118
        {
 
119
                {
 
120
                        .id             = V4L2_CID_EXPOSURE,
 
121
                        .type           = V4L2_CTRL_TYPE_INTEGER,
 
122
                        .name           = "exposure",
 
123
                        .minimum        = 0x00,
 
124
                        .maximum        = 0x1ff,
 
125
                        .step           = 0x4,
 
126
                        .default_value  = EXPOSURE_DEFAULT,
 
127
                        .flags          = V4L2_CTRL_FLAG_SLIDER
 
128
                },
 
129
                .set = ov9650_set_exposure,
 
130
                .get = ov9650_get_exposure
 
131
        },
 
132
#define GAIN_IDX 1
 
133
        {
 
134
                {
 
135
                        .id             = V4L2_CID_GAIN,
 
136
                        .type           = V4L2_CTRL_TYPE_INTEGER,
 
137
                        .name           = "gain",
 
138
                        .minimum        = 0x00,
 
139
                        .maximum        = 0x3ff,
 
140
                        .step           = 0x1,
 
141
                        .default_value  = GAIN_DEFAULT,
 
142
                        .flags          = V4L2_CTRL_FLAG_SLIDER
 
143
                },
 
144
                .set = ov9650_set_gain,
 
145
                .get = ov9650_get_gain
 
146
        },
 
147
#define RED_BALANCE_IDX 2
 
148
        {
 
149
                {
 
150
                        .id             = V4L2_CID_RED_BALANCE,
 
151
                        .type           = V4L2_CTRL_TYPE_INTEGER,
 
152
                        .name           = "red balance",
 
153
                        .minimum        = 0x00,
 
154
                        .maximum        = 0xff,
 
155
                        .step           = 0x1,
 
156
                        .default_value  = RED_GAIN_DEFAULT,
 
157
                        .flags          = V4L2_CTRL_FLAG_SLIDER
 
158
                },
 
159
                .set = ov9650_set_red_balance,
 
160
                .get = ov9650_get_red_balance
 
161
        },
 
162
#define BLUE_BALANCE_IDX 3
 
163
        {
 
164
                {
 
165
                        .id             = V4L2_CID_BLUE_BALANCE,
 
166
                        .type           = V4L2_CTRL_TYPE_INTEGER,
 
167
                        .name           = "blue balance",
 
168
                        .minimum        = 0x00,
 
169
                        .maximum        = 0xff,
 
170
                        .step           = 0x1,
 
171
                        .default_value  = BLUE_GAIN_DEFAULT,
 
172
                        .flags          = V4L2_CTRL_FLAG_SLIDER
 
173
                },
 
174
                .set = ov9650_set_blue_balance,
 
175
                .get = ov9650_get_blue_balance
 
176
        },
 
177
#define HFLIP_IDX 4
 
178
        {
 
179
                {
 
180
                        .id             = V4L2_CID_HFLIP,
 
181
                        .type           = V4L2_CTRL_TYPE_BOOLEAN,
 
182
                        .name           = "horizontal flip",
 
183
                        .minimum        = 0,
 
184
                        .maximum        = 1,
 
185
                        .step           = 1,
 
186
                        .default_value  = 0
 
187
                },
 
188
                .set = ov9650_set_hflip,
 
189
                .get = ov9650_get_hflip
 
190
        },
 
191
#define VFLIP_IDX 5
 
192
        {
 
193
                {
 
194
                        .id             = V4L2_CID_VFLIP,
 
195
                        .type           = V4L2_CTRL_TYPE_BOOLEAN,
 
196
                        .name           = "vertical flip",
 
197
                        .minimum        = 0,
 
198
                        .maximum        = 1,
 
199
                        .step           = 1,
 
200
                        .default_value  = 0
 
201
                },
 
202
                .set = ov9650_set_vflip,
 
203
                .get = ov9650_get_vflip
 
204
        },
 
205
#define AUTO_WHITE_BALANCE_IDX 6
 
206
        {
 
207
                {
 
208
                        .id             = V4L2_CID_AUTO_WHITE_BALANCE,
 
209
                        .type           = V4L2_CTRL_TYPE_BOOLEAN,
 
210
                        .name           = "auto white balance",
 
211
                        .minimum        = 0,
 
212
                        .maximum        = 1,
 
213
                        .step           = 1,
 
214
                        .default_value  = 1
 
215
                },
 
216
                .set = ov9650_set_auto_white_balance,
 
217
                .get = ov9650_get_auto_white_balance
 
218
        },
 
219
#define AUTO_GAIN_CTRL_IDX 7
 
220
        {
 
221
                {
 
222
                        .id             = V4L2_CID_AUTOGAIN,
 
223
                        .type           = V4L2_CTRL_TYPE_BOOLEAN,
 
224
                        .name           = "auto gain control",
 
225
                        .minimum        = 0,
 
226
                        .maximum        = 1,
 
227
                        .step           = 1,
 
228
                        .default_value  = 1
 
229
                },
 
230
                .set = ov9650_set_auto_gain,
 
231
                .get = ov9650_get_auto_gain
 
232
        },
 
233
#define AUTO_EXPOSURE_IDX 8
 
234
        {
 
235
                {
 
236
                        .id             = V4L2_CID_EXPOSURE_AUTO,
 
237
                        .type           = V4L2_CTRL_TYPE_BOOLEAN,
 
238
                        .name           = "auto exposure",
 
239
                        .minimum        = 0,
 
240
                        .maximum        = 1,
 
241
                        .step           = 1,
 
242
                        .default_value  = 1
 
243
                },
 
244
                .set = ov9650_set_auto_exposure,
 
245
                .get = ov9650_get_auto_exposure
 
246
        }
 
247
 
 
248
};
 
249
 
 
250
static struct v4l2_pix_format ov9650_modes[] = {
 
251
        {
 
252
                176,
 
253
                144,
 
254
                V4L2_PIX_FMT_SBGGR8,
 
255
                V4L2_FIELD_NONE,
 
256
                .sizeimage =
 
257
                        176 * 144,
 
258
                .bytesperline = 176,
 
259
                .colorspace = V4L2_COLORSPACE_SRGB,
 
260
                .priv = 9
 
261
        }, {
 
262
                320,
 
263
                240,
 
264
                V4L2_PIX_FMT_SBGGR8,
 
265
                V4L2_FIELD_NONE,
 
266
                .sizeimage =
 
267
                        320 * 240,
 
268
                .bytesperline = 320,
 
269
                .colorspace = V4L2_COLORSPACE_SRGB,
 
270
                .priv = 8
 
271
        }, {
 
272
                352,
 
273
                288,
 
274
                V4L2_PIX_FMT_SBGGR8,
 
275
                V4L2_FIELD_NONE,
 
276
                .sizeimage =
 
277
                        352 * 288,
 
278
                .bytesperline = 352,
 
279
                .colorspace = V4L2_COLORSPACE_SRGB,
 
280
                .priv = 9
 
281
        }, {
 
282
                640,
 
283
                480,
 
284
                V4L2_PIX_FMT_SBGGR8,
 
285
                V4L2_FIELD_NONE,
 
286
                .sizeimage =
 
287
                        640 * 480,
 
288
                .bytesperline = 640,
 
289
                .colorspace = V4L2_COLORSPACE_SRGB,
 
290
                .priv = 9
 
291
        }
 
292
};
 
293
 
 
294
static void ov9650_dump_registers(struct sd *sd);
 
295
 
 
296
int ov9650_probe(struct sd *sd)
 
297
{
 
298
        int err = 0;
 
299
        u8 prod_id = 0, ver_id = 0, i;
 
300
        s32 *sensor_settings;
 
301
 
 
302
        if (force_sensor) {
 
303
                if (force_sensor == OV9650_SENSOR) {
 
304
                        pr_info("Forcing an %s sensor\n", ov9650.name);
 
305
                        goto sensor_found;
 
306
                }
 
307
                /* If we want to force another sensor,
 
308
                   don't try to probe this one */
 
309
                return -ENODEV;
 
310
        }
 
311
 
 
312
        PDEBUG(D_PROBE, "Probing for an ov9650 sensor");
 
313
 
 
314
        /* Run the pre-init before probing the sensor */
 
315
        for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) {
 
316
                u8 data = preinit_ov9650[i][2];
 
317
                if (preinit_ov9650[i][0] == SENSOR)
 
318
                        err = m5602_write_sensor(sd,
 
319
                                preinit_ov9650[i][1], &data, 1);
 
320
                else
 
321
                        err = m5602_write_bridge(sd,
 
322
                                preinit_ov9650[i][1], data);
 
323
        }
 
324
 
 
325
        if (err < 0)
 
326
                return err;
 
327
 
 
328
        if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
 
329
                return -ENODEV;
 
330
 
 
331
        if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
 
332
                return -ENODEV;
 
333
 
 
334
        if ((prod_id == 0x96) && (ver_id == 0x52)) {
 
335
                pr_info("Detected an ov9650 sensor\n");
 
336
                goto sensor_found;
 
337
        }
 
338
        return -ENODEV;
 
339
 
 
340
sensor_found:
 
341
        sensor_settings = kmalloc(
 
342
                ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL);
 
343
        if (!sensor_settings)
 
344
                return -ENOMEM;
 
345
 
 
346
        sd->gspca_dev.cam.cam_mode = ov9650_modes;
 
347
        sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
 
348
        sd->desc->ctrls = ov9650_ctrls;
 
349
        sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls);
 
350
 
 
351
        for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++)
 
352
                sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value;
 
353
        sd->sensor_priv = sensor_settings;
 
354
        return 0;
 
355
}
 
356
 
 
357
int ov9650_init(struct sd *sd)
 
358
{
 
359
        int i, err = 0;
 
360
        u8 data;
 
361
        s32 *sensor_settings = sd->sensor_priv;
 
362
 
 
363
        if (dump_sensor)
 
364
                ov9650_dump_registers(sd);
 
365
 
 
366
        for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
 
367
                data = init_ov9650[i][2];
 
368
                if (init_ov9650[i][0] == SENSOR)
 
369
                        err = m5602_write_sensor(sd, init_ov9650[i][1],
 
370
                                                  &data, 1);
 
371
                else
 
372
                        err = m5602_write_bridge(sd, init_ov9650[i][1], data);
 
373
        }
 
374
 
 
375
        err = ov9650_set_exposure(&sd->gspca_dev,
 
376
                                   sensor_settings[EXPOSURE_IDX]);
 
377
        if (err < 0)
 
378
                return err;
 
379
 
 
380
        err = ov9650_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
 
381
        if (err < 0)
 
382
                return err;
 
383
 
 
384
        err = ov9650_set_red_balance(&sd->gspca_dev,
 
385
                                      sensor_settings[RED_BALANCE_IDX]);
 
386
        if (err < 0)
 
387
                return err;
 
388
 
 
389
        err = ov9650_set_blue_balance(&sd->gspca_dev,
 
390
                                       sensor_settings[BLUE_BALANCE_IDX]);
 
391
        if (err < 0)
 
392
                return err;
 
393
 
 
394
        err = ov9650_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
 
395
        if (err < 0)
 
396
                return err;
 
397
 
 
398
        err = ov9650_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
 
399
        if (err < 0)
 
400
                return err;
 
401
 
 
402
        err = ov9650_set_auto_exposure(&sd->gspca_dev,
 
403
                                sensor_settings[AUTO_EXPOSURE_IDX]);
 
404
        if (err < 0)
 
405
                return err;
 
406
 
 
407
        err = ov9650_set_auto_white_balance(&sd->gspca_dev,
 
408
                                sensor_settings[AUTO_WHITE_BALANCE_IDX]);
 
409
        if (err < 0)
 
410
                return err;
 
411
 
 
412
        err = ov9650_set_auto_gain(&sd->gspca_dev,
 
413
                                sensor_settings[AUTO_GAIN_CTRL_IDX]);
 
414
        return err;
 
415
}
 
416
 
 
417
int ov9650_start(struct sd *sd)
 
418
{
 
419
        u8 data;
 
420
        int i, err = 0;
 
421
        struct cam *cam = &sd->gspca_dev.cam;
 
422
        s32 *sensor_settings = sd->sensor_priv;
 
423
 
 
424
        int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
 
425
        int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
 
426
        int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
 
427
        int hor_offs = OV9650_LEFT_OFFSET;
 
428
 
 
429
        if ((!dmi_check_system(ov9650_flip_dmi_table) &&
 
430
                sensor_settings[VFLIP_IDX]) ||
 
431
                (dmi_check_system(ov9650_flip_dmi_table) &&
 
432
                !sensor_settings[VFLIP_IDX]))
 
433
                ver_offs--;
 
434
 
 
435
        if (width <= 320)
 
436
                hor_offs /= 2;
 
437
 
 
438
        /* Synthesize the vsync/hsync setup */
 
439
        for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
 
440
                if (res_init_ov9650[i][0] == BRIDGE)
 
441
                        err = m5602_write_bridge(sd, res_init_ov9650[i][1],
 
442
                                res_init_ov9650[i][2]);
 
443
                else if (res_init_ov9650[i][0] == SENSOR) {
 
444
                        data = res_init_ov9650[i][2];
 
445
                        err = m5602_write_sensor(sd,
 
446
                                res_init_ov9650[i][1], &data, 1);
 
447
                }
 
448
        }
 
449
        if (err < 0)
 
450
                return err;
 
451
 
 
452
        err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
 
453
                                 ((ver_offs >> 8) & 0xff));
 
454
        if (err < 0)
 
455
                return err;
 
456
 
 
457
        err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
 
458
        if (err < 0)
 
459
                return err;
 
460
 
 
461
        err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
 
462
        if (err < 0)
 
463
                return err;
 
464
 
 
465
        err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
 
466
        if (err < 0)
 
467
                return err;
 
468
 
 
469
        err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
 
470
        if (err < 0)
 
471
                return err;
 
472
 
 
473
        for (i = 0; i < 2 && !err; i++)
 
474
                err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
 
475
        if (err < 0)
 
476
                return err;
 
477
 
 
478
        err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
 
479
        if (err < 0)
 
480
                return err;
 
481
 
 
482
        err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
 
483
        if (err < 0)
 
484
                return err;
 
485
 
 
486
        err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
 
487
                                 (hor_offs >> 8) & 0xff);
 
488
        if (err < 0)
 
489
                return err;
 
490
 
 
491
        err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
 
492
        if (err < 0)
 
493
                return err;
 
494
 
 
495
        err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
 
496
                                 ((width + hor_offs) >> 8) & 0xff);
 
497
        if (err < 0)
 
498
                return err;
 
499
 
 
500
        err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
 
501
                                 ((width + hor_offs) & 0xff));
 
502
        if (err < 0)
 
503
                return err;
 
504
 
 
505
        err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
 
506
        if (err < 0)
 
507
                return err;
 
508
 
 
509
        switch (width) {
 
510
        case 640:
 
511
                PDEBUG(D_V4L2, "Configuring camera for VGA mode");
 
512
 
 
513
                data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
 
514
                       OV9650_RAW_RGB_SELECT;
 
515
                err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
 
516
                break;
 
517
 
 
518
        case 352:
 
519
                PDEBUG(D_V4L2, "Configuring camera for CIF mode");
 
520
 
 
521
                data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
 
522
                                OV9650_RAW_RGB_SELECT;
 
523
                err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
 
524
                break;
 
525
 
 
526
        case 320:
 
527
                PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
 
528
 
 
529
                data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
 
530
                                OV9650_RAW_RGB_SELECT;
 
531
                err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
 
532
                break;
 
533
 
 
534
        case 176:
 
535
                PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
 
536
 
 
537
                data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
 
538
                        OV9650_RAW_RGB_SELECT;
 
539
                err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
 
540
                break;
 
541
        }
 
542
        return err;
 
543
}
 
544
 
 
545
int ov9650_stop(struct sd *sd)
 
546
{
 
547
        u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
 
548
        return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
 
549
}
 
550
 
 
551
void ov9650_disconnect(struct sd *sd)
 
552
{
 
553
        ov9650_stop(sd);
 
554
 
 
555
        sd->sensor = NULL;
 
556
        kfree(sd->sensor_priv);
 
557
}
 
558
 
 
559
static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
 
560
{
 
561
        struct sd *sd = (struct sd *) gspca_dev;
 
562
        s32 *sensor_settings = sd->sensor_priv;
 
563
 
 
564
        *val = sensor_settings[EXPOSURE_IDX];
 
565
        PDEBUG(D_V4L2, "Read exposure %d", *val);
 
566
        return 0;
 
567
}
 
568
 
 
569
static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 
570
{
 
571
        struct sd *sd = (struct sd *) gspca_dev;
 
572
        s32 *sensor_settings = sd->sensor_priv;
 
573
        u8 i2c_data;
 
574
        int err;
 
575
 
 
576
        PDEBUG(D_V4L2, "Set exposure to %d", val);
 
577
 
 
578
        sensor_settings[EXPOSURE_IDX] = val;
 
579
        /* The 6 MSBs */
 
580
        i2c_data = (val >> 10) & 0x3f;
 
581
        err = m5602_write_sensor(sd, OV9650_AECHM,
 
582
                                  &i2c_data, 1);
 
583
        if (err < 0)
 
584
                return err;
 
585
 
 
586
        /* The 8 middle bits */
 
587
        i2c_data = (val >> 2) & 0xff;
 
588
        err = m5602_write_sensor(sd, OV9650_AECH,
 
589
                                  &i2c_data, 1);
 
590
        if (err < 0)
 
591
                return err;
 
592
 
 
593
        /* The 2 LSBs */
 
594
        i2c_data = val & 0x03;
 
595
        err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
 
596
        return err;
 
597
}
 
598
 
 
599
static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
 
600
{
 
601
        struct sd *sd = (struct sd *) gspca_dev;
 
602
        s32 *sensor_settings = sd->sensor_priv;
 
603
 
 
604
        *val = sensor_settings[GAIN_IDX];
 
605
        PDEBUG(D_V4L2, "Read gain %d", *val);
 
606
        return 0;
 
607
}
 
608
 
 
609
static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 
610
{
 
611
        int err;
 
612
        u8 i2c_data;
 
613
        struct sd *sd = (struct sd *) gspca_dev;
 
614
        s32 *sensor_settings = sd->sensor_priv;
 
615
 
 
616
        PDEBUG(D_V4L2, "Setting gain to %d", val);
 
617
 
 
618
        sensor_settings[GAIN_IDX] = val;
 
619
 
 
620
        /* The 2 MSB */
 
621
        /* Read the OV9650_VREF register first to avoid
 
622
           corrupting the VREF high and low bits */
 
623
        err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
 
624
        if (err < 0)
 
625
                return err;
 
626
 
 
627
        /* Mask away all uninteresting bits */
 
628
        i2c_data = ((val & 0x0300) >> 2) |
 
629
                        (i2c_data & 0x3f);
 
630
        err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
 
631
        if (err < 0)
 
632
                return err;
 
633
 
 
634
        /* The 8 LSBs */
 
635
        i2c_data = val & 0xff;
 
636
        err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
 
637
        return err;
 
638
}
 
639
 
 
640
static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
 
641
{
 
642
        struct sd *sd = (struct sd *) gspca_dev;
 
643
        s32 *sensor_settings = sd->sensor_priv;
 
644
 
 
645
        *val = sensor_settings[RED_BALANCE_IDX];
 
646
        PDEBUG(D_V4L2, "Read red gain %d", *val);
 
647
        return 0;
 
648
}
 
649
 
 
650
static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
 
651
{
 
652
        int err;
 
653
        u8 i2c_data;
 
654
        struct sd *sd = (struct sd *) gspca_dev;
 
655
        s32 *sensor_settings = sd->sensor_priv;
 
656
 
 
657
        PDEBUG(D_V4L2, "Set red gain to %d", val);
 
658
 
 
659
        sensor_settings[RED_BALANCE_IDX] = val;
 
660
 
 
661
        i2c_data = val & 0xff;
 
662
        err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
 
663
        return err;
 
664
}
 
665
 
 
666
static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
 
667
{
 
668
        struct sd *sd = (struct sd *) gspca_dev;
 
669
        s32 *sensor_settings = sd->sensor_priv;
 
670
 
 
671
        *val = sensor_settings[BLUE_BALANCE_IDX];
 
672
        PDEBUG(D_V4L2, "Read blue gain %d", *val);
 
673
 
 
674
        return 0;
 
675
}
 
676
 
 
677
static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
 
678
{
 
679
        int err;
 
680
        u8 i2c_data;
 
681
        struct sd *sd = (struct sd *) gspca_dev;
 
682
        s32 *sensor_settings = sd->sensor_priv;
 
683
 
 
684
        PDEBUG(D_V4L2, "Set blue gain to %d", val);
 
685
 
 
686
        sensor_settings[BLUE_BALANCE_IDX] = val;
 
687
 
 
688
        i2c_data = val & 0xff;
 
689
        err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
 
690
        return err;
 
691
}
 
692
 
 
693
static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
 
694
{
 
695
        struct sd *sd = (struct sd *) gspca_dev;
 
696
        s32 *sensor_settings = sd->sensor_priv;
 
697
 
 
698
        *val = sensor_settings[HFLIP_IDX];
 
699
        PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
 
700
        return 0;
 
701
}
 
702
 
 
703
static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
 
704
{
 
705
        int err;
 
706
        u8 i2c_data;
 
707
        struct sd *sd = (struct sd *) gspca_dev;
 
708
        s32 *sensor_settings = sd->sensor_priv;
 
709
 
 
710
        PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
 
711
 
 
712
        sensor_settings[HFLIP_IDX] = val;
 
713
 
 
714
        if (!dmi_check_system(ov9650_flip_dmi_table))
 
715
                i2c_data = ((val & 0x01) << 5) |
 
716
                                (sensor_settings[VFLIP_IDX] << 4);
 
717
        else
 
718
                i2c_data = ((val & 0x01) << 5) |
 
719
                                (!sensor_settings[VFLIP_IDX] << 4);
 
720
 
 
721
        err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
 
722
 
 
723
        return err;
 
724
}
 
725
 
 
726
static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
 
727
{
 
728
        struct sd *sd = (struct sd *) gspca_dev;
 
729
        s32 *sensor_settings = sd->sensor_priv;
 
730
 
 
731
        *val = sensor_settings[VFLIP_IDX];
 
732
        PDEBUG(D_V4L2, "Read vertical flip %d", *val);
 
733
 
 
734
        return 0;
 
735
}
 
736
 
 
737
static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
 
738
{
 
739
        int err;
 
740
        u8 i2c_data;
 
741
        struct sd *sd = (struct sd *) gspca_dev;
 
742
        s32 *sensor_settings = sd->sensor_priv;
 
743
 
 
744
        PDEBUG(D_V4L2, "Set vertical flip to %d", val);
 
745
        sensor_settings[VFLIP_IDX] = val;
 
746
 
 
747
        if (dmi_check_system(ov9650_flip_dmi_table))
 
748
                val = !val;
 
749
 
 
750
        i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
 
751
        err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
 
752
        if (err < 0)
 
753
                return err;
 
754
 
 
755
        /* When vflip is toggled we need to readjust the bridge hsync/vsync */
 
756
        if (gspca_dev->streaming)
 
757
                err = ov9650_start(sd);
 
758
 
 
759
        return err;
 
760
}
 
761
 
 
762
static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
 
763
{
 
764
        struct sd *sd = (struct sd *) gspca_dev;
 
765
        s32 *sensor_settings = sd->sensor_priv;
 
766
 
 
767
        *val = sensor_settings[AUTO_EXPOSURE_IDX];
 
768
        PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
 
769
        return 0;
 
770
}
 
771
 
 
772
static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
 
773
                                    __s32 val)
 
774
{
 
775
        int err;
 
776
        u8 i2c_data;
 
777
        struct sd *sd = (struct sd *) gspca_dev;
 
778
        s32 *sensor_settings = sd->sensor_priv;
 
779
 
 
780
        PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
 
781
 
 
782
        sensor_settings[AUTO_EXPOSURE_IDX] = val;
 
783
        err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 
784
        if (err < 0)
 
785
                return err;
 
786
 
 
787
        i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
 
788
 
 
789
        return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
 
790
}
 
791
 
 
792
static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
 
793
                                         __s32 *val)
 
794
{
 
795
        struct sd *sd = (struct sd *) gspca_dev;
 
796
        s32 *sensor_settings = sd->sensor_priv;
 
797
 
 
798
        *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
 
799
        return 0;
 
800
}
 
801
 
 
802
static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
 
803
                                         __s32 val)
 
804
{
 
805
        int err;
 
806
        u8 i2c_data;
 
807
        struct sd *sd = (struct sd *) gspca_dev;
 
808
        s32 *sensor_settings = sd->sensor_priv;
 
809
 
 
810
        PDEBUG(D_V4L2, "Set auto white balance to %d", val);
 
811
 
 
812
        sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
 
813
        err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 
814
        if (err < 0)
 
815
                return err;
 
816
 
 
817
        i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
 
818
        err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
 
819
 
 
820
        return err;
 
821
}
 
822
 
 
823
static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
 
824
{
 
825
        struct sd *sd = (struct sd *) gspca_dev;
 
826
        s32 *sensor_settings = sd->sensor_priv;
 
827
 
 
828
        *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
 
829
        PDEBUG(D_V4L2, "Read auto gain control %d", *val);
 
830
        return 0;
 
831
}
 
832
 
 
833
static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
 
834
{
 
835
        int err;
 
836
        u8 i2c_data;
 
837
        struct sd *sd = (struct sd *) gspca_dev;
 
838
        s32 *sensor_settings = sd->sensor_priv;
 
839
 
 
840
        PDEBUG(D_V4L2, "Set auto gain control to %d", val);
 
841
 
 
842
        sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
 
843
        err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 
844
        if (err < 0)
 
845
                return err;
 
846
 
 
847
        i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
 
848
 
 
849
        return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
 
850
}
 
851
 
 
852
static void ov9650_dump_registers(struct sd *sd)
 
853
{
 
854
        int address;
 
855
        pr_info("Dumping the ov9650 register state\n");
 
856
        for (address = 0; address < 0xa9; address++) {
 
857
                u8 value;
 
858
                m5602_read_sensor(sd, address, &value, 1);
 
859
                pr_info("register 0x%x contains 0x%x\n", address, value);
 
860
        }
 
861
 
 
862
        pr_info("ov9650 register state dump complete\n");
 
863
 
 
864
        pr_info("Probing for which registers that are read/write\n");
 
865
        for (address = 0; address < 0xff; address++) {
 
866
                u8 old_value, ctrl_value;
 
867
                u8 test_value[2] = {0xff, 0xff};
 
868
 
 
869
                m5602_read_sensor(sd, address, &old_value, 1);
 
870
                m5602_write_sensor(sd, address, test_value, 1);
 
871
                m5602_read_sensor(sd, address, &ctrl_value, 1);
 
872
 
 
873
                if (ctrl_value == test_value[0])
 
874
                        pr_info("register 0x%x is writeable\n", address);
 
875
                else
 
876
                        pr_info("register 0x%x is read only\n", address);
 
877
 
 
878
                /* Restore original value */
 
879
                m5602_write_sensor(sd, address, &old_value, 1);
 
880
        }
 
881
}