aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobby Cai <R63905@freescale.com>2013-09-05 05:55:15 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:05:32 -0400
commitbaab9c6a093bf1a7b2a665ba1e9d22249956a623 (patch)
treeab3472a231b147740c4ceb761e68f8db744f295f
parent369ee2413b848dc22775816a453a0aad60420884 (diff)
ENGR00275034-3 camera: ov5640: port the driver from 3.5.7
from commit 9293d3aaef4886eae9a500f0dabdcd2b679422b4 and commit cb1d78fc935fa00be03ae1a7b66477ad518a09dc, branch imx_3.5.7 This patch also does - use module_i2c_driver() instead of module_init/exit. - set the regulator reference pointer to NULL if it's not found in DT. Otherwise call regulator_enable/disable() on it will cause dump since the codes only check the regulator against NULL before the call and it's not NULL but still invalid. - drop gpo regulator definition and operations since it's of no use Signed-off-by: Robby Cai <R63905@freescale.com>
-rw-r--r--drivers/media/platform/mxc/capture/Kconfig6
-rw-r--r--drivers/media/platform/mxc/capture/Makefile1
-rw-r--r--drivers/media/platform/mxc/capture/ov5640.c1945
3 files changed, 1952 insertions, 0 deletions
diff --git a/drivers/media/platform/mxc/capture/Kconfig b/drivers/media/platform/mxc/capture/Kconfig
index 393bb7f70c34..762de46f7c62 100644
--- a/drivers/media/platform/mxc/capture/Kconfig
+++ b/drivers/media/platform/mxc/capture/Kconfig
@@ -3,3 +3,9 @@ config VIDEO_MXC_CSI_CAMERA
3 depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2 3 depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2
4 ---help--- 4 ---help---
5 This is the video4linux2 capture driver based on CSI module. 5 This is the video4linux2 capture driver based on CSI module.
6
7config MXC_CAMERA_OV5640
8 tristate "OmniVision ov5640 camera support"
9 depends on !VIDEO_MXC_EMMA_CAMERA && I2C
10 ---help---
11 If you plan to use the ov5640 Camera with your MXC system, say Y here.
diff --git a/drivers/media/platform/mxc/capture/Makefile b/drivers/media/platform/mxc/capture/Makefile
index b1ca343d82f1..2fc2596038f9 100644
--- a/drivers/media/platform/mxc/capture/Makefile
+++ b/drivers/media/platform/mxc/capture/Makefile
@@ -1 +1,2 @@
1obj-$(CONFIG_VIDEO_MXC_CSI_CAMERA) += fsl_csi.o csi_v4l2_capture.o 1obj-$(CONFIG_VIDEO_MXC_CSI_CAMERA) += fsl_csi.o csi_v4l2_capture.o
2obj-$(CONFIG_MXC_CAMERA_OV5640) += ov5640.o
diff --git a/drivers/media/platform/mxc/capture/ov5640.c b/drivers/media/platform/mxc/capture/ov5640.c
new file mode 100644
index 000000000000..cfb86ed3b565
--- /dev/null
+++ b/drivers/media/platform/mxc/capture/ov5640.c
@@ -0,0 +1,1945 @@
1/*
2 * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
3 */
4
5/*
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <linux/clk.h>
22#include <linux/delay.h>
23#include <linux/device.h>
24#include <linux/i2c.h>
25#include <linux/init.h>
26#include <linux/module.h>
27#include <linux/of_device.h>
28#include <linux/of_gpio.h>
29#include <linux/pinctrl/consumer.h>
30#include <linux/regulator/consumer.h>
31#include <media/v4l2-chip-ident.h>
32#include <media/v4l2-int-device.h>
33#include "mxc_v4l2_capture.h"
34
35#define OV5640_VOLTAGE_ANALOG 2800000
36#define OV5640_VOLTAGE_DIGITAL_CORE 1500000
37#define OV5640_VOLTAGE_DIGITAL_IO 1800000
38
39#define MIN_FPS 15
40#define MAX_FPS 30
41#define DEFAULT_FPS 30
42
43#define OV5640_XCLK_MIN 6000000
44#define OV5640_XCLK_MAX 24000000
45
46#define OV5640_CHIP_ID_HIGH_BYTE 0x300A
47#define OV5640_CHIP_ID_LOW_BYTE 0x300B
48
49enum ov5640_mode {
50 ov5640_mode_MIN = 0,
51 ov5640_mode_VGA_640_480 = 0,
52 ov5640_mode_QVGA_320_240 = 1,
53 ov5640_mode_NTSC_720_480 = 2,
54 ov5640_mode_PAL_720_576 = 3,
55 ov5640_mode_720P_1280_720 = 4,
56 ov5640_mode_1080P_1920_1080 = 5,
57 ov5640_mode_QSXGA_2592_1944 = 6,
58 ov5640_mode_QCIF_176_144 = 7,
59 ov5640_mode_XGA_1024_768 = 8,
60 ov5640_mode_MAX = 8
61};
62
63enum ov5640_frame_rate {
64 ov5640_15_fps,
65 ov5640_30_fps
66};
67
68static int ov5640_framerates[] = {
69 [ov5640_15_fps] = 15,
70 [ov5640_30_fps] = 30,
71};
72
73struct reg_value {
74 u16 u16RegAddr;
75 u8 u8Val;
76 u8 u8Mask;
77 u32 u32Delay_ms;
78};
79
80struct ov5640_mode_info {
81 enum ov5640_mode mode;
82 u32 width;
83 u32 height;
84 struct reg_value *init_data_ptr;
85 u32 init_data_size;
86};
87
88/*!
89 * Maintains the information on the current state of the sesor.
90 */
91static struct sensor_data ov5640_data;
92static int pwn_gpio, rst_gpio;
93static int prev_sysclk;
94static int AE_Target = 52, night_mode;
95static int prev_HTS;
96static int AE_high, AE_low;
97
98static struct reg_value ov5640_global_init_setting[] = {
99 {0x3008, 0x42, 0, 0},
100 {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0},
101 {0x3034, 0x1a, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0},
102 {0x3630, 0x36, 0, 0}, {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0},
103 {0x3633, 0x12, 0, 0}, {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0},
104 {0x3703, 0x5a, 0, 0}, {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0},
105 {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0},
106 {0x3906, 0x10, 0, 0}, {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0},
107 {0x3600, 0x08, 0, 0}, {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0},
108 {0x3620, 0x52, 0, 0}, {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0},
109 {0x3a13, 0x43, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0},
110 {0x3635, 0x13, 0, 0}, {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0},
111 {0x3622, 0x01, 0, 0}, {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0},
112 {0x3c05, 0x98, 0, 0}, {0x3c06, 0x00, 0, 0}, {0x3c07, 0x07, 0, 0},
113 {0x3c08, 0x00, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0},
114 {0x3c0b, 0x40, 0, 0}, {0x3810, 0x00, 0, 0}, {0x3811, 0x10, 0, 0},
115 {0x3812, 0x00, 0, 0}, {0x3708, 0x64, 0, 0}, {0x4001, 0x02, 0, 0},
116 {0x4005, 0x1a, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3004, 0xff, 0, 0},
117 {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0},
118 {0x501f, 0x00, 0, 0}, {0x440e, 0x00, 0, 0}, {0x5000, 0xa7, 0, 0},
119 {0x3008, 0x02, 0, 0},
120};
121
122static struct reg_value ov5640_init_setting_30fps_VGA[] = {
123 {0x3008, 0x42, 0, 0},
124 {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0},
125 {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, {0x3036, 0x46, 0, 0},
126 {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
127 {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
128 {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
129 {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
130 {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
131 {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
132 {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
133 {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
134 {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
135 {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
136 {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
137 {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
138 {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
139 {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
140 {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
141 {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
142 {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
143 {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
144 {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
145 {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
146 {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
147 {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
148 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
149 {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
150 {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
151 {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
152 {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
153 {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
154 {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0},
155 {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
156 {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
157 {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, {0x5000, 0xa7, 0, 0},
158 {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0xf2, 0, 0},
159 {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0},
160 {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, {0x5187, 0x09, 0, 0},
161 {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0}, {0x518a, 0x54, 0, 0},
162 {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x50, 0, 0},
163 {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0}, {0x5190, 0x46, 0, 0},
164 {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0},
165 {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0},
166 {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x6c, 0, 0},
167 {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x09, 0, 0},
168 {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0}, {0x5381, 0x1e, 0, 0},
169 {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, {0x5384, 0x0a, 0, 0},
170 {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, {0x5387, 0x7c, 0, 0},
171 {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, {0x538a, 0x01, 0, 0},
172 {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, {0x5301, 0x30, 0, 0},
173 {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, {0x5304, 0x08, 0, 0},
174 {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, {0x5307, 0x16, 0, 0},
175 {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, {0x530b, 0x04, 0, 0},
176 {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, {0x5481, 0x08, 0, 0},
177 {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, {0x5484, 0x51, 0, 0},
178 {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, {0x5487, 0x7d, 0, 0},
179 {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, {0x548a, 0x9a, 0, 0},
180 {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, {0x548d, 0xcd, 0, 0},
181 {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, {0x5490, 0x1d, 0, 0},
182 {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x10, 0, 0},
183 {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, {0x558b, 0xf8, 0, 0},
184 {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, {0x5802, 0x0f, 0, 0},
185 {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, {0x5805, 0x26, 0, 0},
186 {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, {0x5808, 0x05, 0, 0},
187 {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, {0x580b, 0x0d, 0, 0},
188 {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, {0x580e, 0x00, 0, 0},
189 {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, {0x5811, 0x09, 0, 0},
190 {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x00, 0, 0},
191 {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, {0x5817, 0x08, 0, 0},
192 {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, {0x581a, 0x05, 0, 0},
193 {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, {0x581d, 0x0e, 0, 0},
194 {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, {0x5820, 0x11, 0, 0},
195 {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, {0x5823, 0x28, 0, 0},
196 {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, {0x5826, 0x08, 0, 0},
197 {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, {0x5829, 0x26, 0, 0},
198 {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, {0x582c, 0x24, 0, 0},
199 {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, {0x582f, 0x22, 0, 0},
200 {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, {0x5832, 0x24, 0, 0},
201 {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, {0x5835, 0x22, 0, 0},
202 {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, {0x5838, 0x44, 0, 0},
203 {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, {0x583b, 0x28, 0, 0},
204 {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, {0x5025, 0x00, 0, 0},
205 {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, {0x3a1b, 0x30, 0, 0},
206 {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x14, 0, 0},
207 {0x3008, 0x02, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
208 {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
209};
210
211static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
212 {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
213 {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
214 {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
215 {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
216 {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
217 {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
218 {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
219 {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
220 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
221 {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
222 {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
223 {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
224 {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
225 {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
226 {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0},
227};
228
229static struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
230 {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
231 {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
232 {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
233 {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
234 {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0},
235 {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
236 {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
237 {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
238 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
239 {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
240 {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
241 {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
242 {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
243 {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
244 {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0},
245};
246
247static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
248 {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
249 {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
250 {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
251 {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
252 {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0},
253 {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0},
254 {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
255 {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
256 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
257 {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
258 {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
259 {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
260 {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
261 {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
262 {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
263};
264
265static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
266 {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
267 {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
268 {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
269 {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
270 {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0},
271 {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0},
272 {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
273 {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
274 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
275 {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
276 {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
277 {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
278 {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
279 {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
280 {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
281};
282
283static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
284 {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
285 {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
286 {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
287 {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0},
288 {0x3807, 0xd4, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
289 {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
290 {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
291 {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
292 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
293 {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
294 {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
295 {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
296 {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
297 {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
298 {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
299};
300
301static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
302 {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
303 {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
304 {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
305 {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0},
306 {0x3807, 0xd4, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
307 {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0},
308 {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
309 {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
310 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
311 {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
312 {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
313 {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
314 {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
315 {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
316 {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
317};
318
319static struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
320 {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
321 {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
322 {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
323 {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 0, 0}, {0x3806, 0x07, 0, 0},
324 {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
325 {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0},
326 {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
327 {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
328 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
329 {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
330 {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
331 {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
332 {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
333 {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
334 {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
335};
336
337static struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
338 {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
339 {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
340 {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
341 {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 0, 0}, {0x3806, 0x07, 0, 0},
342 {0x3807, 0x9b, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0},
343 {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0},
344 {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
345 {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
346 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
347 {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
348 {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
349 {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
350 {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
351 {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
352 {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
353};
354
355static struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
356 {0x3035, 0x21, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 0, 0},
357 {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
358 {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
359 {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
360 {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
361 {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
362 {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
363 {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3813, 0x04, 0, 0},
364 {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0},
365 {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0},
366 {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0},
367 {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0},
368 {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
369 {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
370 {0x3503, 0x00, 0, 0},
371};
372
373static struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
374 {0x3035, 0x41, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 0, 0},
375 {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
376 {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
377 {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
378 {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
379 {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
380 {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
381 {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3813, 0x04, 0, 0},
382 {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0},
383 {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0},
384 {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0},
385 {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0},
386 {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
387 {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
388 {0x3503, 0x00, 0, 0},
389};
390
391static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
392 {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
393 {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
394 {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
395 {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
396 {0x3807, 0x9b, 0, 0}, {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0},
397 {0x380a, 0x00, 0, 0}, {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0},
398 {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
399 {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
400 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
401 {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
402 {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
403 {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
404 {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
405 {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0},
406 {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
407};
408
409static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
410 {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
411 {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
412 {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
413 {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
414 {0x3807, 0x9b, 0, 0}, {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0},
415 {0x380a, 0x00, 0, 0}, {0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0},
416 {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
417 {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
418 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
419 {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
420 {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
421 {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
422 {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0},
423 {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
424 {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
425};
426
427static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
428 {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
429 {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
430 {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
431 {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
432 {0x3807, 0x9b, 0, 0}, {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0},
433 {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0},
434 {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
435 {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
436 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
437 {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
438 {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
439 {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
440 {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0},
441 {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
442 {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
443};
444
445static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
446 {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0},
447 {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0},
448 {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0},
449 {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
450 {0x3807, 0x9b, 0, 0}, {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0},
451 {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0},
452 {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0},
453 {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0},
454 {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0},
455 {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0},
456 {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
457 {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0},
458 {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0},
459 {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
460 {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0},
461};
462
463
464static struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
465 {0x3c07, 0x07, 0, 0}, {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
466 {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0},
467 {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0xee, 0, 0},
468 {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x05, 0, 0},
469 {0x3807, 0xc3, 0, 0}, {0x3808, 0x07, 0, 0}, {0x3809, 0x80, 0, 0},
470 {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0}, {0x380c, 0x0b, 0, 0},
471 {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0},
472 {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0},
473 {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0},
474 {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0},
475 {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
476 {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0},
477 {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0},
478 {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
479 {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
480};
481
482static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
483 {0x3c07, 0x07, 0, 0}, {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
484 {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0},
485 {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0},
486 {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0},
487 {0x3807, 0x9f, 0, 0}, {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0},
488 {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0},
489 {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0},
490 {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0},
491 {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0},
492 {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0},
493 {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0},
494 {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0},
495 {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0},
496 {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0},
497 {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0},
498};
499
500static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = {
501 {
502 {ov5640_mode_VGA_640_480, 640, 480,
503 ov5640_setting_15fps_VGA_640_480,
504 ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
505 {ov5640_mode_QVGA_320_240, 320, 240,
506 ov5640_setting_15fps_QVGA_320_240,
507 ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
508 {ov5640_mode_NTSC_720_480, 720, 480,
509 ov5640_setting_15fps_NTSC_720_480,
510 ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
511 {ov5640_mode_PAL_720_576, 720, 576,
512 ov5640_setting_15fps_PAL_720_576,
513 ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
514 {ov5640_mode_720P_1280_720, 1280, 720,
515 ov5640_setting_15fps_720P_1280_720,
516 ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
517 {ov5640_mode_1080P_1920_1080, 1920, 1080,
518 ov5640_setting_15fps_1080P_1920_1080,
519 ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
520 {ov5640_mode_QSXGA_2592_1944, 2592, 1944,
521 ov5640_setting_15fps_QSXGA_2592_1944,
522 ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
523 {ov5640_mode_QCIF_176_144, 176, 144,
524 ov5640_setting_15fps_QCIF_176_144,
525 ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
526 {ov5640_mode_XGA_1024_768, 1024, 768,
527 ov5640_setting_15fps_XGA_1024_768,
528 ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
529 },
530 {
531 {ov5640_mode_VGA_640_480, 640, 480,
532 ov5640_setting_30fps_VGA_640_480,
533 ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
534 {ov5640_mode_QVGA_320_240, 320, 240,
535 ov5640_setting_30fps_QVGA_320_240,
536 ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
537 {ov5640_mode_NTSC_720_480, 720, 480,
538 ov5640_setting_30fps_NTSC_720_480,
539 ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
540 {ov5640_mode_PAL_720_576, 720, 576,
541 ov5640_setting_30fps_PAL_720_576,
542 ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
543 {ov5640_mode_720P_1280_720, 1280, 720,
544 ov5640_setting_30fps_720P_1280_720,
545 ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
546 {ov5640_mode_1080P_1920_1080, 0, 0, NULL, 0},
547 {ov5640_mode_QSXGA_2592_1944, 0, 0, NULL, 0},
548 {ov5640_mode_QCIF_176_144, 176, 144,
549 ov5640_setting_30fps_QCIF_176_144,
550 ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
551 {ov5640_mode_XGA_1024_768, 1024, 768,
552 ov5640_setting_30fps_XGA_1024_768,
553 ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
554 },
555};
556
557static struct regulator *io_regulator;
558static struct regulator *core_regulator;
559static struct regulator *analog_regulator;
560
561static int ov5640_probe(struct i2c_client *adapter,
562 const struct i2c_device_id *device_id);
563static int ov5640_remove(struct i2c_client *client);
564
565static s32 ov5640_read_reg(u16 reg, u8 *val);
566static s32 ov5640_write_reg(u16 reg, u8 val);
567
568static const struct i2c_device_id ov5640_id[] = {
569 {"ov5640", 0},
570 {"ov564x", 0},
571 {},
572};
573
574MODULE_DEVICE_TABLE(i2c, ov5640_id);
575
576static struct i2c_driver ov5640_i2c_driver = {
577 .driver = {
578 .owner = THIS_MODULE,
579 .name = "ov5640",
580 },
581 .probe = ov5640_probe,
582 .remove = ov5640_remove,
583 .id_table = ov5640_id,
584};
585
586static inline void ov5640_power_down(int enable)
587{
588 gpio_set_value(pwn_gpio, enable);
589
590 msleep(2);
591}
592
593static inline void ov5640_reset(void)
594{
595 /* camera reset */
596 gpio_set_value(rst_gpio, 1);
597
598 /* camera power down */
599 gpio_set_value(pwn_gpio, 1);
600 msleep(5);
601 gpio_set_value(pwn_gpio, 0);
602 msleep(5);
603 gpio_set_value(rst_gpio, 0);
604 msleep(1);
605 gpio_set_value(rst_gpio, 1);
606 msleep(5);
607 gpio_set_value(pwn_gpio, 1);
608}
609
610static int ov5640_regulator_enable(struct device *dev)
611{
612 int ret = 0;
613
614 io_regulator = devm_regulator_get(dev, "DOVDD");
615 if (!IS_ERR(io_regulator)) {
616 regulator_set_voltage(io_regulator,
617 OV5640_VOLTAGE_DIGITAL_IO,
618 OV5640_VOLTAGE_DIGITAL_IO);
619 ret = regulator_enable(io_regulator);
620 if (ret) {
621 dev_err(dev, "set io voltage failed\n");
622 return ret;
623 } else {
624 dev_dbg(dev, "set io voltage ok\n");
625 }
626 } else {
627 io_regulator = NULL;
628 dev_warn(dev, "cannot get io voltage\n");
629 }
630
631 core_regulator = devm_regulator_get(dev, "DVDD");
632 if (!IS_ERR(core_regulator)) {
633 regulator_set_voltage(core_regulator,
634 OV5640_VOLTAGE_DIGITAL_CORE,
635 OV5640_VOLTAGE_DIGITAL_CORE);
636 ret = regulator_enable(core_regulator);
637 if (ret) {
638 dev_err(dev, "set core voltage failed\n");
639 return ret;
640 } else {
641 dev_dbg(dev, "set core voltage ok\n");
642 }
643 } else {
644 core_regulator = NULL;
645 dev_warn(dev, "cannot get core voltage\n");
646 }
647
648 analog_regulator = devm_regulator_get(dev, "AVDD");
649 if (!IS_ERR(analog_regulator)) {
650 regulator_set_voltage(analog_regulator,
651 OV5640_VOLTAGE_ANALOG,
652 OV5640_VOLTAGE_ANALOG);
653 ret = regulator_enable(analog_regulator);
654 if (ret) {
655 dev_err(dev, "set analog voltage failed\n");
656 return ret;
657 } else {
658 dev_dbg(dev, "set analog voltage ok\n");
659 }
660 } else {
661 analog_regulator = NULL;
662 dev_warn(dev, "cannot get analog voltage\n");
663 }
664
665 return ret;
666}
667
668static s32 ov5640_write_reg(u16 reg, u8 val)
669{
670 u8 au8Buf[3] = {0};
671
672 au8Buf[0] = reg >> 8;
673 au8Buf[1] = reg & 0xff;
674 au8Buf[2] = val;
675
676 if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
677 pr_err("%s:write reg error:reg=%x,val=%x\n",
678 __func__, reg, val);
679 return -1;
680 }
681
682 return 0;
683}
684
685static s32 ov5640_read_reg(u16 reg, u8 *val)
686{
687 u8 au8RegBuf[2] = {0};
688 u8 u8RdVal = 0;
689
690 au8RegBuf[0] = reg >> 8;
691 au8RegBuf[1] = reg & 0xff;
692
693 if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) {
694 pr_err("%s:write reg error:reg=%x\n",
695 __func__, reg);
696 return -1;
697 }
698
699 if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) {
700 pr_err("%s:read reg error:reg=%x,val=%x\n",
701 __func__, reg, u8RdVal);
702 return -1;
703 }
704
705 *val = u8RdVal;
706
707 return u8RdVal;
708}
709
710static void ov5640_soft_reset(void)
711{
712 /* sysclk from pad */
713 ov5640_write_reg(0x3103, 0x11);
714
715 /* software reset */
716 ov5640_write_reg(0x3008, 0x82);
717
718 /* delay at least 5ms */
719 msleep(10);
720}
721
722/* set sensor driver capability
723 * 0x302c[7:6] - strength
724 00 - 1x
725 01 - 2x
726 10 - 3x
727 11 - 4x
728 */
729static int ov5640_driver_capability(int strength)
730{
731 u8 temp = 0;
732
733 if (strength > 4 || strength < 1) {
734 pr_err("The valid driver capability of ov5640 is 1x~4x\n");
735 return -EINVAL;
736 }
737
738 ov5640_read_reg(0x302c, &temp);
739
740 temp &= ~0xc0; /* clear [7:6] */
741 temp |= ((strength - 1) << 6); /* set [7:6] */
742
743 ov5640_write_reg(0x302c, temp);
744
745 return 0;
746}
747
748/* calculate sysclk */
749static int ov5640_get_sysclk(void)
750{
751 int xvclk = ov5640_data.mclk / 10000;
752 int sysclk;
753 int temp1, temp2;
754 int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv, Bit_div2x, sclk_rdiv;
755 int sclk_rdiv_map[] = {1, 2, 4, 8};
756 u8 regval = 0;
757
758 temp1 = ov5640_read_reg(0x3034, &regval);
759 temp2 = temp1 & 0x0f;
760 if (temp2 == 8 || temp2 == 10) {
761 Bit_div2x = temp2 / 2;
762 } else {
763 pr_err("ov5640: unsupported bit mode %d\n", temp2);
764 return -1;
765 }
766
767 temp1 = ov5640_read_reg(0x3035, &regval);
768 SysDiv = temp1 >> 4;
769 if (SysDiv == 0)
770 SysDiv = 16;
771
772 temp1 = ov5640_read_reg(0x3036, &regval);
773 Multiplier = temp1;
774 temp1 = ov5640_read_reg(0x3037, &regval);
775 PreDiv = temp1 & 0x0f;
776 Pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
777
778 temp1 = ov5640_read_reg(0x3108, &regval);
779 temp2 = temp1 & 0x03;
780
781 sclk_rdiv = sclk_rdiv_map[temp2];
782 VCO = xvclk * Multiplier / PreDiv;
783 sysclk = VCO / SysDiv / Pll_rdiv * 2 / Bit_div2x / sclk_rdiv;
784
785 return sysclk;
786}
787
788/* read HTS from register settings */
789static int ov5640_get_HTS(void)
790{
791 int HTS;
792 u8 temp = 0;
793
794 HTS = ov5640_read_reg(0x380c, &temp);
795 HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp);
796 return HTS;
797}
798
799/* read VTS from register settings */
800static int ov5640_get_VTS(void)
801{
802 int VTS;
803 u8 temp = 0;
804
805 VTS = ov5640_read_reg(0x380e, &temp);
806 VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp);
807
808 return VTS;
809}
810
811/* write VTS to registers */
812static int ov5640_set_VTS(int VTS)
813{
814 int temp;
815
816 temp = VTS & 0xff;
817 ov5640_write_reg(0x380f, temp);
818
819 temp = VTS>>8;
820 ov5640_write_reg(0x380e, temp);
821 return 0;
822}
823
824/* read shutter, in number of line period */
825static int ov5640_get_shutter(void)
826{
827 int shutter;
828 u8 regval;
829
830 shutter = (ov5640_read_reg(0x03500, &regval) & 0x0f);
831
832 shutter = (shutter<<8) + ov5640_read_reg(0x3501, &regval);
833 shutter = (shutter<<4) + (ov5640_read_reg(0x3502, &regval)>>4);
834
835 return shutter;
836}
837
838/* write shutter, in number of line period */
839static int ov5640_set_shutter(int shutter)
840{
841 int temp;
842
843 shutter = shutter & 0xffff;
844 temp = shutter & 0x0f;
845 temp = temp<<4;
846 ov5640_write_reg(0x3502, temp);
847
848 temp = shutter & 0xfff;
849 temp = temp>>4;
850 ov5640_write_reg(0x3501, temp);
851
852 temp = shutter>>12;
853 ov5640_write_reg(0x3500, temp);
854
855 return 0;
856}
857
858/* read gain, 16 = 1x */
859static int ov5640_get_gain16(void)
860{
861 int gain16;
862 u8 regval;
863
864 gain16 = ov5640_read_reg(0x350a, &regval) & 0x03;
865 gain16 = (gain16<<8) + ov5640_read_reg(0x350b, &regval);
866
867 return gain16;
868}
869
870/* write gain, 16 = 1x */
871static int ov5640_set_gain16(int gain16)
872{
873 int temp;
874
875 gain16 = gain16 & 0x3ff;
876 temp = gain16 & 0xff;
877
878 ov5640_write_reg(0x350b, temp);
879 temp = gain16>>8;
880
881 ov5640_write_reg(0x350a, temp);
882 return 0;
883}
884
885/* get banding filter value */
886static int ov5640_get_light_freq(void)
887{
888 int temp, temp1, light_frequency;
889 u8 regval;
890
891 temp = ov5640_read_reg(0x3c01, &regval);
892 if (temp & 0x80) {
893 /* manual */
894 temp1 = ov5640_read_reg(0x3c00, &regval);
895 if (temp1 & 0x04) {
896 /* 50Hz */
897 light_frequency = 50;
898 } else {
899 /* 60Hz */
900 light_frequency = 60;
901 }
902 } else {
903 /* auto */
904 temp1 = ov5640_read_reg(0x3c0c, &regval);
905 if (temp1 & 0x01) {
906 /* 50Hz */
907 light_frequency = 50;
908 } else {
909 /* 60Hz */
910 light_frequency = 60;
911 }
912 }
913
914 return light_frequency;
915}
916
917static void ov5640_set_bandingfilter(void)
918{
919 int prev_VTS;
920 int band_step60, max_band60, band_step50, max_band50;
921
922 /* read preview PCLK */
923 prev_sysclk = ov5640_get_sysclk();
924
925 /* read preview HTS */
926 prev_HTS = ov5640_get_HTS();
927
928 /* read preview VTS */
929 prev_VTS = ov5640_get_VTS();
930
931 /* calculate banding filter */
932 /* 60Hz */
933 band_step60 = prev_sysclk * 100/prev_HTS * 100/120;
934 ov5640_write_reg(0x3a0a, (band_step60 >> 8));
935 ov5640_write_reg(0x3a0b, (band_step60 & 0xff));
936
937 max_band60 = (int)((prev_VTS-4)/band_step60);
938 ov5640_write_reg(0x3a0d, max_band60);
939
940 /* 50Hz */
941 band_step50 = prev_sysclk * 100/prev_HTS;
942 ov5640_write_reg(0x3a08, (band_step50 >> 8));
943 ov5640_write_reg(0x3a09, (band_step50 & 0xff));
944
945 max_band50 = (int)((prev_VTS-4)/band_step50);
946 ov5640_write_reg(0x3a0e, max_band50);
947}
948
949/* stable in high */
950static int ov5640_set_AE_target(int target)
951{
952 int fast_high, fast_low;
953
954 AE_low = target * 23 / 25; /* 0.92 */
955 AE_high = target * 27 / 25; /* 1.08 */
956 fast_high = AE_high << 1;
957
958 if (fast_high > 255)
959 fast_high = 255;
960 fast_low = AE_low >> 1;
961
962 ov5640_write_reg(0x3a0f, AE_high);
963 ov5640_write_reg(0x3a10, AE_low);
964 ov5640_write_reg(0x3a1b, AE_high);
965 ov5640_write_reg(0x3a1e, AE_low);
966 ov5640_write_reg(0x3a11, fast_high);
967 ov5640_write_reg(0x3a1f, fast_low);
968
969 return 0;
970}
971
972/* enable = 0 to turn off night mode
973 enable = 1 to turn on night mode */
974static int ov5640_set_night_mode(int enable)
975{
976 u8 mode;
977
978 ov5640_read_reg(0x3a00, &mode);
979
980 if (enable) {
981 /* night mode on */
982 mode |= 0x04;
983 ov5640_write_reg(0x3a00, mode);
984 } else {
985 /* night mode off */
986 mode &= 0xfb;
987 ov5640_write_reg(0x3a00, mode);
988 }
989
990 return 0;
991}
992
993/* enable = 0 to turn off AEC/AGC
994 enable = 1 to turn on AEC/AGC */
995void ov5640_turn_on_AE_AG(int enable)
996{
997 u8 ae_ag_ctrl;
998
999 ov5640_read_reg(0x3503, &ae_ag_ctrl);
1000 if (enable) {
1001 /* turn on auto AE/AG */
1002 ae_ag_ctrl = ae_ag_ctrl & ~(0x03);
1003 } else {
1004 /* turn off AE/AG */
1005 ae_ag_ctrl = ae_ag_ctrl | 0x03;
1006 }
1007 ov5640_write_reg(0x3503, ae_ag_ctrl);
1008}
1009
1010/* download ov5640 settings to sensor through i2c */
1011static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
1012{
1013 register u32 Delay_ms = 0;
1014 register u16 RegAddr = 0;
1015 register u8 Mask = 0;
1016 register u8 Val = 0;
1017 u8 RegVal = 0;
1018 int i, retval = 0;
1019
1020 for (i = 0; i < ArySize; ++i, ++pModeSetting) {
1021 Delay_ms = pModeSetting->u32Delay_ms;
1022 RegAddr = pModeSetting->u16RegAddr;
1023 Val = pModeSetting->u8Val;
1024 Mask = pModeSetting->u8Mask;
1025
1026 if (Mask) {
1027 retval = ov5640_read_reg(RegAddr, &RegVal);
1028 if (retval < 0)
1029 goto err;
1030
1031 RegVal &= ~(u8)Mask;
1032 Val &= Mask;
1033 Val |= RegVal;
1034 }
1035
1036 retval = ov5640_write_reg(RegAddr, Val);
1037 if (retval < 0)
1038 goto err;
1039
1040 if (Delay_ms)
1041 msleep(Delay_ms);
1042 }
1043err:
1044 return retval;
1045}
1046
1047static int ov5640_init_mode(void)
1048{
1049 struct reg_value *pModeSetting = NULL;
1050 int ArySize = 0, retval = 0;
1051
1052 ov5640_soft_reset();
1053
1054 pModeSetting = ov5640_global_init_setting;
1055 ArySize = ARRAY_SIZE(ov5640_global_init_setting);
1056 retval = ov5640_download_firmware(pModeSetting, ArySize);
1057 if (retval < 0)
1058 goto err;
1059
1060 pModeSetting = ov5640_init_setting_30fps_VGA;
1061 ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA);
1062 retval = ov5640_download_firmware(pModeSetting, ArySize);
1063 if (retval < 0)
1064 goto err;
1065
1066 /* change driver capability to 2x according to validation board.
1067 * if the image is not stable, please increase the driver strength.
1068 */
1069 ov5640_driver_capability(2);
1070 ov5640_set_bandingfilter();
1071 ov5640_set_AE_target(AE_Target);
1072 ov5640_set_night_mode(night_mode);
1073
1074 /* skip 9 vysnc: start capture at 10th vsync */
1075 msleep(300);
1076
1077 /* turn off night mode */
1078 night_mode = 0;
1079 ov5640_data.pix.width = 640;
1080 ov5640_data.pix.height = 480;
1081err:
1082 return retval;
1083}
1084
1085/* change to or back to subsampling mode set the mode directly
1086 * image size below 1280 * 960 is subsampling mode */
1087static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate,
1088 enum ov5640_mode mode)
1089{
1090 struct reg_value *pModeSetting = NULL;
1091 s32 ArySize = 0;
1092 int retval = 0;
1093
1094 if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) {
1095 pr_err("Wrong ov5640 mode detected!\n");
1096 return -1;
1097 }
1098
1099 pModeSetting = ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
1100 ArySize =
1101 ov5640_mode_info_data[frame_rate][mode].init_data_size;
1102
1103 ov5640_data.pix.width = ov5640_mode_info_data[frame_rate][mode].width;
1104 ov5640_data.pix.height = ov5640_mode_info_data[frame_rate][mode].height;
1105
1106 if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
1107 pModeSetting == NULL || ArySize == 0)
1108 return -EINVAL;
1109
1110 /* set ov5640 to subsampling mode */
1111 retval = ov5640_download_firmware(pModeSetting, ArySize);
1112
1113 /* turn on AE AG for subsampling mode, in case the firmware didn't */
1114 ov5640_turn_on_AE_AG(1);
1115
1116 /* calculate banding filter */
1117 ov5640_set_bandingfilter();
1118
1119 /* set AE target */
1120 ov5640_set_AE_target(AE_Target);
1121
1122 /* update night mode setting */
1123 ov5640_set_night_mode(night_mode);
1124
1125 /* skip 9 vysnc: start capture at 10th vsync */
1126 if (mode == ov5640_mode_XGA_1024_768 && frame_rate == ov5640_30_fps) {
1127 pr_warning("ov5640: actual frame rate of XGA is 22.5fps\n");
1128 /* 1/22.5 * 9*/
1129 msleep(400);
1130 return retval;
1131 }
1132
1133 if (frame_rate == ov5640_15_fps) {
1134 /* 1/15 * 9*/
1135 msleep(600);
1136 } else if (frame_rate == ov5640_30_fps) {
1137 /* 1/30 * 9*/
1138 msleep(300);
1139 }
1140
1141 return retval;
1142}
1143
1144/* change to scaling mode go through exposure calucation
1145 * image size above 1280 * 960 is scaling mode */
1146static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate,
1147 enum ov5640_mode mode)
1148{
1149 int prev_shutter, prev_gain16, average;
1150 int cap_shutter, cap_gain16;
1151 int cap_sysclk, cap_HTS, cap_VTS;
1152 int light_freq, cap_bandfilt, cap_maxband;
1153 long cap_gain16_shutter;
1154 u8 temp;
1155 struct reg_value *pModeSetting = NULL;
1156 s32 ArySize = 0;
1157 int retval = 0;
1158
1159 /* check if the input mode and frame rate is valid */
1160 pModeSetting =
1161 ov5640_mode_info_data[frame_rate][mode].init_data_ptr;
1162 ArySize =
1163 ov5640_mode_info_data[frame_rate][mode].init_data_size;
1164
1165 ov5640_data.pix.width =
1166 ov5640_mode_info_data[frame_rate][mode].width;
1167 ov5640_data.pix.height =
1168 ov5640_mode_info_data[frame_rate][mode].height;
1169
1170 if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 ||
1171 pModeSetting == NULL || ArySize == 0)
1172 return -EINVAL;
1173
1174 /* read preview shutter */
1175 prev_shutter = ov5640_get_shutter();
1176
1177 /* read preview gain */
1178 prev_gain16 = ov5640_get_gain16();
1179
1180 /* get average */
1181 average = ov5640_read_reg(0x56a1, &temp);
1182
1183 /* turn off night mode for capture */
1184 ov5640_set_night_mode(0);
1185
1186 /* turn off overlay */
1187 ov5640_write_reg(0x3022, 0x06);
1188
1189 /* Write capture setting */
1190 retval = ov5640_download_firmware(pModeSetting, ArySize);
1191 if (retval < 0)
1192 goto err;
1193
1194 /* turn off AE AG when capture image. */
1195 ov5640_turn_on_AE_AG(0);
1196
1197 /* read capture VTS */
1198 cap_VTS = ov5640_get_VTS();
1199 cap_HTS = ov5640_get_HTS();
1200 cap_sysclk = ov5640_get_sysclk();
1201
1202 /* calculate capture banding filter */
1203 light_freq = ov5640_get_light_freq();
1204 if (light_freq == 60) {
1205 /* 60Hz */
1206 cap_bandfilt = cap_sysclk * 100 / cap_HTS * 100 / 120;
1207 } else {
1208 /* 50Hz */
1209 cap_bandfilt = cap_sysclk * 100 / cap_HTS;
1210 }
1211 cap_maxband = (int)((cap_VTS - 4)/cap_bandfilt);
1212 /* calculate capture shutter/gain16 */
1213 if (average > AE_low && average < AE_high) {
1214 /* in stable range */
1215 cap_gain16_shutter =
1216 prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk *
1217 prev_HTS/cap_HTS * AE_Target / average;
1218 } else {
1219 cap_gain16_shutter =
1220 prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk *
1221 prev_HTS/cap_HTS;
1222 }
1223
1224 /* gain to shutter */
1225 if (cap_gain16_shutter < (cap_bandfilt * 16)) {
1226 /* shutter < 1/100 */
1227 cap_shutter = cap_gain16_shutter/16;
1228 if (cap_shutter < 1)
1229 cap_shutter = 1;
1230 cap_gain16 = cap_gain16_shutter/cap_shutter;
1231 if (cap_gain16 < 16)
1232 cap_gain16 = 16;
1233 } else {
1234 if (cap_gain16_shutter > (cap_bandfilt*cap_maxband*16)) {
1235 /* exposure reach max */
1236 cap_shutter = cap_bandfilt*cap_maxband;
1237 cap_gain16 = cap_gain16_shutter / cap_shutter;
1238 } else {
1239 /* 1/100 < cap_shutter =< max, cap_shutter = n/100 */
1240 cap_shutter =
1241 ((int)(cap_gain16_shutter/16/cap_bandfilt))
1242 * cap_bandfilt;
1243 cap_gain16 = cap_gain16_shutter / cap_shutter;
1244 }
1245 }
1246
1247 /* write capture gain */
1248 ov5640_set_gain16(cap_gain16);
1249
1250 /* write capture shutter */
1251 if (cap_shutter > (cap_VTS - 4)) {
1252 cap_VTS = cap_shutter + 4;
1253 ov5640_set_VTS(cap_VTS);
1254 }
1255
1256 ov5640_set_shutter(cap_shutter);
1257
1258 /* skip 2 vysnc: start capture at 3rd vsync
1259 * frame rate of QSXGA and 1080P is 7.5fps: 1/7.5 * 2
1260 */
1261 pr_warning("ov5640: the actual frame rate of %s is 7.5fps\n",
1262 mode == ov5640_mode_1080P_1920_1080 ? "1080P" : "QSXGA");
1263 msleep(267);
1264err:
1265 return retval;
1266}
1267
1268static int ov5640_change_mode(enum ov5640_frame_rate frame_rate,
1269 enum ov5640_mode mode)
1270{
1271 int retval = 0;
1272
1273 if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) {
1274 pr_err("Wrong ov5640 mode detected!\n");
1275 return -1;
1276 }
1277
1278 if (mode == ov5640_mode_1080P_1920_1080 ||
1279 mode == ov5640_mode_QSXGA_2592_1944) {
1280 /* change to scaling mode go through exposure calucation
1281 * image size above 1280 * 960 is scaling mode */
1282 retval = ov5640_change_mode_exposure_calc(frame_rate, mode);
1283 } else {
1284 /* change back to subsampling modem download firmware directly
1285 * image size below 1280 * 960 is subsampling mode */
1286 retval = ov5640_change_mode_direct(frame_rate, mode);
1287 }
1288
1289 return retval;
1290}
1291
1292/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
1293
1294static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
1295{
1296 if (s == NULL) {
1297 pr_err(" ERROR!! no slave device set!\n");
1298 return -1;
1299 }
1300
1301 memset(p, 0, sizeof(*p));
1302 p->u.bt656.clock_curr = ov5640_data.mclk;
1303 pr_debug(" clock_curr=mclk=%d\n", ov5640_data.mclk);
1304 p->if_type = V4L2_IF_TYPE_BT656;
1305 p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
1306 p->u.bt656.clock_min = OV5640_XCLK_MIN;
1307 p->u.bt656.clock_max = OV5640_XCLK_MAX;
1308 p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */
1309
1310 return 0;
1311}
1312
1313/*!
1314 * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
1315 * @s: pointer to standard V4L2 device structure
1316 * @on: indicates power mode (on or off)
1317 *
1318 * Turns the power on or off, depending on the value of on and returns the
1319 * appropriate error code.
1320 */
1321static int ioctl_s_power(struct v4l2_int_device *s, int on)
1322{
1323 struct sensor_data *sensor = s->priv;
1324
1325 if (on && !sensor->on) {
1326 if (io_regulator)
1327 if (regulator_enable(io_regulator) != 0)
1328 return -EIO;
1329 if (core_regulator)
1330 if (regulator_enable(core_regulator) != 0)
1331 return -EIO;
1332 if (analog_regulator)
1333 if (regulator_enable(analog_regulator) != 0)
1334 return -EIO;
1335 /* Make sure power on */
1336 ov5640_power_down(0);
1337 } else if (!on && sensor->on) {
1338 if (analog_regulator)
1339 regulator_disable(analog_regulator);
1340 if (core_regulator)
1341 regulator_disable(core_regulator);
1342 if (io_regulator)
1343 regulator_disable(io_regulator);
1344
1345 ov5640_power_down(1);
1346}
1347
1348 sensor->on = on;
1349
1350 return 0;
1351}
1352
1353/*!
1354 * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
1355 * @s: pointer to standard V4L2 device structure
1356 * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
1357 *
1358 * Returns the sensor's video CAPTURE parameters.
1359 */
1360static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
1361{
1362 struct sensor_data *sensor = s->priv;
1363 struct v4l2_captureparm *cparm = &a->parm.capture;
1364 int ret = 0;
1365
1366 switch (a->type) {
1367 /* This is the only case currently handled. */
1368 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1369 memset(a, 0, sizeof(*a));
1370 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1371 cparm->capability = sensor->streamcap.capability;
1372 cparm->timeperframe = sensor->streamcap.timeperframe;
1373 cparm->capturemode = sensor->streamcap.capturemode;
1374 ret = 0;
1375 break;
1376
1377 /* These are all the possible cases. */
1378 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1379 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
1380 case V4L2_BUF_TYPE_VBI_CAPTURE:
1381 case V4L2_BUF_TYPE_VBI_OUTPUT:
1382 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
1383 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
1384 ret = -EINVAL;
1385 break;
1386
1387 default:
1388 pr_debug(" type is unknown - %d\n", a->type);
1389 ret = -EINVAL;
1390 break;
1391 }
1392
1393 return ret;
1394}
1395
1396/*!
1397 * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
1398 * @s: pointer to standard V4L2 device structure
1399 * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
1400 *
1401 * Configures the sensor to use the input parameters, if possible. If
1402 * not possible, reverts to the old parameters and returns the
1403 * appropriate error code.
1404 */
1405static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
1406{
1407 struct sensor_data *sensor = s->priv;
1408 struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
1409 u32 tgt_fps; /* target frames per secound */
1410 enum ov5640_frame_rate frame_rate;
1411 int ret = 0;
1412
1413 /* Make sure power on */
1414 ov5640_power_down(0);
1415
1416 switch (a->type) {
1417 /* This is the only case currently handled. */
1418 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1419 /* Check that the new frame rate is allowed. */
1420 if ((timeperframe->numerator == 0) ||
1421 (timeperframe->denominator == 0)) {
1422 timeperframe->denominator = DEFAULT_FPS;
1423 timeperframe->numerator = 1;
1424 }
1425
1426 tgt_fps = timeperframe->denominator /
1427 timeperframe->numerator;
1428
1429 if (tgt_fps > MAX_FPS) {
1430 timeperframe->denominator = MAX_FPS;
1431 timeperframe->numerator = 1;
1432 } else if (tgt_fps < MIN_FPS) {
1433 timeperframe->denominator = MIN_FPS;
1434 timeperframe->numerator = 1;
1435 }
1436
1437 /* Actual frame rate we use */
1438 tgt_fps = timeperframe->denominator /
1439 timeperframe->numerator;
1440
1441 if (tgt_fps == 15)
1442 frame_rate = ov5640_15_fps;
1443 else if (tgt_fps == 30)
1444 frame_rate = ov5640_30_fps;
1445 else {
1446 pr_err(" The camera frame rate is not supported!\n");
1447 return -EINVAL;
1448 }
1449
1450 ret = ov5640_change_mode(frame_rate,
1451 a->parm.capture.capturemode);
1452 if (ret < 0)
1453 return ret;
1454
1455 sensor->streamcap.timeperframe = *timeperframe;
1456 sensor->streamcap.capturemode = a->parm.capture.capturemode;
1457
1458 break;
1459
1460 /* These are all the possible cases. */
1461 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1462 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
1463 case V4L2_BUF_TYPE_VBI_CAPTURE:
1464 case V4L2_BUF_TYPE_VBI_OUTPUT:
1465 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
1466 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
1467 pr_debug(" type is not " \
1468 "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
1469 a->type);
1470 ret = -EINVAL;
1471 break;
1472
1473 default:
1474 pr_debug(" type is unknown - %d\n", a->type);
1475 ret = -EINVAL;
1476 break;
1477 }
1478
1479 return ret;
1480}
1481
1482/*!
1483 * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
1484 * @s: pointer to standard V4L2 device structure
1485 * @f: pointer to standard V4L2 v4l2_format structure
1486 *
1487 * Returns the sensor's current pixel format in the v4l2_format
1488 * parameter.
1489 */
1490static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
1491{
1492 struct sensor_data *sensor = s->priv;
1493
1494 f->fmt.pix = sensor->pix;
1495
1496 return 0;
1497}
1498
1499/*!
1500 * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
1501 * @s: pointer to standard V4L2 device structure
1502 * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
1503 *
1504 * If the requested control is supported, returns the control's current
1505 * value from the video_control[] array. Otherwise, returns -EINVAL
1506 * if the control is not supported.
1507 */
1508static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
1509{
1510 int ret = 0;
1511
1512 switch (vc->id) {
1513 case V4L2_CID_BRIGHTNESS:
1514 vc->value = ov5640_data.brightness;
1515 break;
1516 case V4L2_CID_HUE:
1517 vc->value = ov5640_data.hue;
1518 break;
1519 case V4L2_CID_CONTRAST:
1520 vc->value = ov5640_data.contrast;
1521 break;
1522 case V4L2_CID_SATURATION:
1523 vc->value = ov5640_data.saturation;
1524 break;
1525 case V4L2_CID_RED_BALANCE:
1526 vc->value = ov5640_data.red;
1527 break;
1528 case V4L2_CID_BLUE_BALANCE:
1529 vc->value = ov5640_data.blue;
1530 break;
1531 case V4L2_CID_EXPOSURE:
1532 vc->value = ov5640_data.ae_mode;
1533 break;
1534 default:
1535 ret = -EINVAL;
1536 }
1537
1538 return ret;
1539}
1540
1541/*!
1542 * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
1543 * @s: pointer to standard V4L2 device structure
1544 * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
1545 *
1546 * If the requested control is supported, sets the control's current
1547 * value in HW (and updates the video_control[] array). Otherwise,
1548 * returns -EINVAL if the control is not supported.
1549 */
1550static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
1551{
1552 int retval = 0;
1553
1554 pr_debug("In ov5640:ioctl_s_ctrl %d\n",
1555 vc->id);
1556
1557 switch (vc->id) {
1558 case V4L2_CID_BRIGHTNESS:
1559 break;
1560 case V4L2_CID_CONTRAST:
1561 break;
1562 case V4L2_CID_SATURATION:
1563 break;
1564 case V4L2_CID_HUE:
1565 break;
1566 case V4L2_CID_AUTO_WHITE_BALANCE:
1567 break;
1568 case V4L2_CID_DO_WHITE_BALANCE:
1569 break;
1570 case V4L2_CID_RED_BALANCE:
1571 break;
1572 case V4L2_CID_BLUE_BALANCE:
1573 break;
1574 case V4L2_CID_GAMMA:
1575 break;
1576 case V4L2_CID_EXPOSURE:
1577 break;
1578 case V4L2_CID_AUTOGAIN:
1579 break;
1580 case V4L2_CID_GAIN:
1581 break;
1582 case V4L2_CID_HFLIP:
1583 break;
1584 case V4L2_CID_VFLIP:
1585 break;
1586 default:
1587 retval = -EPERM;
1588 break;
1589 }
1590
1591 return retval;
1592}
1593
1594/*!
1595 * ioctl_enum_framesizes - V4L2 sensor interface handler for
1596 * VIDIOC_ENUM_FRAMESIZES ioctl
1597 * @s: pointer to standard V4L2 device structure
1598 * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
1599 *
1600 * Return 0 if successful, otherwise -EINVAL.
1601 */
1602static int ioctl_enum_framesizes(struct v4l2_int_device *s,
1603 struct v4l2_frmsizeenum *fsize)
1604{
1605 if (fsize->index > ov5640_mode_MAX)
1606 return -EINVAL;
1607
1608 fsize->pixel_format = ov5640_data.pix.pixelformat;
1609 fsize->discrete.width =
1610 max(ov5640_mode_info_data[0][fsize->index].width,
1611 ov5640_mode_info_data[1][fsize->index].width);
1612 fsize->discrete.height =
1613 max(ov5640_mode_info_data[0][fsize->index].height,
1614 ov5640_mode_info_data[1][fsize->index].height);
1615 return 0;
1616}
1617
1618/*!
1619 * ioctl_enum_frameintervals - V4L2 sensor interface handler for
1620 * VIDIOC_ENUM_FRAMEINTERVALS ioctl
1621 * @s: pointer to standard V4L2 device structure
1622 * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
1623 *
1624 * Return 0 if successful, otherwise -EINVAL.
1625 */
1626static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
1627 struct v4l2_frmivalenum *fival)
1628{
1629 int i, j, count;
1630
1631 if (fival->index < 0 || fival->index > ov5640_mode_MAX)
1632 return -EINVAL;
1633
1634 if (fival->width == 0 || fival->height == 0 ||
1635 fival->pixel_format == 0) {
1636 pr_warning("Please assign pixelformat, width and height.\n");
1637 return -EINVAL;
1638 }
1639
1640 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
1641 fival->discrete.numerator = 1;
1642
1643 count = 0;
1644 for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++) {
1645 for (j = 0; j < (ov5640_mode_MAX + 1); j++) {
1646 if (fival->pixel_format == ov5640_data.pix.pixelformat
1647 && fival->width == ov5640_mode_info_data[i][j].width
1648 && fival->height == ov5640_mode_info_data[i][j].height
1649 && ov5640_mode_info_data[i][j].init_data_ptr != NULL) {
1650 count++;
1651 }
1652 if (fival->index == (count - 1)) {
1653 fival->discrete.denominator =
1654 ov5640_framerates[i];
1655 return 0;
1656 }
1657 }
1658 }
1659
1660 return -EINVAL;
1661}
1662
1663/*!
1664 * ioctl_g_chip_ident - V4L2 sensor interface handler for
1665 * VIDIOC_DBG_G_CHIP_IDENT ioctl
1666 * @s: pointer to standard V4L2 device structure
1667 * @id: pointer to int
1668 *
1669 * Return 0.
1670 */
1671static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
1672{
1673 ((struct v4l2_dbg_chip_ident *)id)->match.type =
1674 V4L2_CHIP_MATCH_I2C_DRIVER;
1675 strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov5640_camera");
1676
1677 return 0;
1678}
1679
1680/*!
1681 * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
1682 * @s: pointer to standard V4L2 device structure
1683 */
1684static int ioctl_init(struct v4l2_int_device *s)
1685{
1686
1687 return 0;
1688}
1689
1690/*!
1691 * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
1692 * @s: pointer to standard V4L2 device structure
1693 * @fmt: pointer to standard V4L2 fmt description structure
1694 *
1695 * Return 0.
1696 */
1697static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
1698 struct v4l2_fmtdesc *fmt)
1699{
1700 if (fmt->index > ov5640_mode_MAX)
1701 return -EINVAL;
1702
1703 fmt->pixelformat = ov5640_data.pix.pixelformat;
1704
1705 return 0;
1706}
1707
1708/*!
1709 * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
1710 * @s: pointer to standard V4L2 device structure
1711 *
1712 * Initialise the device when slave attaches to the master.
1713 */
1714static int ioctl_dev_init(struct v4l2_int_device *s)
1715{
1716 struct sensor_data *sensor = s->priv;
1717 u32 tgt_xclk; /* target xclk */
1718 u32 tgt_fps; /* target frames per secound */
1719 enum ov5640_frame_rate frame_rate;
1720 int ret;
1721
1722 ov5640_data.on = true;
1723
1724 /* mclk */
1725 tgt_xclk = ov5640_data.mclk;
1726 tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX);
1727 tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN);
1728 ov5640_data.mclk = tgt_xclk;
1729
1730 pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
1731 clk_set_rate(ov5640_data.sensor_clk, ov5640_data.mclk);
1732
1733 /* Default camera frame rate is set in probe */
1734 tgt_fps = sensor->streamcap.timeperframe.denominator /
1735 sensor->streamcap.timeperframe.numerator;
1736
1737 if (tgt_fps == 15)
1738 frame_rate = ov5640_15_fps;
1739 else if (tgt_fps == 30)
1740 frame_rate = ov5640_30_fps;
1741 else
1742 return -EINVAL; /* Only support 15fps or 30fps now. */
1743
1744 ret = ov5640_init_mode();
1745 return ret;
1746}
1747
1748/*!
1749 * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
1750 * @s: pointer to standard V4L2 device structure
1751 *
1752 * Delinitialise the device when slave detaches to the master.
1753 */
1754static int ioctl_dev_exit(struct v4l2_int_device *s)
1755{
1756 return 0;
1757}
1758
1759/*!
1760 * This structure defines all the ioctls for this module and links them to the
1761 * enumeration.
1762 */
1763static struct v4l2_int_ioctl_desc ov5640_ioctl_desc[] = {
1764 { vidioc_int_dev_init_num,
1765 (v4l2_int_ioctl_func *)ioctl_dev_init },
1766 { vidioc_int_dev_exit_num,
1767 ioctl_dev_exit},
1768 { vidioc_int_s_power_num,
1769 (v4l2_int_ioctl_func *)ioctl_s_power },
1770 { vidioc_int_g_ifparm_num,
1771 (v4l2_int_ioctl_func *)ioctl_g_ifparm },
1772 { vidioc_int_init_num,
1773 (v4l2_int_ioctl_func *)ioctl_init },
1774 { vidioc_int_enum_fmt_cap_num,
1775 (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
1776 { vidioc_int_g_fmt_cap_num,
1777 (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
1778 { vidioc_int_g_parm_num,
1779 (v4l2_int_ioctl_func *)ioctl_g_parm },
1780 { vidioc_int_s_parm_num,
1781 (v4l2_int_ioctl_func *)ioctl_s_parm },
1782 { vidioc_int_g_ctrl_num,
1783 (v4l2_int_ioctl_func *)ioctl_g_ctrl },
1784 { vidioc_int_s_ctrl_num,
1785 (v4l2_int_ioctl_func *)ioctl_s_ctrl },
1786 { vidioc_int_enum_framesizes_num,
1787 (v4l2_int_ioctl_func *)ioctl_enum_framesizes },
1788 { vidioc_int_enum_frameintervals_num,
1789 (v4l2_int_ioctl_func *)ioctl_enum_frameintervals },
1790 { vidioc_int_g_chip_ident_num,
1791 (v4l2_int_ioctl_func *)ioctl_g_chip_ident },
1792};
1793
1794static struct v4l2_int_slave ov5640_slave = {
1795 .ioctls = ov5640_ioctl_desc,
1796 .num_ioctls = ARRAY_SIZE(ov5640_ioctl_desc),
1797};
1798
1799static struct v4l2_int_device ov5640_int_device = {
1800 .module = THIS_MODULE,
1801 .name = "ov5640",
1802 .type = v4l2_int_type_slave,
1803 .u = {
1804 .slave = &ov5640_slave,
1805 },
1806};
1807
1808/*!
1809 * ov5640 I2C probe function
1810 *
1811 * @param adapter struct i2c_adapter *
1812 * @return Error code indicating success or failure
1813 */
1814static int ov5640_probe(struct i2c_client *client,
1815 const struct i2c_device_id *id)
1816{
1817 struct pinctrl *pinctrl;
1818 struct device *dev = &client->dev;
1819 int retval;
1820 u8 chip_id_high, chip_id_low;
1821
1822 /* ov5640 pinctrl */
1823 pinctrl = devm_pinctrl_get_select_default(dev);
1824 if (IS_ERR(pinctrl)) {
1825 dev_err(dev, "setup pinctrl failed\n");
1826 return PTR_ERR(pinctrl);
1827 }
1828
1829 /* request power down pin */
1830 pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
1831 if (!gpio_is_valid(pwn_gpio)) {
1832 dev_err(dev, "no sensor pwdn pin available\n");
1833 return -ENODEV;
1834 }
1835 retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
1836 "ov5640_pwdn");
1837 if (retval < 0)
1838 return retval;
1839
1840 /* request reset pin */
1841 rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
1842 if (!gpio_is_valid(rst_gpio)) {
1843 dev_err(dev, "no sensor reset pin available\n");
1844 return -EINVAL;
1845 }
1846 retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
1847 "ov5640_reset");
1848 if (retval < 0)
1849 return retval;
1850
1851 /* Set initial values for the sensor struct. */
1852 memset(&ov5640_data, 0, sizeof(ov5640_data));
1853 ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
1854 if (IS_ERR(ov5640_data.sensor_clk)) {
1855 dev_err(dev, "get mclk failed\n");
1856 return PTR_ERR(ov5640_data.sensor_clk);
1857 }
1858
1859 retval = of_property_read_u32(dev->of_node, "mclk",
1860 &ov5640_data.mclk);
1861 if (retval) {
1862 dev_err(dev, "mclk frequency is invalid\n");
1863 return retval;
1864 }
1865
1866 retval = of_property_read_u32(dev->of_node, "mclk_source",
1867 (u32 *) &(ov5640_data.mclk_source));
1868 if (retval) {
1869 dev_err(dev, "mclk_source invalid\n");
1870 return retval;
1871 }
1872
1873 retval = of_property_read_u32(dev->of_node, "csi_id",
1874 &(ov5640_data.csi));
1875 if (retval) {
1876 dev_err(dev, "csi_id invalid\n");
1877 return retval;
1878 }
1879
1880 ov5640_data.io_init = ov5640_reset;
1881 ov5640_data.i2c_client = client;
1882 ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;
1883 ov5640_data.pix.width = 640;
1884 ov5640_data.pix.height = 480;
1885 ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
1886 V4L2_CAP_TIMEPERFRAME;
1887 ov5640_data.streamcap.capturemode = 0;
1888 ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
1889 ov5640_data.streamcap.timeperframe.numerator = 1;
1890
1891 ov5640_regulator_enable(&client->dev);
1892
1893 ov5640_reset();
1894
1895 ov5640_power_down(0);
1896
1897 retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high);
1898 if (retval < 0 || chip_id_high != 0x56) {
1899 pr_warning("camera ov5640 is not found\n");
1900 return -ENODEV;
1901 }
1902 retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low);
1903 if (retval < 0 || chip_id_low != 0x40) {
1904 pr_warning("camera ov5640 is not found\n");
1905 return -ENODEV;
1906 }
1907
1908 ov5640_power_down(1);
1909
1910 ov5640_int_device.priv = &ov5640_data;
1911 retval = v4l2_int_device_register(&ov5640_int_device);
1912
1913 pr_info("camera ov5640 is found\n");
1914 return retval;
1915}
1916
1917/*!
1918 * ov5640 I2C detach function
1919 *
1920 * @param client struct i2c_client *
1921 * @return Error code indicating success or failure
1922 */
1923static int ov5640_remove(struct i2c_client *client)
1924{
1925 v4l2_int_device_unregister(&ov5640_int_device);
1926
1927 if (analog_regulator)
1928 regulator_disable(analog_regulator);
1929
1930 if (core_regulator)
1931 regulator_disable(core_regulator);
1932
1933 if (io_regulator)
1934 regulator_disable(io_regulator);
1935
1936 return 0;
1937}
1938
1939module_i2c_driver(ov5640_i2c_driver);
1940
1941MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1942MODULE_DESCRIPTION("OV5640 Camera Driver");
1943MODULE_LICENSE("GPL");
1944MODULE_VERSION("1.0");
1945MODULE_ALIAS("CSI");