diff options
author | Robby Cai <R63905@freescale.com> | 2013-09-05 05:55:15 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:05:32 -0400 |
commit | baab9c6a093bf1a7b2a665ba1e9d22249956a623 (patch) | |
tree | ab3472a231b147740c4ceb761e68f8db744f295f | |
parent | 369ee2413b848dc22775816a453a0aad60420884 (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/Kconfig | 6 | ||||
-rw-r--r-- | drivers/media/platform/mxc/capture/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/platform/mxc/capture/ov5640.c | 1945 |
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 | |||
7 | config 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 @@ | |||
1 | obj-$(CONFIG_VIDEO_MXC_CSI_CAMERA) += fsl_csi.o csi_v4l2_capture.o | 1 | obj-$(CONFIG_VIDEO_MXC_CSI_CAMERA) += fsl_csi.o csi_v4l2_capture.o |
2 | obj-$(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 | |||
49 | enum 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 | |||
63 | enum ov5640_frame_rate { | ||
64 | ov5640_15_fps, | ||
65 | ov5640_30_fps | ||
66 | }; | ||
67 | |||
68 | static int ov5640_framerates[] = { | ||
69 | [ov5640_15_fps] = 15, | ||
70 | [ov5640_30_fps] = 30, | ||
71 | }; | ||
72 | |||
73 | struct reg_value { | ||
74 | u16 u16RegAddr; | ||
75 | u8 u8Val; | ||
76 | u8 u8Mask; | ||
77 | u32 u32Delay_ms; | ||
78 | }; | ||
79 | |||
80 | struct 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 | */ | ||
91 | static struct sensor_data ov5640_data; | ||
92 | static int pwn_gpio, rst_gpio; | ||
93 | static int prev_sysclk; | ||
94 | static int AE_Target = 52, night_mode; | ||
95 | static int prev_HTS; | ||
96 | static int AE_high, AE_low; | ||
97 | |||
98 | static 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 | |||
122 | static 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 | |||
211 | static 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 | |||
229 | static 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 | |||
247 | static 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 | |||
265 | static 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 | |||
283 | static 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 | |||
301 | static 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 | |||
319 | static 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 | |||
337 | static 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 | |||
355 | static 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 | |||
373 | static 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 | |||
391 | static 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 | |||
409 | static 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 | |||
427 | static 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 | |||
445 | static 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 | |||
464 | static 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 | |||
482 | static 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 | |||
500 | static 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 | |||
557 | static struct regulator *io_regulator; | ||
558 | static struct regulator *core_regulator; | ||
559 | static struct regulator *analog_regulator; | ||
560 | |||
561 | static int ov5640_probe(struct i2c_client *adapter, | ||
562 | const struct i2c_device_id *device_id); | ||
563 | static int ov5640_remove(struct i2c_client *client); | ||
564 | |||
565 | static s32 ov5640_read_reg(u16 reg, u8 *val); | ||
566 | static s32 ov5640_write_reg(u16 reg, u8 val); | ||
567 | |||
568 | static const struct i2c_device_id ov5640_id[] = { | ||
569 | {"ov5640", 0}, | ||
570 | {"ov564x", 0}, | ||
571 | {}, | ||
572 | }; | ||
573 | |||
574 | MODULE_DEVICE_TABLE(i2c, ov5640_id); | ||
575 | |||
576 | static 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 | |||
586 | static inline void ov5640_power_down(int enable) | ||
587 | { | ||
588 | gpio_set_value(pwn_gpio, enable); | ||
589 | |||
590 | msleep(2); | ||
591 | } | ||
592 | |||
593 | static 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 | |||
610 | static 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 | |||
668 | static 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 | |||
685 | static 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 | |||
710 | static 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 | */ | ||
729 | static 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 */ | ||
749 | static 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, ®val); | ||
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, ®val); | ||
768 | SysDiv = temp1 >> 4; | ||
769 | if (SysDiv == 0) | ||
770 | SysDiv = 16; | ||
771 | |||
772 | temp1 = ov5640_read_reg(0x3036, ®val); | ||
773 | Multiplier = temp1; | ||
774 | temp1 = ov5640_read_reg(0x3037, ®val); | ||
775 | PreDiv = temp1 & 0x0f; | ||
776 | Pll_rdiv = ((temp1 >> 4) & 0x01) + 1; | ||
777 | |||
778 | temp1 = ov5640_read_reg(0x3108, ®val); | ||
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 */ | ||
789 | static 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 */ | ||
800 | static 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 */ | ||
812 | static 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 */ | ||
825 | static int ov5640_get_shutter(void) | ||
826 | { | ||
827 | int shutter; | ||
828 | u8 regval; | ||
829 | |||
830 | shutter = (ov5640_read_reg(0x03500, ®val) & 0x0f); | ||
831 | |||
832 | shutter = (shutter<<8) + ov5640_read_reg(0x3501, ®val); | ||
833 | shutter = (shutter<<4) + (ov5640_read_reg(0x3502, ®val)>>4); | ||
834 | |||
835 | return shutter; | ||
836 | } | ||
837 | |||
838 | /* write shutter, in number of line period */ | ||
839 | static 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 */ | ||
859 | static int ov5640_get_gain16(void) | ||
860 | { | ||
861 | int gain16; | ||
862 | u8 regval; | ||
863 | |||
864 | gain16 = ov5640_read_reg(0x350a, ®val) & 0x03; | ||
865 | gain16 = (gain16<<8) + ov5640_read_reg(0x350b, ®val); | ||
866 | |||
867 | return gain16; | ||
868 | } | ||
869 | |||
870 | /* write gain, 16 = 1x */ | ||
871 | static 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 */ | ||
886 | static int ov5640_get_light_freq(void) | ||
887 | { | ||
888 | int temp, temp1, light_frequency; | ||
889 | u8 regval; | ||
890 | |||
891 | temp = ov5640_read_reg(0x3c01, ®val); | ||
892 | if (temp & 0x80) { | ||
893 | /* manual */ | ||
894 | temp1 = ov5640_read_reg(0x3c00, ®val); | ||
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, ®val); | ||
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 | |||
917 | static 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 */ | ||
950 | static 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 */ | ||
974 | static 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 */ | ||
995 | void 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 */ | ||
1011 | static 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 | } | ||
1043 | err: | ||
1044 | return retval; | ||
1045 | } | ||
1046 | |||
1047 | static 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; | ||
1081 | err: | ||
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 */ | ||
1087 | static 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 */ | ||
1146 | static 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); | ||
1264 | err: | ||
1265 | return retval; | ||
1266 | } | ||
1267 | |||
1268 | static 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 | |||
1294 | static 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 | */ | ||
1321 | static 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 | */ | ||
1360 | static 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 | */ | ||
1405 | static 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 | */ | ||
1490 | static 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 | */ | ||
1508 | static 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 | */ | ||
1550 | static 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 | */ | ||
1602 | static 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 | */ | ||
1626 | static 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 | */ | ||
1671 | static 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 | */ | ||
1684 | static 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 | */ | ||
1697 | static 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 | */ | ||
1714 | static 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 | */ | ||
1754 | static 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 | */ | ||
1763 | static 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 | |||
1794 | static struct v4l2_int_slave ov5640_slave = { | ||
1795 | .ioctls = ov5640_ioctl_desc, | ||
1796 | .num_ioctls = ARRAY_SIZE(ov5640_ioctl_desc), | ||
1797 | }; | ||
1798 | |||
1799 | static 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 | */ | ||
1814 | static 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 | */ | ||
1923 | static 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 | |||
1939 | module_i2c_driver(ov5640_i2c_driver); | ||
1940 | |||
1941 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
1942 | MODULE_DESCRIPTION("OV5640 Camera Driver"); | ||
1943 | MODULE_LICENSE("GPL"); | ||
1944 | MODULE_VERSION("1.0"); | ||
1945 | MODULE_ALIAS("CSI"); | ||