Revert "media: camera config changes"
[linux-2.6.git] / drivers / media / video / tegra / ov2710.c
1 /*
2  * ov2710.c - ov2710 sensor driver
3  *
4  * Copyright (c) 2011, NVIDIA, All Rights Reserved.
5  *
6  * Contributors:
7  *      erik lilliebjerg <elilliebjerg@nvidia.com>
8  *
9  * Leverage OV5650.c
10  *
11  * This file is licensed under the terms of the GNU General Public License
12  * version 2. This program is licensed "as is" without any warranty of any
13  * kind, whether express or implied.
14  */
15
16 #include <linux/delay.h>
17 #include <linux/fs.h>
18 #include <linux/i2c.h>
19 #include <linux/miscdevice.h>
20 #include <linux/slab.h>
21 #include <linux/uaccess.h>
22 #include <media/ov2710.h>
23
24 #define SIZEOF_I2C_TRANSBUF 32
25
26 struct ov2710_reg {
27         u16 addr;
28         u16 val;
29 };
30
31 struct ov2710_info {
32         int mode;
33         struct i2c_client *i2c_client;
34         struct ov2710_platform_data *pdata;
35         u8 i2c_trans_buf[SIZEOF_I2C_TRANSBUF];
36 };
37
38 #define OV2710_TABLE_WAIT_MS 0
39 #define OV2710_TABLE_END 1
40 #define OV2710_MAX_RETRIES 3
41
42 static struct ov2710_reg mode_1920x1080[] = {
43         {0x3103, 0x93},
44         {0x3008, 0x82},
45         {OV2710_TABLE_WAIT_MS, 5},
46         {0x3008, 0x42},
47         {OV2710_TABLE_WAIT_MS, 5},
48         {0x3017, 0x7f},
49         {0x3018, 0xfc},
50         {0x3706, 0x61},
51         {0x3712, 0x0c},
52         {0x3630, 0x6d},
53         {0x3801, 0xb4},
54
55         {0x3621, 0x04},
56         {0x3604, 0x60},
57         {0x3603, 0xa7},
58         {0x3631, 0x26},
59         {0x3600, 0x04},
60         {0x3620, 0x37},
61         {0x3623, 0x00},
62         {0x3702, 0x9e},
63         {0x3703, 0x5c},
64         {0x3704, 0x40},
65         {0x370d, 0x0f},
66         {0x3713, 0x9f},
67         {0x3714, 0x4c},
68         {0x3710, 0x9e},
69         {0x3801, 0xc4},
70         {0x3605, 0x05},
71         {0x3606, 0x3f},
72         {0x302d, 0x90},
73         {0x370b, 0x40},
74         {0x3716, 0x31},
75         {0x3707, 0x52},
76         {0x380d, 0x74},
77         {0x5181, 0x20},
78         {0x518f, 0x00},
79         {0x4301, 0xff},
80         {0x4303, 0x00},
81         {0x3a00, 0x78},
82         {0x300f, 0x88},
83         {0x3011, 0x28},
84         {0x3a1a, 0x06},
85         {0x3a18, 0x00},
86         {0x3a19, 0x7a},
87         {0x3a13, 0x54},
88         {0x382e, 0x0f},
89         {0x381a, 0x1a},
90         {0x401d, 0x02},
91
92         {0x381c, 0x00},
93         {0x381d, 0x02},
94         {0x381e, 0x04},
95         {0x381f, 0x38},
96         {0x3820, 0x00},
97         {0x3821, 0x98},
98         {0x3800, 0x01},
99         {0x3802, 0x00},
100         {0x3803, 0x0a},
101         {0x3804, 0x07},
102         {0x3805, 0x90},
103         {0x3806, 0x04},
104         {0x3807, 0x40},
105         {0x3808, 0x07},
106         {0x3809, 0x90},
107         {0x380a, 0x04},
108         {0x380b, 0x40},
109         {0x380e, 0x04},
110         {0x380f, 0x50},
111         {0x380c, 0x09},
112         {0x380d, 0x74},
113         {0x3810, 0x08},
114         {0x3811, 0x02},
115
116         {0x5688, 0x03},
117         {0x5684, 0x07},
118         {0x5685, 0xa0},
119         {0x5686, 0x04},
120         {0x5687, 0x43},
121         {0x3011, 0x0a},
122         {0x300f, 0x8a},
123         {0x3017, 0x00},
124         {0x3018, 0x00},
125         {0x4800, 0x24},
126         {0x300e, 0x04},
127         {0x4801, 0x0f},
128
129         {0x300f, 0xc3},
130         {0x3010, 0x00},
131         {0x3011, 0x0a},
132         {0x3012, 0x01},
133
134         {0x3a0f, 0x40},
135         {0x3a10, 0x38},
136         {0x3a1b, 0x48},
137         {0x3a1e, 0x30},
138         {0x3a11, 0x90},
139         {0x3a1f, 0x10},
140
141         {0x3a0e, 0x03},
142         {0x3a0d, 0x04},
143         {0x3a08, 0x14},
144         {0x3a09, 0xc0},
145         {0x3a0a, 0x11},
146         {0x3a0b, 0x40},
147
148         {0x300f, 0xc3},
149         {0x3010, 0x00},
150         {0x3011, 0x0e},
151         {0x3012, 0x02},
152         {0x380c, 0x09},
153         {0x380d, 0xec},
154         {0x3703, 0x61},
155         {0x3704, 0x44},
156         {0x3801, 0xd2},
157
158         {0x3503, 0x33},
159         {0x3500, 0x00},
160         {0x3501, 0x00},
161         {0x3502, 0x00},
162         {0x350a, 0x00},
163         {0x350b, 0x00},
164         {0x5001, 0x4e},
165         {0x5000, 0x5f},
166         {0x3008, 0x02},
167
168         {OV2710_TABLE_END, 0x0000}
169 };
170
171 static struct ov2710_reg mode_1280x720[] = {
172         {0x3103, 0x93},
173         {0x3008, 0x82},
174         {OV2710_TABLE_WAIT_MS, 5},
175         {0x3008, 0x42},
176         {OV2710_TABLE_WAIT_MS, 5},
177         {0x3017, 0x7f},
178         {0x3018, 0xfc},
179
180         {0x3706, 0x61},
181         {0x3712, 0x0c},
182         {0x3630, 0x6d},
183         {0x3801, 0xb4},
184         {0x3621, 0x04},
185         {0x3604, 0x60},
186         {0x3603, 0xa7},
187         {0x3631, 0x26},
188         {0x3600, 0x04},
189         {0x3620, 0x37},
190         {0x3623, 0x00},
191         {0x3702, 0x9e},
192         {0x3703, 0x5c},
193         {0x3704, 0x40},
194         {0x370d, 0x0f},
195         {0x3713, 0x9f},
196         {0x3714, 0x4c},
197         {0x3710, 0x9e},
198         {0x3801, 0xc4},
199         {0x3605, 0x05},
200         {0x3606, 0x3f},
201         {0x302d, 0x90},
202         {0x370b, 0x40},
203         {0x3716, 0x31},
204         {0x3707, 0x52},
205         {0x380d, 0x74},
206         {0x5181, 0x20},
207         {0x518f, 0x00},
208         {0x4301, 0xff},
209         {0x4303, 0x00},
210         {0x3a00, 0x78},
211         {0x300f, 0x88},
212         {0x3011, 0x28},
213         {0x3a1a, 0x06},
214         {0x3a18, 0x00},
215         {0x3a19, 0x7a},
216         {0x3a13, 0x54},
217         {0x382e, 0x0f},
218         {0x381a, 0x1a},
219         {0x401d, 0x02},
220
221         {0x381c, 0x10},
222         {0x381d, 0xb0},
223         {0x381e, 0x02},
224         {0x381f, 0xec},
225         {0x3800, 0x01},
226         {0x3820, 0x0a},
227         {0x3821, 0x2a},
228         {0x3804, 0x05},
229         {0x3805, 0x10},
230         {0x3802, 0x00},
231         {0x3803, 0x04},
232         {0x3806, 0x02},
233         {0x3807, 0xe0},
234         {0x3808, 0x05},
235         {0x3809, 0x10},
236         {0x380a, 0x02},
237         {0x380b, 0xe0},
238         {0x380e, 0x02},
239         {0x380f, 0xf0},
240         {0x380c, 0x07},
241         {0x380d, 0x00},
242         {0x3810, 0x10},
243         {0x3811, 0x06},
244
245         {0x5688, 0x03},
246         {0x5684, 0x05},
247         {0x5685, 0x00},
248         {0x5686, 0x02},
249         {0x5687, 0xd0},
250
251         {0x3a08, 0x1b},
252         {0x3a09, 0xe6},
253         {0x3a0a, 0x17},
254         {0x3a0b, 0x40},
255         {0x3a0e, 0x01},
256         {0x3a0d, 0x02},
257         {0x3011, 0x0a},
258         {0x300f, 0x8a},
259         {0x3017, 0x00},
260         {0x3018, 0x00},
261         {0x4800, 0x24},
262         {0x300e, 0x04},
263         {0x4801, 0x0f},
264         {0x300f, 0xc3},
265         {0x3a0f, 0x40},
266         {0x3a10, 0x38},
267         {0x3a1b, 0x48},
268         {0x3a1e, 0x30},
269         {0x3a11, 0x90},
270         {0x3a1f, 0x10},
271
272         {0x3010, 0x10},
273         {0x3a0e, 0x02},
274         {0x3a0d, 0x03},
275         {0x3a08, 0x0d},
276         {0x3a09, 0xf3},
277         {0x3a0a, 0x0b},
278         {0x3a0b, 0xa0},
279
280         {0x300f, 0xc3},
281         {0x3011, 0x0e},
282         {0x3012, 0x02},
283         {0x380c, 0x07},
284         {0x380d, 0x6a},
285         {0x3703, 0x5c},
286         {0x3704, 0x40},
287         {0x3801, 0xbc},
288
289         {0x3503, 0x33},
290         {0x3500, 0x00},
291         {0x3501, 0x00},
292         {0x3502, 0x00},
293         {0x350a, 0x00},
294         {0x350b, 0x00},
295         {0x5001, 0x4e},
296         {0x5000, 0x5f},
297         {0x3008, 0x02},
298
299         {OV2710_TABLE_END, 0x0000}
300 };
301
302 enum {
303         OV2710_MODE_1920x1080,
304         OV2710_MODE_1280x720,
305 };
306
307
308 static struct ov2710_reg *mode_table[] = {
309         [OV2710_MODE_1920x1080] = mode_1920x1080,
310         [OV2710_MODE_1280x720] = mode_1280x720,
311 };
312
313 static inline void ov2710_get_frame_length_regs(struct ov2710_reg *regs,
314                                                 u32 frame_length)
315 {
316         regs->addr = 0x380e;
317         regs->val = (frame_length >> 8) & 0xff;
318         (regs + 1)->addr = 0x380f;
319         (regs + 1)->val = (frame_length) & 0xff;
320 }
321
322 static inline void ov2710_get_coarse_time_regs(struct ov2710_reg *regs,
323                                                u32 coarse_time)
324 {
325         regs->addr = 0x3500;
326         regs->val = (coarse_time >> 12) & 0xff;
327         (regs + 1)->addr = 0x3501;
328         (regs + 1)->val = (coarse_time >> 4) & 0xff;
329         (regs + 2)->addr = 0x3502;
330         (regs + 2)->val = (coarse_time & 0xf) << 4;
331 }
332
333 static inline void ov2710_get_gain_reg(struct ov2710_reg *regs, u16 gain)
334 {
335         regs->addr = 0x350b;
336         regs->val = gain;
337 }
338
339 static int ov2710_read_reg(struct i2c_client *client, u16 addr, u8 *val)
340 {
341         int err;
342         struct i2c_msg msg[2];
343         unsigned char data[3];
344
345         if (!client->adapter)
346                 return -ENODEV;
347
348         msg[0].addr = client->addr;
349         msg[0].flags = 0;
350         msg[0].len = 2;
351         msg[0].buf = data;
352
353         /* high byte goes out first */
354         data[0] = (u8) (addr >> 8);;
355         data[1] = (u8) (addr & 0xff);
356
357         msg[1].addr = client->addr;
358         msg[1].flags = I2C_M_RD;
359         msg[1].len = 1;
360         msg[1].buf = data + 2;
361
362         err = i2c_transfer(client->adapter, msg, 2);
363
364         if (err != 2)
365
366                 return -EINVAL;
367
368         *val = data[2];
369
370         return 0;
371 }
372
373 static int ov2710_write_reg(struct i2c_client *client, u16 addr, u8 val)
374 {
375         int err;
376         struct i2c_msg msg;
377         unsigned char data[3];
378         int retry = 0;
379
380         if (!client->adapter)
381                 return -ENODEV;
382
383         data[0] = (u8) (addr >> 8);;
384         data[1] = (u8) (addr & 0xff);
385         data[2] = (u8) (val & 0xff);
386
387         msg.addr = client->addr;
388         msg.flags = 0;
389         msg.len = 3;
390         msg.buf = data;
391
392         do {
393                 err = i2c_transfer(client->adapter, &msg, 1);
394                 if (err == 1)
395                         return 0;
396                 retry++;
397                 pr_err("ov2710: i2c transfer failed, retrying %x %x\n",
398                        addr, val);
399
400                 msleep(3);
401         } while (retry <= OV2710_MAX_RETRIES);
402
403         return err;
404 }
405
406 static int ov2710_write_bulk_reg(struct i2c_client *client, u8 *data, int len)
407 {
408         int err;
409         struct i2c_msg msg;
410
411         if (!client->adapter)
412                 return -ENODEV;
413
414         msg.addr = client->addr;
415         msg.flags = 0;
416         msg.len = len;
417         msg.buf = data;
418
419         err = i2c_transfer(client->adapter, &msg, 1);
420         if (err == 1)
421                 return 0;
422
423         pr_err("ov2710: i2c bulk transfer failed at %x\n",
424                 (int)data[0] << 8 | data[1]);
425
426         return err;
427 }
428
429 static int ov2710_write_table(struct ov2710_info *info,
430                               const struct ov2710_reg table[],
431                               const struct ov2710_reg override_list[],
432                               int num_override_regs)
433 {
434         int err;
435         const struct ov2710_reg *next, *n_next;
436         u8 *b_ptr = info->i2c_trans_buf;
437         unsigned int buf_filled = 0;
438         unsigned int i;
439         u16 val;
440
441         for (next = table; next->addr != OV2710_TABLE_END; next++) {
442                 if (next->addr == OV2710_TABLE_WAIT_MS) {
443                         msleep(next->val);
444                         continue;
445                 }
446
447                 val = next->val;
448                 /* When an override list is passed in, replace the reg */
449                 /* value to write if the reg is in the list            */
450                 if (override_list) {
451                         for (i = 0; i < num_override_regs; i++) {
452                                 if (next->addr == override_list[i].addr) {
453                                         val = override_list[i].val;
454                                         break;
455                                 }
456                         }
457                 }
458
459                 if (!buf_filled) {
460                         b_ptr = info->i2c_trans_buf;
461                         *b_ptr++ = next->addr >> 8;
462                         *b_ptr++ = next->addr & 0xff;
463                         buf_filled = 2;
464                 }
465                 *b_ptr++ = val;
466                 buf_filled++;
467
468                 n_next = next + 1;
469                 if (n_next->addr != OV2710_TABLE_END &&
470                         n_next->addr != OV2710_TABLE_WAIT_MS &&
471                         buf_filled < SIZEOF_I2C_TRANSBUF &&
472                         n_next->addr == next->addr + 1) {
473                         continue;
474                 }
475
476                 err = ov2710_write_bulk_reg(info->i2c_client,
477                         info->i2c_trans_buf, buf_filled);
478                 if (err)
479                         return err;
480                 buf_filled = 0;
481         }
482         return 0;
483 }
484
485 static int ov2710_set_mode(struct ov2710_info *info, struct ov2710_mode *mode)
486 {
487         int sensor_mode;
488         int err;
489         struct ov2710_reg reg_list[6];
490
491         pr_info("%s: xres %u yres %u framelength %u coarsetime %u gain %u\n",
492                 __func__, mode->xres, mode->yres, mode->frame_length,
493                 mode->coarse_time, mode->gain);
494
495         if (mode->xres == 1920 && mode->yres == 1080)
496                 sensor_mode = OV2710_MODE_1920x1080;
497         else if (mode->xres == 1280 && mode->yres == 720)
498                 sensor_mode = OV2710_MODE_1280x720;
499         else {
500                 pr_err("%s: invalid resolution supplied to set mode %d %d\n",
501                        __func__, mode->xres, mode->yres);
502                 return -EINVAL;
503         }
504
505         /* get a list of override regs for the asking frame length, */
506         /* coarse integration time, and gain.                       */
507         ov2710_get_frame_length_regs(reg_list, mode->frame_length);
508         ov2710_get_coarse_time_regs(reg_list + 2, mode->coarse_time);
509         ov2710_get_gain_reg(reg_list + 5, mode->gain);
510
511         err = ov2710_write_table(info, mode_table[sensor_mode],
512         reg_list, 6);
513         if (err)
514                 return err;
515
516         info->mode = sensor_mode;
517         return 0;
518 }
519
520 static int ov2710_set_frame_length(struct ov2710_info *info, u32 frame_length)
521 {
522         int ret;
523         struct ov2710_reg reg_list[2];
524         u8 *b_ptr = info->i2c_trans_buf;
525
526         ov2710_get_frame_length_regs(reg_list, frame_length);
527
528         *b_ptr++ = reg_list[0].addr >> 8;
529         *b_ptr++ = reg_list[0].addr & 0xff;
530         *b_ptr++ = reg_list[0].val & 0xff;
531         *b_ptr++ = reg_list[1].val & 0xff;
532         ret = ov2710_write_bulk_reg(info->i2c_client, info->i2c_trans_buf, 4);
533
534         return ret;
535 }
536
537 static int ov2710_set_coarse_time(struct ov2710_info *info, u32 coarse_time)
538 {
539         int ret;
540         struct ov2710_reg reg_list[3];
541         u8 *b_ptr = info->i2c_trans_buf;
542
543         ov2710_get_coarse_time_regs(reg_list, coarse_time);
544
545         *b_ptr++ = reg_list[0].addr >> 8;
546         *b_ptr++ = reg_list[0].addr & 0xff;
547         *b_ptr++ = reg_list[0].val & 0xff;
548         *b_ptr++ = reg_list[1].val & 0xff;
549         *b_ptr++ = reg_list[2].val & 0xff;
550         ret = ov2710_write_bulk_reg(info->i2c_client, info->i2c_trans_buf, 5);
551
552         return ret;
553 }
554
555 static int ov2710_set_gain(struct ov2710_info *info, u16 gain)
556 {
557         int ret;
558         struct ov2710_reg reg_list;
559
560         ov2710_get_gain_reg(&reg_list, gain);
561
562         ret = ov2710_write_reg(info->i2c_client, reg_list.addr, reg_list.val);
563
564         return ret;
565 }
566
567 static int ov2710_set_group_hold(struct ov2710_info *info, struct ov2710_ae *ae)
568 {
569         int ret;
570         int count = 0;
571         bool groupHoldEnabled = false;
572
573         if (ae->gain_enable)
574                 count++;
575         if (ae->coarse_time_enable)
576                 count++;
577         if (ae->frame_length_enable)
578                 count++;
579         if (count >= 2)
580                 groupHoldEnabled = true;
581
582         if (groupHoldEnabled) {
583                 ret = ov2710_write_reg(info->i2c_client, 0x3212, 0x01);
584                 if (ret)
585                         return ret;
586         }
587
588         if (ae->gain_enable)
589                 ov2710_set_gain(info, ae->gain);
590         if (ae->coarse_time_enable)
591                 ov2710_set_coarse_time(info, ae->coarse_time);
592         if (ae->frame_length_enable)
593                 ov2710_set_frame_length(info, ae->frame_length);
594
595         if (groupHoldEnabled) {
596                 ret = ov2710_write_reg(info->i2c_client, 0x3212, 0x11);
597                 if (ret)
598                         return ret;
599
600                 ret = ov2710_write_reg(info->i2c_client, 0x3212, 0xa1);
601                 if (ret)
602                         return ret;
603         }
604
605         return 0;
606 }
607
608
609 static int ov2710_get_status(struct ov2710_info *info, u8 *status)
610 {
611         int err;
612
613         *status = 0;
614         err = ov2710_read_reg(info->i2c_client, 0x002, status);
615         return err;
616 }
617
618
619 static long ov2710_ioctl(struct file *file,
620                          unsigned int cmd, unsigned long arg)
621 {
622         int err;
623         struct ov2710_info *info = file->private_data;
624
625         switch (cmd) {
626         case OV2710_IOCTL_SET_MODE:
627         {
628                 struct ov2710_mode mode;
629                 if (copy_from_user(&mode,
630                                    (const void __user *)arg,
631                                    sizeof(struct ov2710_mode))) {
632                         return -EFAULT;
633                 }
634
635                 return ov2710_set_mode(info, &mode);
636         }
637         case OV2710_IOCTL_SET_FRAME_LENGTH:
638                 return ov2710_set_frame_length(info, (u32)arg);
639         case OV2710_IOCTL_SET_COARSE_TIME:
640                 return ov2710_set_coarse_time(info, (u32)arg);
641         case OV2710_IOCTL_SET_GAIN:
642                 return ov2710_set_gain(info, (u16)arg);
643         case OV2710_IOCTL_SET_GROUP_HOLD:
644         {
645                 struct ov2710_ae ae;
646                 if (copy_from_user(&ae,
647                                 (const void __user *)arg,
648                                 sizeof(struct ov2710_ae))) {
649                         pr_info("%s %d\n", __func__, __LINE__);
650                         return -EFAULT;
651                 }
652                 return ov2710_set_group_hold(info, &ae);
653         }
654         case OV2710_IOCTL_GET_STATUS:
655         {
656                 u8 status;
657
658                 err = ov2710_get_status(info, &status);
659                 if (err)
660                         return err;
661                 if (copy_to_user((void __user *)arg, &status,
662                                  2)) {
663                         return -EFAULT;
664                 }
665                 return 0;
666         }
667         default:
668                 return -EINVAL;
669         }
670         return 0;
671 }
672
673 static struct ov2710_info *info;
674
675 static int ov2710_open(struct inode *inode, struct file *file)
676 {
677         u8 status;
678
679         file->private_data = info;
680         if (info->pdata && info->pdata->power_on)
681                 info->pdata->power_on();
682         ov2710_get_status(info, &status);
683         return 0;
684 }
685
686 int ov2710_release(struct inode *inode, struct file *file)
687 {
688         if (info->pdata && info->pdata->power_off)
689                 info->pdata->power_off();
690         file->private_data = NULL;
691         return 0;
692 }
693
694
695 static const struct file_operations ov2710_fileops = {
696         .owner = THIS_MODULE,
697         .open = ov2710_open,
698         .unlocked_ioctl = ov2710_ioctl,
699         .release = ov2710_release,
700 };
701
702 static struct miscdevice ov2710_device = {
703         .minor = MISC_DYNAMIC_MINOR,
704         .name = "ov2710",
705         .fops = &ov2710_fileops,
706 };
707
708 static int ov2710_probe(struct i2c_client *client,
709                         const struct i2c_device_id *id)
710 {
711         int err;
712
713         pr_info("ov2710: probing sensor.\n");
714
715         info = kzalloc(sizeof(struct ov2710_info), GFP_KERNEL);
716         if (!info) {
717                 pr_err("ov2710: Unable to allocate memory!\n");
718                 return -ENOMEM;
719         }
720
721         err = misc_register(&ov2710_device);
722         if (err) {
723                 pr_err("ov2710: Unable to register misc device!\n");
724                 kfree(info);
725                 return err;
726         }
727
728         info->pdata = client->dev.platform_data;
729         info->i2c_client = client;
730
731         i2c_set_clientdata(client, info);
732         return 0;
733 }
734
735 static int ov2710_remove(struct i2c_client *client)
736 {
737         struct ov2710_info *info;
738         info = i2c_get_clientdata(client);
739         misc_deregister(&ov2710_device);
740         kfree(info);
741         return 0;
742 }
743
744 static const struct i2c_device_id ov2710_id[] = {
745         { "ov2710", 0 },
746         { },
747 };
748
749 MODULE_DEVICE_TABLE(i2c, ov2710_id);
750
751 static struct i2c_driver ov2710_i2c_driver = {
752         .driver = {
753                 .name = "ov2710",
754                 .owner = THIS_MODULE,
755         },
756         .probe = ov2710_probe,
757         .remove = ov2710_remove,
758         .id_table = ov2710_id,
759 };
760
761 static int __init ov2710_init(void)
762 {
763         pr_info("ov2710 sensor driver loading\n");
764         return i2c_add_driver(&ov2710_i2c_driver);
765 }
766
767 static void __exit ov2710_exit(void)
768 {
769         i2c_del_driver(&ov2710_i2c_driver);
770 }
771
772 module_init(ov2710_init);
773 module_exit(ov2710_exit);
774 MODULE_LICENSE("GPL v2");