1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) 2020 Bootlin |
4 | * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com> |
5 | */ |
6 | |
7 | #include <linux/clk.h> |
8 | #include <linux/delay.h> |
9 | #include <linux/device.h> |
10 | #include <linux/i2c.h> |
11 | #include <linux/module.h> |
12 | #include <linux/of_graph.h> |
13 | #include <linux/pm_runtime.h> |
14 | #include <linux/regulator/consumer.h> |
15 | #include <linux/videodev2.h> |
16 | #include <media/v4l2-ctrls.h> |
17 | #include <media/v4l2-device.h> |
18 | #include <media/v4l2-fwnode.h> |
19 | #include <media/v4l2-image-sizes.h> |
20 | #include <media/v4l2-mediabus.h> |
21 | |
22 | /* Clock rate */ |
23 | |
24 | #define OV5648_XVCLK_RATE 24000000 |
25 | |
26 | /* Register definitions */ |
27 | |
28 | /* System */ |
29 | |
30 | #define OV5648_SW_STANDBY_REG 0x100 |
31 | #define OV5648_SW_STANDBY_STREAM_ON BIT(0) |
32 | |
33 | #define OV5648_SW_RESET_REG 0x103 |
34 | #define OV5648_SW_RESET_RESET BIT(0) |
35 | |
36 | #define OV5648_PAD_OEN0_REG 0x3000 |
37 | #define OV5648_PAD_OEN1_REG 0x3001 |
38 | #define OV5648_PAD_OEN2_REG 0x3002 |
39 | #define OV5648_PAD_OUT0_REG 0x3008 |
40 | #define OV5648_PAD_OUT1_REG 0x3009 |
41 | |
42 | #define OV5648_CHIP_ID_H_REG 0x300a |
43 | #define OV5648_CHIP_ID_H_VALUE 0x56 |
44 | #define OV5648_CHIP_ID_L_REG 0x300b |
45 | #define OV5648_CHIP_ID_L_VALUE 0x48 |
46 | |
47 | #define OV5648_PAD_OUT2_REG 0x300d |
48 | #define OV5648_PAD_SEL0_REG 0x300e |
49 | #define OV5648_PAD_SEL1_REG 0x300f |
50 | #define OV5648_PAD_SEL2_REG 0x3010 |
51 | #define OV5648_PAD_PK_REG 0x3011 |
52 | #define OV5648_PAD_PK_PD_DATO_EN BIT(7) |
53 | #define OV5648_PAD_PK_DRIVE_STRENGTH_1X (0 << 5) |
54 | #define OV5648_PAD_PK_DRIVE_STRENGTH_2X (2 << 5) |
55 | #define OV5648_PAD_PK_FREX_N BIT(1) |
56 | |
57 | #define OV5648_A_PWC_PK_O0_REG 0x3013 |
58 | #define OV5648_A_PWC_PK_O0_BP_REGULATOR_N BIT(3) |
59 | #define OV5648_A_PWC_PK_O1_REG 0x3014 |
60 | |
61 | #define OV5648_MIPI_PHY0_REG 0x3016 |
62 | #define OV5648_MIPI_PHY1_REG 0x3017 |
63 | #define OV5648_MIPI_SC_CTRL0_REG 0x3018 |
64 | #define OV5648_MIPI_SC_CTRL0_MIPI_LANES(v) (((v) << 5) & GENMASK(7, 5)) |
65 | #define OV5648_MIPI_SC_CTRL0_PHY_HS_TX_PD BIT(4) |
66 | #define OV5648_MIPI_SC_CTRL0_PHY_LP_RX_PD BIT(3) |
67 | #define OV5648_MIPI_SC_CTRL0_MIPI_EN BIT(2) |
68 | #define OV5648_MIPI_SC_CTRL0_MIPI_SUSP BIT(1) |
69 | #define OV5648_MIPI_SC_CTRL0_LANE_DIS_OP BIT(0) |
70 | #define OV5648_MIPI_SC_CTRL1_REG 0x3019 |
71 | #define OV5648_MISC_CTRL0_REG 0x3021 |
72 | #define OV5648_MIPI_SC_CTRL2_REG 0x3022 |
73 | #define OV5648_SUB_ID_REG 0x302a |
74 | |
75 | #define OV5648_PLL_CTRL0_REG 0x3034 |
76 | #define OV5648_PLL_CTRL0_PLL_CHARGE_PUMP(v) (((v) << 4) & GENMASK(6, 4)) |
77 | #define OV5648_PLL_CTRL0_BITS(v) ((v) & GENMASK(3, 0)) |
78 | #define OV5648_PLL_CTRL1_REG 0x3035 |
79 | #define OV5648_PLL_CTRL1_SYS_DIV(v) (((v) << 4) & GENMASK(7, 4)) |
80 | #define OV5648_PLL_CTRL1_MIPI_DIV(v) ((v) & GENMASK(3, 0)) |
81 | #define OV5648_PLL_MUL_REG 0x3036 |
82 | #define OV5648_PLL_MUL(v) ((v) & GENMASK(7, 0)) |
83 | #define OV5648_PLL_DIV_REG 0x3037 |
84 | #define OV5648_PLL_DIV_ROOT_DIV(v) ((((v) - 1) << 4) & BIT(4)) |
85 | #define OV5648_PLL_DIV_PLL_PRE_DIV(v) ((v) & GENMASK(3, 0)) |
86 | #define OV5648_PLL_DEBUG_REG 0x3038 |
87 | #define OV5648_PLL_BYPASS_REG 0x3039 |
88 | |
89 | #define OV5648_PLLS_BYPASS_REG 0x303a |
90 | #define OV5648_PLLS_MUL_REG 0x303b |
91 | #define OV5648_PLLS_MUL(v) ((v) & GENMASK(4, 0)) |
92 | #define OV5648_PLLS_CTRL_REG 0x303c |
93 | #define OV5648_PLLS_CTRL_PLL_CHARGE_PUMP(v) (((v) << 4) & GENMASK(6, 4)) |
94 | #define OV5648_PLLS_CTRL_SYS_DIV(v) ((v) & GENMASK(3, 0)) |
95 | #define OV5648_PLLS_DIV_REG 0x303d |
96 | #define OV5648_PLLS_DIV_PLLS_PRE_DIV(v) (((v) << 4) & GENMASK(5, 4)) |
97 | #define OV5648_PLLS_DIV_PLLS_DIV_R(v) ((((v) - 1) << 2) & BIT(2)) |
98 | #define OV5648_PLLS_DIV_PLLS_SEL_DIV(v) ((v) & GENMASK(1, 0)) |
99 | |
100 | #define OV5648_SRB_CTRL_REG 0x3106 |
101 | #define OV5648_SRB_CTRL_SCLK_DIV(v) (((v) << 2) & GENMASK(3, 2)) |
102 | #define OV5648_SRB_CTRL_RESET_ARBITER_EN BIT(1) |
103 | #define OV5648_SRB_CTRL_SCLK_ARBITER_EN BIT(0) |
104 | |
105 | /* Group Hold */ |
106 | |
107 | #define OV5648_GROUP_ADR0_REG 0x3200 |
108 | #define OV5648_GROUP_ADR1_REG 0x3201 |
109 | #define OV5648_GROUP_ADR2_REG 0x3202 |
110 | #define OV5648_GROUP_ADR3_REG 0x3203 |
111 | #define OV5648_GROUP_LEN0_REG 0x3204 |
112 | #define OV5648_GROUP_LEN1_REG 0x3205 |
113 | #define OV5648_GROUP_LEN2_REG 0x3206 |
114 | #define OV5648_GROUP_LEN3_REG 0x3207 |
115 | #define OV5648_GROUP_ACCESS_REG 0x3208 |
116 | |
117 | /* Exposure/gain/banding */ |
118 | |
119 | #define OV5648_EXPOSURE_CTRL_HH_REG 0x3500 |
120 | #define OV5648_EXPOSURE_CTRL_HH(v) (((v) & GENMASK(19, 16)) >> 16) |
121 | #define OV5648_EXPOSURE_CTRL_HH_VALUE(v) (((v) << 16) & GENMASK(19, 16)) |
122 | #define OV5648_EXPOSURE_CTRL_H_REG 0x3501 |
123 | #define OV5648_EXPOSURE_CTRL_H(v) (((v) & GENMASK(15, 8)) >> 8) |
124 | #define OV5648_EXPOSURE_CTRL_H_VALUE(v) (((v) << 8) & GENMASK(15, 8)) |
125 | #define OV5648_EXPOSURE_CTRL_L_REG 0x3502 |
126 | #define OV5648_EXPOSURE_CTRL_L(v) ((v) & GENMASK(7, 0)) |
127 | #define OV5648_EXPOSURE_CTRL_L_VALUE(v) ((v) & GENMASK(7, 0)) |
128 | #define OV5648_MANUAL_CTRL_REG 0x3503 |
129 | #define OV5648_MANUAL_CTRL_FRAME_DELAY(v) (((v) << 4) & GENMASK(5, 4)) |
130 | #define OV5648_MANUAL_CTRL_AGC_MANUAL_EN BIT(1) |
131 | #define OV5648_MANUAL_CTRL_AEC_MANUAL_EN BIT(0) |
132 | #define OV5648_GAIN_CTRL_H_REG 0x350a |
133 | #define OV5648_GAIN_CTRL_H(v) (((v) & GENMASK(9, 8)) >> 8) |
134 | #define OV5648_GAIN_CTRL_H_VALUE(v) (((v) << 8) & GENMASK(9, 8)) |
135 | #define OV5648_GAIN_CTRL_L_REG 0x350b |
136 | #define OV5648_GAIN_CTRL_L(v) ((v) & GENMASK(7, 0)) |
137 | #define OV5648_GAIN_CTRL_L_VALUE(v) ((v) & GENMASK(7, 0)) |
138 | |
139 | #define OV5648_ANALOG_CTRL0_REG_BASE 0x3600 |
140 | #define OV5648_ANALOG_CTRL1_REG_BASE 0x3700 |
141 | |
142 | #define OV5648_AEC_CTRL0_REG 0x3a00 |
143 | #define OV5648_AEC_CTRL0_DEBUG BIT(6) |
144 | #define OV5648_AEC_CTRL0_DEBAND_EN BIT(5) |
145 | #define OV5648_AEC_CTRL0_DEBAND_LOW_LIMIT_EN BIT(4) |
146 | #define OV5648_AEC_CTRL0_START_SEL_EN BIT(3) |
147 | #define OV5648_AEC_CTRL0_NIGHT_MODE_EN BIT(2) |
148 | #define OV5648_AEC_CTRL0_FREEZE_EN BIT(0) |
149 | #define OV5648_EXPOSURE_MIN_REG 0x3a01 |
150 | #define OV5648_EXPOSURE_MAX_60_H_REG 0x3a02 |
151 | #define OV5648_EXPOSURE_MAX_60_L_REG 0x3a03 |
152 | #define OV5648_AEC_CTRL5_REG 0x3a05 |
153 | #define OV5648_AEC_CTRL6_REG 0x3a06 |
154 | #define OV5648_AEC_CTRL7_REG 0x3a07 |
155 | #define OV5648_BANDING_STEP_50_H_REG 0x3a08 |
156 | #define OV5648_BANDING_STEP_50_L_REG 0x3a09 |
157 | #define OV5648_BANDING_STEP_60_H_REG 0x3a0a |
158 | #define OV5648_BANDING_STEP_60_L_REG 0x3a0b |
159 | #define OV5648_AEC_CTRLC_REG 0x3a0c |
160 | #define OV5648_BANDING_MAX_60_REG 0x3a0d |
161 | #define OV5648_BANDING_MAX_50_REG 0x3a0e |
162 | #define OV5648_WPT_REG 0x3a0f |
163 | #define OV5648_BPT_REG 0x3a10 |
164 | #define OV5648_VPT_HIGH_REG 0x3a11 |
165 | #define OV5648_AVG_MANUAL_REG 0x3a12 |
166 | #define OV5648_PRE_GAIN_REG 0x3a13 |
167 | #define OV5648_EXPOSURE_MAX_50_H_REG 0x3a14 |
168 | #define OV5648_EXPOSURE_MAX_50_L_REG 0x3a15 |
169 | #define OV5648_GAIN_BASE_NIGHT_REG 0x3a17 |
170 | #define OV5648_AEC_GAIN_CEILING_H_REG 0x3a18 |
171 | #define OV5648_AEC_GAIN_CEILING_L_REG 0x3a19 |
172 | #define OV5648_DIFF_MAX_REG 0x3a1a |
173 | #define OV5648_WPT2_REG 0x3a1b |
174 | #define OV5648_LED_ADD_ROW_H_REG 0x3a1c |
175 | #define OV5648_LED_ADD_ROW_L_REG 0x3a1d |
176 | #define OV5648_BPT2_REG 0x3a1e |
177 | #define OV5648_VPT_LOW_REG 0x3a1f |
178 | #define OV5648_AEC_CTRL20_REG 0x3a20 |
179 | #define OV5648_AEC_CTRL21_REG 0x3a21 |
180 | |
181 | #define OV5648_AVG_START_X_H_REG 0x5680 |
182 | #define OV5648_AVG_START_X_L_REG 0x5681 |
183 | #define OV5648_AVG_START_Y_H_REG 0x5682 |
184 | #define OV5648_AVG_START_Y_L_REG 0x5683 |
185 | #define OV5648_AVG_WINDOW_X_H_REG 0x5684 |
186 | #define OV5648_AVG_WINDOW_X_L_REG 0x5685 |
187 | #define OV5648_AVG_WINDOW_Y_H_REG 0x5686 |
188 | #define OV5648_AVG_WINDOW_Y_L_REG 0x5687 |
189 | #define OV5648_AVG_WEIGHT00_REG 0x5688 |
190 | #define OV5648_AVG_WEIGHT01_REG 0x5689 |
191 | #define OV5648_AVG_WEIGHT02_REG 0x568a |
192 | #define OV5648_AVG_WEIGHT03_REG 0x568b |
193 | #define OV5648_AVG_WEIGHT04_REG 0x568c |
194 | #define OV5648_AVG_WEIGHT05_REG 0x568d |
195 | #define OV5648_AVG_WEIGHT06_REG 0x568e |
196 | #define OV5648_AVG_WEIGHT07_REG 0x568f |
197 | #define OV5648_AVG_CTRL10_REG 0x5690 |
198 | #define OV5648_AVG_WEIGHT_SUM_REG 0x5691 |
199 | #define OV5648_AVG_READOUT_REG 0x5693 |
200 | |
201 | #define OV5648_DIG_CTRL0_REG 0x5a00 |
202 | #define OV5648_DIG_COMP_MAN_H_REG 0x5a02 |
203 | #define OV5648_DIG_COMP_MAN_L_REG 0x5a03 |
204 | |
205 | #define OV5648_GAINC_MAN_H_REG 0x5a20 |
206 | #define OV5648_GAINC_MAN_L_REG 0x5a21 |
207 | #define OV5648_GAINC_DGC_MAN_H_REG 0x5a22 |
208 | #define OV5648_GAINC_DGC_MAN_L_REG 0x5a23 |
209 | #define OV5648_GAINC_CTRL0_REG 0x5a24 |
210 | |
211 | #define OV5648_GAINF_ANA_NUM_REG 0x5a40 |
212 | #define OV5648_GAINF_DIG_GAIN_REG 0x5a41 |
213 | |
214 | /* Timing */ |
215 | |
216 | #define OV5648_CROP_START_X_H_REG 0x3800 |
217 | #define OV5648_CROP_START_X_H(v) (((v) & GENMASK(11, 8)) >> 8) |
218 | #define OV5648_CROP_START_X_L_REG 0x3801 |
219 | #define OV5648_CROP_START_X_L(v) ((v) & GENMASK(7, 0)) |
220 | #define OV5648_CROP_START_Y_H_REG 0x3802 |
221 | #define OV5648_CROP_START_Y_H(v) (((v) & GENMASK(11, 8)) >> 8) |
222 | #define OV5648_CROP_START_Y_L_REG 0x3803 |
223 | #define OV5648_CROP_START_Y_L(v) ((v) & GENMASK(7, 0)) |
224 | #define OV5648_CROP_END_X_H_REG 0x3804 |
225 | #define OV5648_CROP_END_X_H(v) (((v) & GENMASK(11, 8)) >> 8) |
226 | #define OV5648_CROP_END_X_L_REG 0x3805 |
227 | #define OV5648_CROP_END_X_L(v) ((v) & GENMASK(7, 0)) |
228 | #define OV5648_CROP_END_Y_H_REG 0x3806 |
229 | #define OV5648_CROP_END_Y_H(v) (((v) & GENMASK(11, 8)) >> 8) |
230 | #define OV5648_CROP_END_Y_L_REG 0x3807 |
231 | #define OV5648_CROP_END_Y_L(v) ((v) & GENMASK(7, 0)) |
232 | #define OV5648_OUTPUT_SIZE_X_H_REG 0x3808 |
233 | #define OV5648_OUTPUT_SIZE_X_H(v) (((v) & GENMASK(11, 8)) >> 8) |
234 | #define OV5648_OUTPUT_SIZE_X_L_REG 0x3809 |
235 | #define OV5648_OUTPUT_SIZE_X_L(v) ((v) & GENMASK(7, 0)) |
236 | #define OV5648_OUTPUT_SIZE_Y_H_REG 0x380a |
237 | #define OV5648_OUTPUT_SIZE_Y_H(v) (((v) & GENMASK(11, 8)) >> 8) |
238 | #define OV5648_OUTPUT_SIZE_Y_L_REG 0x380b |
239 | #define OV5648_OUTPUT_SIZE_Y_L(v) ((v) & GENMASK(7, 0)) |
240 | #define OV5648_HTS_H_REG 0x380c |
241 | #define OV5648_HTS_H(v) (((v) & GENMASK(12, 8)) >> 8) |
242 | #define OV5648_HTS_L_REG 0x380d |
243 | #define OV5648_HTS_L(v) ((v) & GENMASK(7, 0)) |
244 | #define OV5648_VTS_H_REG 0x380e |
245 | #define OV5648_VTS_H(v) (((v) & GENMASK(15, 8)) >> 8) |
246 | #define OV5648_VTS_L_REG 0x380f |
247 | #define OV5648_VTS_L(v) ((v) & GENMASK(7, 0)) |
248 | #define OV5648_OFFSET_X_H_REG 0x3810 |
249 | #define OV5648_OFFSET_X_H(v) (((v) & GENMASK(11, 8)) >> 8) |
250 | #define OV5648_OFFSET_X_L_REG 0x3811 |
251 | #define OV5648_OFFSET_X_L(v) ((v) & GENMASK(7, 0)) |
252 | #define OV5648_OFFSET_Y_H_REG 0x3812 |
253 | #define OV5648_OFFSET_Y_H(v) (((v) & GENMASK(11, 8)) >> 8) |
254 | #define OV5648_OFFSET_Y_L_REG 0x3813 |
255 | #define OV5648_OFFSET_Y_L(v) ((v) & GENMASK(7, 0)) |
256 | #define OV5648_SUB_INC_X_REG 0x3814 |
257 | #define OV5648_SUB_INC_X_ODD(v) (((v) << 4) & GENMASK(7, 4)) |
258 | #define OV5648_SUB_INC_X_EVEN(v) ((v) & GENMASK(3, 0)) |
259 | #define OV5648_SUB_INC_Y_REG 0x3815 |
260 | #define OV5648_SUB_INC_Y_ODD(v) (((v) << 4) & GENMASK(7, 4)) |
261 | #define OV5648_SUB_INC_Y_EVEN(v) ((v) & GENMASK(3, 0)) |
262 | #define OV5648_HSYNCST_H_REG 0x3816 |
263 | #define OV5648_HSYNCST_H(v) (((v) >> 8) & 0xf) |
264 | #define OV5648_HSYNCST_L_REG 0x3817 |
265 | #define OV5648_HSYNCST_L(v) ((v) & GENMASK(7, 0)) |
266 | #define OV5648_HSYNCW_H_REG 0x3818 |
267 | #define OV5648_HSYNCW_H(v) (((v) >> 8) & 0xf) |
268 | #define OV5648_HSYNCW_L_REG 0x3819 |
269 | #define OV5648_HSYNCW_L(v) ((v) & GENMASK(7, 0)) |
270 | |
271 | #define OV5648_TC20_REG 0x3820 |
272 | #define OV5648_TC20_DEBUG BIT(6) |
273 | #define OV5648_TC20_FLIP_VERT_ISP_EN BIT(2) |
274 | #define OV5648_TC20_FLIP_VERT_SENSOR_EN BIT(1) |
275 | #define OV5648_TC20_BINNING_VERT_EN BIT(0) |
276 | #define OV5648_TC21_REG 0x3821 |
277 | #define OV5648_TC21_FLIP_HORZ_ISP_EN BIT(2) |
278 | #define OV5648_TC21_FLIP_HORZ_SENSOR_EN BIT(1) |
279 | #define OV5648_TC21_BINNING_HORZ_EN BIT(0) |
280 | |
281 | /* Strobe/exposure */ |
282 | |
283 | #define OV5648_STROBE_REG 0x3b00 |
284 | #define OV5648_FREX_EXP_HH_REG 0x3b01 |
285 | #define OV5648_SHUTTER_DLY_H_REG 0x3b02 |
286 | #define OV5648_SHUTTER_DLY_L_REG 0x3b03 |
287 | #define OV5648_FREX_EXP_H_REG 0x3b04 |
288 | #define OV5648_FREX_EXP_L_REG 0x3b05 |
289 | #define OV5648_FREX_CTRL_REG 0x3b06 |
290 | #define OV5648_FREX_MODE_SEL_REG 0x3b07 |
291 | #define OV5648_FREX_MODE_SEL_FREX_SA1 BIT(4) |
292 | #define OV5648_FREX_MODE_SEL_FX1_FM_EN BIT(3) |
293 | #define OV5648_FREX_MODE_SEL_FREX_INV BIT(2) |
294 | #define OV5648_FREX_MODE_SEL_MODE1 0x0 |
295 | #define OV5648_FREX_MODE_SEL_MODE2 0x1 |
296 | #define OV5648_FREX_MODE_SEL_ROLLING 0x2 |
297 | #define OV5648_FREX_EXP_REQ_REG 0x3b08 |
298 | #define OV5648_FREX_SHUTTER_DLY_REG 0x3b09 |
299 | #define OV5648_FREX_RST_LEN_REG 0x3b0a |
300 | #define OV5648_STROBE_WIDTH_HH_REG 0x3b0b |
301 | #define OV5648_STROBE_WIDTH_H_REG 0x3b0c |
302 | |
303 | /* OTP */ |
304 | |
305 | #define OV5648_OTP_DATA_REG_BASE 0x3d00 |
306 | #define OV5648_OTP_PROGRAM_CTRL_REG 0x3d80 |
307 | #define OV5648_OTP_LOAD_CTRL_REG 0x3d81 |
308 | |
309 | /* PSRAM */ |
310 | |
311 | #define OV5648_PSRAM_CTRL1_REG 0x3f01 |
312 | #define OV5648_PSRAM_CTRLF_REG 0x3f0f |
313 | |
314 | /* Black Level */ |
315 | |
316 | #define OV5648_BLC_CTRL0_REG 0x4000 |
317 | #define OV5648_BLC_CTRL1_REG 0x4001 |
318 | #define OV5648_BLC_CTRL1_START_LINE(v) ((v) & GENMASK(5, 0)) |
319 | #define OV5648_BLC_CTRL2_REG 0x4002 |
320 | #define OV5648_BLC_CTRL2_AUTO_EN BIT(6) |
321 | #define OV5648_BLC_CTRL2_RESET_FRAME_NUM(v) ((v) & GENMASK(5, 0)) |
322 | #define OV5648_BLC_CTRL3_REG 0x4003 |
323 | #define OV5648_BLC_LINE_NUM_REG 0x4004 |
324 | #define OV5648_BLC_LINE_NUM(v) ((v) & GENMASK(7, 0)) |
325 | #define OV5648_BLC_CTRL5_REG 0x4005 |
326 | #define OV5648_BLC_CTRL5_UPDATE_EN BIT(1) |
327 | #define OV5648_BLC_LEVEL_REG 0x4009 |
328 | |
329 | /* Frame */ |
330 | |
331 | #define OV5648_FRAME_CTRL_REG 0x4200 |
332 | #define OV5648_FRAME_ON_NUM_REG 0x4201 |
333 | #define OV5648_FRAME_OFF_NUM_REG 0x4202 |
334 | |
335 | /* MIPI CSI-2 */ |
336 | |
337 | #define OV5648_MIPI_CTRL0_REG 0x4800 |
338 | #define OV5648_MIPI_CTRL0_CLK_LANE_AUTOGATE BIT(5) |
339 | #define OV5648_MIPI_CTRL0_LANE_SYNC_EN BIT(4) |
340 | #define OV5648_MIPI_CTRL0_LANE_SELECT_LANE1 0 |
341 | #define OV5648_MIPI_CTRL0_LANE_SELECT_LANE2 BIT(3) |
342 | #define OV5648_MIPI_CTRL0_IDLE_LP00 0 |
343 | #define OV5648_MIPI_CTRL0_IDLE_LP11 BIT(2) |
344 | |
345 | #define OV5648_MIPI_CTRL1_REG 0x4801 |
346 | #define OV5648_MIPI_CTRL2_REG 0x4802 |
347 | #define OV5648_MIPI_CTRL3_REG 0x4803 |
348 | #define OV5648_MIPI_CTRL4_REG 0x4804 |
349 | #define OV5648_MIPI_CTRL5_REG 0x4805 |
350 | #define OV5648_MIPI_MAX_FRAME_COUNT_H_REG 0x4810 |
351 | #define OV5648_MIPI_MAX_FRAME_COUNT_L_REG 0x4811 |
352 | #define OV5648_MIPI_CTRL14_REG 0x4814 |
353 | #define OV5648_MIPI_DT_SPKT_REG 0x4815 |
354 | #define OV5648_MIPI_HS_ZERO_MIN_H_REG 0x4818 |
355 | #define OV5648_MIPI_HS_ZERO_MIN_L_REG 0x4819 |
356 | #define OV5648_MIPI_HS_TRAIN_MIN_H_REG 0x481a |
357 | #define OV5648_MIPI_HS_TRAIN_MIN_L_REG 0x481b |
358 | #define OV5648_MIPI_CLK_ZERO_MIN_H_REG 0x481c |
359 | #define OV5648_MIPI_CLK_ZERO_MIN_L_REG 0x481d |
360 | #define OV5648_MIPI_CLK_PREPARE_MIN_H_REG 0x481e |
361 | #define OV5648_MIPI_CLK_PREPARE_MIN_L_REG 0x481f |
362 | #define OV5648_MIPI_CLK_POST_MIN_H_REG 0x4820 |
363 | #define OV5648_MIPI_CLK_POST_MIN_L_REG 0x4821 |
364 | #define OV5648_MIPI_CLK_TRAIL_MIN_H_REG 0x4822 |
365 | #define OV5648_MIPI_CLK_TRAIL_MIN_L_REG 0x4823 |
366 | #define OV5648_MIPI_LPX_P_MIN_H_REG 0x4824 |
367 | #define OV5648_MIPI_LPX_P_MIN_L_REG 0x4825 |
368 | #define OV5648_MIPI_HS_PREPARE_MIN_H_REG 0x4826 |
369 | #define OV5648_MIPI_HS_PREPARE_MIN_L_REG 0x4827 |
370 | #define OV5648_MIPI_HS_EXIT_MIN_H_REG 0x4828 |
371 | #define OV5648_MIPI_HS_EXIT_MIN_L_REG 0x4829 |
372 | #define OV5648_MIPI_HS_ZERO_MIN_UI_REG 0x482a |
373 | #define OV5648_MIPI_HS_TRAIL_MIN_UI_REG 0x482b |
374 | #define OV5648_MIPI_CLK_ZERO_MIN_UI_REG 0x482c |
375 | #define OV5648_MIPI_CLK_PREPARE_MIN_UI_REG 0x482d |
376 | #define OV5648_MIPI_CLK_POST_MIN_UI_REG 0x482e |
377 | #define OV5648_MIPI_CLK_TRAIL_MIN_UI_REG 0x482f |
378 | #define OV5648_MIPI_LPX_P_MIN_UI_REG 0x4830 |
379 | #define OV5648_MIPI_HS_PREPARE_MIN_UI_REG 0x4831 |
380 | #define OV5648_MIPI_HS_EXIT_MIN_UI_REG 0x4832 |
381 | #define OV5648_MIPI_REG_MIN_H_REG 0x4833 |
382 | #define OV5648_MIPI_REG_MIN_L_REG 0x4834 |
383 | #define OV5648_MIPI_REG_MAX_H_REG 0x4835 |
384 | #define OV5648_MIPI_REG_MAX_L_REG 0x4836 |
385 | #define OV5648_MIPI_PCLK_PERIOD_REG 0x4837 |
386 | #define OV5648_MIPI_WKUP_DLY_REG 0x4838 |
387 | #define OV5648_MIPI_LP_GPIO_REG 0x483b |
388 | #define OV5648_MIPI_SNR_PCLK_DIV_REG 0x4843 |
389 | |
390 | /* ISP */ |
391 | |
392 | #define OV5648_ISP_CTRL0_REG 0x5000 |
393 | #define OV5648_ISP_CTRL0_BLACK_CORRECT_EN BIT(2) |
394 | #define OV5648_ISP_CTRL0_WHITE_CORRECT_EN BIT(1) |
395 | #define OV5648_ISP_CTRL1_REG 0x5001 |
396 | #define OV5648_ISP_CTRL1_AWB_EN BIT(0) |
397 | #define OV5648_ISP_CTRL2_REG 0x5002 |
398 | #define OV5648_ISP_CTRL2_WIN_EN BIT(6) |
399 | #define OV5648_ISP_CTRL2_OTP_EN BIT(1) |
400 | #define OV5648_ISP_CTRL2_AWB_GAIN_EN BIT(0) |
401 | #define OV5648_ISP_CTRL3_REG 0x5003 |
402 | #define OV5648_ISP_CTRL3_BUF_EN BIT(3) |
403 | #define OV5648_ISP_CTRL3_BIN_MAN_SET BIT(2) |
404 | #define OV5648_ISP_CTRL3_BIN_AUTO_EN BIT(1) |
405 | #define OV5648_ISP_CTRL4_REG 0x5004 |
406 | #define OV5648_ISP_CTRL5_REG 0x5005 |
407 | #define OV5648_ISP_CTRL6_REG 0x5006 |
408 | #define OV5648_ISP_CTRL7_REG 0x5007 |
409 | #define OV5648_ISP_MAN_OFFSET_X_H_REG 0x5008 |
410 | #define OV5648_ISP_MAN_OFFSET_X_L_REG 0x5009 |
411 | #define OV5648_ISP_MAN_OFFSET_Y_H_REG 0x500a |
412 | #define OV5648_ISP_MAN_OFFSET_Y_L_REG 0x500b |
413 | #define OV5648_ISP_MAN_WIN_OFFSET_X_H_REG 0x500c |
414 | #define OV5648_ISP_MAN_WIN_OFFSET_X_L_REG 0x500d |
415 | #define OV5648_ISP_MAN_WIN_OFFSET_Y_H_REG 0x500e |
416 | #define OV5648_ISP_MAN_WIN_OFFSET_Y_L_REG 0x500f |
417 | #define OV5648_ISP_MAN_WIN_OUTPUT_X_H_REG 0x5010 |
418 | #define OV5648_ISP_MAN_WIN_OUTPUT_X_L_REG 0x5011 |
419 | #define OV5648_ISP_MAN_WIN_OUTPUT_Y_H_REG 0x5012 |
420 | #define OV5648_ISP_MAN_WIN_OUTPUT_Y_L_REG 0x5013 |
421 | #define OV5648_ISP_MAN_INPUT_X_H_REG 0x5014 |
422 | #define OV5648_ISP_MAN_INPUT_X_L_REG 0x5015 |
423 | #define OV5648_ISP_MAN_INPUT_Y_H_REG 0x5016 |
424 | #define OV5648_ISP_MAN_INPUT_Y_L_REG 0x5017 |
425 | #define OV5648_ISP_CTRL18_REG 0x5018 |
426 | #define OV5648_ISP_CTRL19_REG 0x5019 |
427 | #define OV5648_ISP_CTRL1A_REG 0x501a |
428 | #define OV5648_ISP_CTRL1D_REG 0x501d |
429 | #define OV5648_ISP_CTRL1F_REG 0x501f |
430 | #define OV5648_ISP_CTRL1F_OUTPUT_EN 3 |
431 | #define OV5648_ISP_CTRL25_REG 0x5025 |
432 | |
433 | #define OV5648_ISP_CTRL3D_REG 0x503d |
434 | #define OV5648_ISP_CTRL3D_PATTERN_EN BIT(7) |
435 | #define OV5648_ISP_CTRL3D_ROLLING_BAR_EN BIT(6) |
436 | #define OV5648_ISP_CTRL3D_TRANSPARENT_MODE BIT(5) |
437 | #define OV5648_ISP_CTRL3D_SQUARES_BW_MODE BIT(4) |
438 | #define OV5648_ISP_CTRL3D_PATTERN_COLOR_BARS 0 |
439 | #define OV5648_ISP_CTRL3D_PATTERN_RANDOM_DATA 1 |
440 | #define OV5648_ISP_CTRL3D_PATTERN_COLOR_SQUARES 2 |
441 | #define OV5648_ISP_CTRL3D_PATTERN_INPUT 3 |
442 | |
443 | #define OV5648_ISP_CTRL3E_REG 0x503e |
444 | #define OV5648_ISP_CTRL4B_REG 0x504b |
445 | #define OV5648_ISP_CTRL4B_POST_BIN_H_EN BIT(5) |
446 | #define OV5648_ISP_CTRL4B_POST_BIN_V_EN BIT(4) |
447 | #define OV5648_ISP_CTRL4C_REG 0x504c |
448 | #define OV5648_ISP_CTRL57_REG 0x5057 |
449 | #define OV5648_ISP_CTRL58_REG 0x5058 |
450 | #define OV5648_ISP_CTRL59_REG 0x5059 |
451 | |
452 | #define OV5648_ISP_WINDOW_START_X_H_REG 0x5980 |
453 | #define OV5648_ISP_WINDOW_START_X_L_REG 0x5981 |
454 | #define OV5648_ISP_WINDOW_START_Y_H_REG 0x5982 |
455 | #define OV5648_ISP_WINDOW_START_Y_L_REG 0x5983 |
456 | #define OV5648_ISP_WINDOW_WIN_X_H_REG 0x5984 |
457 | #define OV5648_ISP_WINDOW_WIN_X_L_REG 0x5985 |
458 | #define OV5648_ISP_WINDOW_WIN_Y_H_REG 0x5986 |
459 | #define OV5648_ISP_WINDOW_WIN_Y_L_REG 0x5987 |
460 | #define OV5648_ISP_WINDOW_MAN_REG 0x5988 |
461 | |
462 | /* White Balance */ |
463 | |
464 | #define OV5648_AWB_CTRL_REG 0x5180 |
465 | #define OV5648_AWB_CTRL_FAST_AWB BIT(6) |
466 | #define OV5648_AWB_CTRL_GAIN_FREEZE_EN BIT(5) |
467 | #define OV5648_AWB_CTRL_SUM_FREEZE_EN BIT(4) |
468 | #define OV5648_AWB_CTRL_GAIN_MANUAL_EN BIT(3) |
469 | |
470 | #define OV5648_AWB_DELTA_REG 0x5181 |
471 | #define OV5648_AWB_STABLE_RANGE_REG 0x5182 |
472 | #define OV5648_AWB_STABLE_RANGE_WIDE_REG 0x5183 |
473 | #define OV5648_HSIZE_MAN_REG 0x5185 |
474 | |
475 | #define OV5648_GAIN_RED_MAN_H_REG 0x5186 |
476 | #define OV5648_GAIN_RED_MAN_H(v) (((v) & GENMASK(11, 8)) >> 8) |
477 | #define OV5648_GAIN_RED_MAN_L_REG 0x5187 |
478 | #define OV5648_GAIN_RED_MAN_L(v) ((v) & GENMASK(7, 0)) |
479 | #define OV5648_GAIN_GREEN_MAN_H_REG 0x5188 |
480 | #define OV5648_GAIN_GREEN_MAN_H(v) (((v) & GENMASK(11, 8)) >> 8) |
481 | #define OV5648_GAIN_GREEN_MAN_L_REG 0x5189 |
482 | #define OV5648_GAIN_GREEN_MAN_L(v) ((v) & GENMASK(7, 0)) |
483 | #define OV5648_GAIN_BLUE_MAN_H_REG 0x518a |
484 | #define OV5648_GAIN_BLUE_MAN_H(v) (((v) & GENMASK(11, 8)) >> 8) |
485 | #define OV5648_GAIN_BLUE_MAN_L_REG 0x518b |
486 | #define OV5648_GAIN_BLUE_MAN_L(v) ((v) & GENMASK(7, 0)) |
487 | #define OV5648_GAIN_RED_LIMIT_REG 0x518c |
488 | #define OV5648_GAIN_GREEN_LIMIT_REG 0x518d |
489 | #define OV5648_GAIN_BLUE_LIMIT_REG 0x518e |
490 | #define OV5648_AWB_FRAME_COUNT_REG 0x518f |
491 | #define OV5648_AWB_BASE_MAN_REG 0x51df |
492 | |
493 | /* Macros */ |
494 | |
495 | #define ov5648_subdev_sensor(s) \ |
496 | container_of(s, struct ov5648_sensor, subdev) |
497 | |
498 | #define ov5648_ctrl_subdev(c) \ |
499 | (&container_of((c)->handler, struct ov5648_sensor, \ |
500 | ctrls.handler)->subdev) |
501 | |
502 | /* Data structures */ |
503 | |
504 | struct ov5648_register_value { |
505 | u16 address; |
506 | u8 value; |
507 | unsigned int delay_ms; |
508 | }; |
509 | |
510 | /* |
511 | * PLL1 Clock Tree: |
512 | * |
513 | * +-< XVCLK |
514 | * | |
515 | * +-+ pll_pre_div (0x3037 [3:0], special values: 5: 1.5, 7: 2.5) |
516 | * | |
517 | * +-+ pll_mul (0x3036 [7:0]) |
518 | * | |
519 | * +-+ sys_div (0x3035 [7:4]) |
520 | * | |
521 | * +-+ mipi_div (0x3035 [3:0]) |
522 | * | | |
523 | * | +-> MIPI_SCLK |
524 | * | | |
525 | * | +-+ mipi_phy_div (2) |
526 | * | | |
527 | * | +-> MIPI_CLK |
528 | * | |
529 | * +-+ root_div (0x3037 [4]) |
530 | * | |
531 | * +-+ bit_div (0x3034 [3:0], 8 bits: 2, 10 bits: 2.5, other: 1) |
532 | * | |
533 | * +-+ sclk_div (0x3106 [3:2]) |
534 | * | |
535 | * +-> SCLK |
536 | * | |
537 | * +-+ mipi_div (0x3035, 1: PCLK = SCLK) |
538 | * | |
539 | * +-> PCLK |
540 | */ |
541 | |
542 | struct ov5648_pll1_config { |
543 | unsigned int pll_pre_div; |
544 | unsigned int pll_mul; |
545 | unsigned int sys_div; |
546 | unsigned int root_div; |
547 | unsigned int sclk_div; |
548 | unsigned int mipi_div; |
549 | }; |
550 | |
551 | /* |
552 | * PLL2 Clock Tree: |
553 | * |
554 | * +-< XVCLK |
555 | * | |
556 | * +-+ plls_pre_div (0x303d [5:4], special values: 0: 1, 1: 1.5) |
557 | * | |
558 | * +-+ plls_div_r (0x303d [2]) |
559 | * | |
560 | * +-+ plls_mul (0x303b [4:0]) |
561 | * | |
562 | * +-+ sys_div (0x303c [3:0]) |
563 | * | |
564 | * +-+ sel_div (0x303d [1:0], special values: 0: 1, 3: 2.5) |
565 | * | |
566 | * +-> ADCLK |
567 | */ |
568 | |
569 | struct ov5648_pll2_config { |
570 | unsigned int plls_pre_div; |
571 | unsigned int plls_div_r; |
572 | unsigned int plls_mul; |
573 | unsigned int sys_div; |
574 | unsigned int sel_div; |
575 | }; |
576 | |
577 | /* |
578 | * General formulas for (array-centered) mode calculation: |
579 | * - photo_array_width = 2624 |
580 | * - crop_start_x = (photo_array_width - output_size_x) / 2 |
581 | * - crop_end_x = crop_start_x + offset_x + output_size_x - 1 |
582 | * |
583 | * - photo_array_height = 1956 |
584 | * - crop_start_y = (photo_array_height - output_size_y) / 2 |
585 | * - crop_end_y = crop_start_y + offset_y + output_size_y - 1 |
586 | */ |
587 | |
588 | struct ov5648_mode { |
589 | unsigned int crop_start_x; |
590 | unsigned int offset_x; |
591 | unsigned int output_size_x; |
592 | unsigned int crop_end_x; |
593 | unsigned int hts; |
594 | |
595 | unsigned int crop_start_y; |
596 | unsigned int offset_y; |
597 | unsigned int output_size_y; |
598 | unsigned int crop_end_y; |
599 | unsigned int vts; |
600 | |
601 | bool binning_x; |
602 | bool binning_y; |
603 | |
604 | unsigned int inc_x_odd; |
605 | unsigned int inc_x_even; |
606 | unsigned int inc_y_odd; |
607 | unsigned int inc_y_even; |
608 | |
609 | /* 8-bit frame interval followed by 10-bit frame interval. */ |
610 | struct v4l2_fract frame_interval[2]; |
611 | |
612 | /* 8-bit config followed by 10-bit config. */ |
613 | const struct ov5648_pll1_config *pll1_config[2]; |
614 | const struct ov5648_pll2_config *pll2_config; |
615 | |
616 | const struct ov5648_register_value *register_values; |
617 | unsigned int register_values_count; |
618 | }; |
619 | |
620 | struct ov5648_state { |
621 | const struct ov5648_mode *mode; |
622 | u32 mbus_code; |
623 | |
624 | bool streaming; |
625 | }; |
626 | |
627 | struct ov5648_ctrls { |
628 | struct v4l2_ctrl *exposure_auto; |
629 | struct v4l2_ctrl *exposure; |
630 | |
631 | struct v4l2_ctrl *gain_auto; |
632 | struct v4l2_ctrl *gain; |
633 | |
634 | struct v4l2_ctrl *white_balance_auto; |
635 | struct v4l2_ctrl *red_balance; |
636 | struct v4l2_ctrl *blue_balance; |
637 | |
638 | struct v4l2_ctrl *link_freq; |
639 | struct v4l2_ctrl *pixel_rate; |
640 | |
641 | struct v4l2_ctrl_handler handler; |
642 | }; |
643 | |
644 | struct ov5648_sensor { |
645 | struct device *dev; |
646 | struct i2c_client *i2c_client; |
647 | struct gpio_desc *reset; |
648 | struct gpio_desc *powerdown; |
649 | struct regulator *avdd; |
650 | struct regulator *dvdd; |
651 | struct regulator *dovdd; |
652 | struct clk *xvclk; |
653 | |
654 | struct v4l2_fwnode_endpoint endpoint; |
655 | struct v4l2_subdev subdev; |
656 | struct media_pad pad; |
657 | |
658 | struct mutex mutex; |
659 | |
660 | struct ov5648_state state; |
661 | struct ov5648_ctrls ctrls; |
662 | }; |
663 | |
664 | /* Static definitions */ |
665 | |
666 | /* |
667 | * XVCLK = 24 MHz |
668 | * SCLK = 84 MHz |
669 | * PCLK = 84 MHz |
670 | */ |
671 | static const struct ov5648_pll1_config ov5648_pll1_config_native_8_bits = { |
672 | .pll_pre_div = 3, |
673 | .pll_mul = 84, |
674 | .sys_div = 2, |
675 | .root_div = 1, |
676 | .sclk_div = 1, |
677 | .mipi_div = 1, |
678 | }; |
679 | |
680 | /* |
681 | * XVCLK = 24 MHz |
682 | * SCLK = 84 MHz |
683 | * PCLK = 84 MHz |
684 | */ |
685 | static const struct ov5648_pll1_config ov5648_pll1_config_native_10_bits = { |
686 | .pll_pre_div = 3, |
687 | .pll_mul = 105, |
688 | .sys_div = 2, |
689 | .root_div = 1, |
690 | .sclk_div = 1, |
691 | .mipi_div = 1, |
692 | }; |
693 | |
694 | /* |
695 | * XVCLK = 24 MHz |
696 | * ADCLK = 200 MHz |
697 | */ |
698 | static const struct ov5648_pll2_config ov5648_pll2_config_native = { |
699 | .plls_pre_div = 3, |
700 | .plls_div_r = 1, |
701 | .plls_mul = 25, |
702 | .sys_div = 1, |
703 | .sel_div = 1, |
704 | }; |
705 | |
706 | static const struct ov5648_mode ov5648_modes[] = { |
707 | /* 2592x1944 */ |
708 | { |
709 | /* Horizontal */ |
710 | .crop_start_x = 16, |
711 | .offset_x = 0, |
712 | .output_size_x = 2592, |
713 | .crop_end_x = 2607, |
714 | .hts = 2816, |
715 | |
716 | /* Vertical */ |
717 | .crop_start_y = 6, |
718 | .offset_y = 0, |
719 | .output_size_y = 1944, |
720 | .crop_end_y = 1949, |
721 | .vts = 1984, |
722 | |
723 | /* Subsample increase */ |
724 | .inc_x_odd = 1, |
725 | .inc_x_even = 1, |
726 | .inc_y_odd = 1, |
727 | .inc_y_even = 1, |
728 | |
729 | /* Frame Interval */ |
730 | .frame_interval = { |
731 | { 1, 15 }, |
732 | { 1, 15 }, |
733 | }, |
734 | |
735 | /* PLL */ |
736 | .pll1_config = { |
737 | &ov5648_pll1_config_native_8_bits, |
738 | &ov5648_pll1_config_native_10_bits, |
739 | }, |
740 | .pll2_config = &ov5648_pll2_config_native, |
741 | }, |
742 | /* 1600x1200 (UXGA) */ |
743 | { |
744 | /* Horizontal */ |
745 | .crop_start_x = 512, |
746 | .offset_x = 0, |
747 | .output_size_x = 1600, |
748 | .crop_end_x = 2111, |
749 | .hts = 2816, |
750 | |
751 | /* Vertical */ |
752 | .crop_start_y = 378, |
753 | .offset_y = 0, |
754 | .output_size_y = 1200, |
755 | .crop_end_y = 1577, |
756 | .vts = 1984, |
757 | |
758 | /* Subsample increase */ |
759 | .inc_x_odd = 1, |
760 | .inc_x_even = 1, |
761 | .inc_y_odd = 1, |
762 | .inc_y_even = 1, |
763 | |
764 | /* Frame Interval */ |
765 | .frame_interval = { |
766 | { 1, 15 }, |
767 | { 1, 15 }, |
768 | }, |
769 | |
770 | /* PLL */ |
771 | .pll1_config = { |
772 | &ov5648_pll1_config_native_8_bits, |
773 | &ov5648_pll1_config_native_10_bits, |
774 | }, |
775 | .pll2_config = &ov5648_pll2_config_native, |
776 | }, |
777 | /* 1920x1080 (Full HD) */ |
778 | { |
779 | /* Horizontal */ |
780 | .crop_start_x = 352, |
781 | .offset_x = 0, |
782 | .output_size_x = 1920, |
783 | .crop_end_x = 2271, |
784 | .hts = 2816, |
785 | |
786 | /* Vertical */ |
787 | .crop_start_y = 438, |
788 | .offset_y = 0, |
789 | .output_size_y = 1080, |
790 | .crop_end_y = 1517, |
791 | .vts = 1984, |
792 | |
793 | /* Subsample increase */ |
794 | .inc_x_odd = 1, |
795 | .inc_x_even = 1, |
796 | .inc_y_odd = 1, |
797 | .inc_y_even = 1, |
798 | |
799 | /* Frame Interval */ |
800 | .frame_interval = { |
801 | { 1, 15 }, |
802 | { 1, 15 }, |
803 | }, |
804 | |
805 | /* PLL */ |
806 | .pll1_config = { |
807 | &ov5648_pll1_config_native_8_bits, |
808 | &ov5648_pll1_config_native_10_bits, |
809 | }, |
810 | .pll2_config = &ov5648_pll2_config_native, |
811 | }, |
812 | /* 1280x960 */ |
813 | { |
814 | /* Horizontal */ |
815 | .crop_start_x = 16, |
816 | .offset_x = 8, |
817 | .output_size_x = 1280, |
818 | .crop_end_x = 2607, |
819 | .hts = 1912, |
820 | |
821 | /* Vertical */ |
822 | .crop_start_y = 6, |
823 | .offset_y = 6, |
824 | .output_size_y = 960, |
825 | .crop_end_y = 1949, |
826 | .vts = 1496, |
827 | |
828 | /* Binning */ |
829 | .binning_x = true, |
830 | |
831 | /* Subsample increase */ |
832 | .inc_x_odd = 3, |
833 | .inc_x_even = 1, |
834 | .inc_y_odd = 3, |
835 | .inc_y_even = 1, |
836 | |
837 | /* Frame Interval */ |
838 | .frame_interval = { |
839 | { 1, 30 }, |
840 | { 1, 30 }, |
841 | }, |
842 | |
843 | /* PLL */ |
844 | .pll1_config = { |
845 | &ov5648_pll1_config_native_8_bits, |
846 | &ov5648_pll1_config_native_10_bits, |
847 | }, |
848 | .pll2_config = &ov5648_pll2_config_native, |
849 | }, |
850 | /* 1280x720 (HD) */ |
851 | { |
852 | /* Horizontal */ |
853 | .crop_start_x = 16, |
854 | .offset_x = 8, |
855 | .output_size_x = 1280, |
856 | .crop_end_x = 2607, |
857 | .hts = 1912, |
858 | |
859 | /* Vertical */ |
860 | .crop_start_y = 254, |
861 | .offset_y = 2, |
862 | .output_size_y = 720, |
863 | .crop_end_y = 1701, |
864 | .vts = 1496, |
865 | |
866 | /* Binning */ |
867 | .binning_x = true, |
868 | |
869 | /* Subsample increase */ |
870 | .inc_x_odd = 3, |
871 | .inc_x_even = 1, |
872 | .inc_y_odd = 3, |
873 | .inc_y_even = 1, |
874 | |
875 | /* Frame Interval */ |
876 | .frame_interval = { |
877 | { 1, 30 }, |
878 | { 1, 30 }, |
879 | }, |
880 | |
881 | /* PLL */ |
882 | .pll1_config = { |
883 | &ov5648_pll1_config_native_8_bits, |
884 | &ov5648_pll1_config_native_10_bits, |
885 | }, |
886 | .pll2_config = &ov5648_pll2_config_native, |
887 | }, |
888 | /* 640x480 (VGA) */ |
889 | { |
890 | /* Horizontal */ |
891 | .crop_start_x = 0, |
892 | .offset_x = 8, |
893 | .output_size_x = 640, |
894 | .crop_end_x = 2623, |
895 | .hts = 1896, |
896 | |
897 | /* Vertical */ |
898 | .crop_start_y = 0, |
899 | .offset_y = 2, |
900 | .output_size_y = 480, |
901 | .crop_end_y = 1953, |
902 | .vts = 984, |
903 | |
904 | /* Binning */ |
905 | .binning_x = true, |
906 | |
907 | /* Subsample increase */ |
908 | .inc_x_odd = 7, |
909 | .inc_x_even = 1, |
910 | .inc_y_odd = 7, |
911 | .inc_y_even = 1, |
912 | |
913 | /* Frame Interval */ |
914 | .frame_interval = { |
915 | { 1, 30 }, |
916 | { 1, 30 }, |
917 | }, |
918 | |
919 | /* PLL */ |
920 | .pll1_config = { |
921 | &ov5648_pll1_config_native_8_bits, |
922 | &ov5648_pll1_config_native_10_bits, |
923 | }, |
924 | .pll2_config = &ov5648_pll2_config_native, |
925 | }, |
926 | }; |
927 | |
928 | static const u32 ov5648_mbus_codes[] = { |
929 | MEDIA_BUS_FMT_SBGGR8_1X8, |
930 | MEDIA_BUS_FMT_SBGGR10_1X10, |
931 | }; |
932 | |
933 | static const struct ov5648_register_value ov5648_init_sequence[] = { |
934 | /* PSRAM */ |
935 | { OV5648_PSRAM_CTRL1_REG, 0x0d }, |
936 | { OV5648_PSRAM_CTRLF_REG, 0xf5 }, |
937 | }; |
938 | |
939 | static const s64 [] = { |
940 | 210000000, |
941 | 168000000, |
942 | }; |
943 | |
944 | static const char *const [] = { |
945 | "Disabled" , |
946 | "Random data" , |
947 | "Color bars" , |
948 | "Color bars with rolling bar" , |
949 | "Color squares" , |
950 | "Color squares with rolling bar" |
951 | }; |
952 | |
953 | static const u8 ov5648_test_pattern_bits[] = { |
954 | 0, |
955 | OV5648_ISP_CTRL3D_PATTERN_EN | OV5648_ISP_CTRL3D_PATTERN_RANDOM_DATA, |
956 | OV5648_ISP_CTRL3D_PATTERN_EN | OV5648_ISP_CTRL3D_PATTERN_COLOR_BARS, |
957 | OV5648_ISP_CTRL3D_PATTERN_EN | OV5648_ISP_CTRL3D_ROLLING_BAR_EN | |
958 | OV5648_ISP_CTRL3D_PATTERN_COLOR_BARS, |
959 | OV5648_ISP_CTRL3D_PATTERN_EN | OV5648_ISP_CTRL3D_PATTERN_COLOR_SQUARES, |
960 | OV5648_ISP_CTRL3D_PATTERN_EN | OV5648_ISP_CTRL3D_ROLLING_BAR_EN | |
961 | OV5648_ISP_CTRL3D_PATTERN_COLOR_SQUARES, |
962 | }; |
963 | |
964 | /* Input/Output */ |
965 | |
966 | static int ov5648_read(struct ov5648_sensor *sensor, u16 address, u8 *value) |
967 | { |
968 | unsigned char data[2] = { address >> 8, address & 0xff }; |
969 | struct i2c_client *client = sensor->i2c_client; |
970 | int ret; |
971 | |
972 | ret = i2c_master_send(client, buf: data, count: sizeof(data)); |
973 | if (ret < 0) { |
974 | dev_dbg(&client->dev, "i2c send error at address %#04x\n" , |
975 | address); |
976 | return ret; |
977 | } |
978 | |
979 | ret = i2c_master_recv(client, buf: value, count: 1); |
980 | if (ret < 0) { |
981 | dev_dbg(&client->dev, "i2c recv error at address %#04x\n" , |
982 | address); |
983 | return ret; |
984 | } |
985 | |
986 | return 0; |
987 | } |
988 | |
989 | static int ov5648_write(struct ov5648_sensor *sensor, u16 address, u8 value) |
990 | { |
991 | unsigned char data[3] = { address >> 8, address & 0xff, value }; |
992 | struct i2c_client *client = sensor->i2c_client; |
993 | int ret; |
994 | |
995 | ret = i2c_master_send(client, buf: data, count: sizeof(data)); |
996 | if (ret < 0) { |
997 | dev_dbg(&client->dev, "i2c send error at address %#04x\n" , |
998 | address); |
999 | return ret; |
1000 | } |
1001 | |
1002 | return 0; |
1003 | } |
1004 | |
1005 | static int ov5648_write_sequence(struct ov5648_sensor *sensor, |
1006 | const struct ov5648_register_value *sequence, |
1007 | unsigned int sequence_count) |
1008 | { |
1009 | unsigned int i; |
1010 | int ret = 0; |
1011 | |
1012 | for (i = 0; i < sequence_count; i++) { |
1013 | ret = ov5648_write(sensor, address: sequence[i].address, |
1014 | value: sequence[i].value); |
1015 | if (ret) |
1016 | break; |
1017 | |
1018 | if (sequence[i].delay_ms) |
1019 | msleep(msecs: sequence[i].delay_ms); |
1020 | } |
1021 | |
1022 | return ret; |
1023 | } |
1024 | |
1025 | static int ov5648_update_bits(struct ov5648_sensor *sensor, u16 address, |
1026 | u8 mask, u8 bits) |
1027 | { |
1028 | u8 value = 0; |
1029 | int ret; |
1030 | |
1031 | ret = ov5648_read(sensor, address, value: &value); |
1032 | if (ret) |
1033 | return ret; |
1034 | |
1035 | value &= ~mask; |
1036 | value |= bits; |
1037 | |
1038 | ret = ov5648_write(sensor, address, value); |
1039 | if (ret) |
1040 | return ret; |
1041 | |
1042 | return 0; |
1043 | } |
1044 | |
1045 | /* Sensor */ |
1046 | |
1047 | static int ov5648_sw_reset(struct ov5648_sensor *sensor) |
1048 | { |
1049 | return ov5648_write(sensor, OV5648_SW_RESET_REG, OV5648_SW_RESET_RESET); |
1050 | } |
1051 | |
1052 | static int ov5648_sw_standby(struct ov5648_sensor *sensor, int standby) |
1053 | { |
1054 | u8 value = 0; |
1055 | |
1056 | if (!standby) |
1057 | value = OV5648_SW_STANDBY_STREAM_ON; |
1058 | |
1059 | return ov5648_write(sensor, OV5648_SW_STANDBY_REG, value); |
1060 | } |
1061 | |
1062 | static int ov5648_chip_id_check(struct ov5648_sensor *sensor) |
1063 | { |
1064 | u16 regs[] = { OV5648_CHIP_ID_H_REG, OV5648_CHIP_ID_L_REG }; |
1065 | u8 values[] = { OV5648_CHIP_ID_H_VALUE, OV5648_CHIP_ID_L_VALUE }; |
1066 | unsigned int i; |
1067 | u8 value; |
1068 | int ret; |
1069 | |
1070 | for (i = 0; i < ARRAY_SIZE(regs); i++) { |
1071 | ret = ov5648_read(sensor, address: regs[i], value: &value); |
1072 | if (ret < 0) |
1073 | return ret; |
1074 | |
1075 | if (value != values[i]) { |
1076 | dev_err(sensor->dev, |
1077 | "chip id value mismatch: %#x instead of %#x\n" , |
1078 | value, values[i]); |
1079 | return -EINVAL; |
1080 | } |
1081 | } |
1082 | |
1083 | return 0; |
1084 | } |
1085 | |
1086 | static int ov5648_avdd_internal_power(struct ov5648_sensor *sensor, int on) |
1087 | { |
1088 | return ov5648_write(sensor, OV5648_A_PWC_PK_O0_REG, |
1089 | value: on ? 0 : OV5648_A_PWC_PK_O0_BP_REGULATOR_N); |
1090 | } |
1091 | |
1092 | static int ov5648_pad_configure(struct ov5648_sensor *sensor) |
1093 | { |
1094 | int ret; |
1095 | |
1096 | /* Configure pads as input. */ |
1097 | |
1098 | ret = ov5648_write(sensor, OV5648_PAD_OEN1_REG, value: 0); |
1099 | if (ret) |
1100 | return ret; |
1101 | |
1102 | ret = ov5648_write(sensor, OV5648_PAD_OEN2_REG, value: 0); |
1103 | if (ret) |
1104 | return ret; |
1105 | |
1106 | /* Disable FREX pin. */ |
1107 | |
1108 | return ov5648_write(sensor, OV5648_PAD_PK_REG, |
1109 | OV5648_PAD_PK_DRIVE_STRENGTH_1X | |
1110 | OV5648_PAD_PK_FREX_N); |
1111 | } |
1112 | |
1113 | static int ov5648_mipi_configure(struct ov5648_sensor *sensor) |
1114 | { |
1115 | struct v4l2_mbus_config_mipi_csi2 *bus_mipi_csi2 = |
1116 | &sensor->endpoint.bus.mipi_csi2; |
1117 | unsigned int lanes_count = bus_mipi_csi2->num_data_lanes; |
1118 | int ret; |
1119 | |
1120 | ret = ov5648_write(sensor, OV5648_MIPI_CTRL0_REG, |
1121 | OV5648_MIPI_CTRL0_CLK_LANE_AUTOGATE | |
1122 | OV5648_MIPI_CTRL0_LANE_SELECT_LANE1 | |
1123 | OV5648_MIPI_CTRL0_IDLE_LP11); |
1124 | if (ret) |
1125 | return ret; |
1126 | |
1127 | return ov5648_write(sensor, OV5648_MIPI_SC_CTRL0_REG, |
1128 | OV5648_MIPI_SC_CTRL0_MIPI_LANES(lanes_count) | |
1129 | OV5648_MIPI_SC_CTRL0_PHY_LP_RX_PD | |
1130 | OV5648_MIPI_SC_CTRL0_MIPI_EN); |
1131 | } |
1132 | |
1133 | static int ov5648_black_level_configure(struct ov5648_sensor *sensor) |
1134 | { |
1135 | int ret; |
1136 | |
1137 | /* Up to 6 lines are available for black level calibration. */ |
1138 | |
1139 | ret = ov5648_write(sensor, OV5648_BLC_CTRL1_REG, |
1140 | OV5648_BLC_CTRL1_START_LINE(2)); |
1141 | if (ret) |
1142 | return ret; |
1143 | |
1144 | ret = ov5648_write(sensor, OV5648_BLC_CTRL2_REG, |
1145 | OV5648_BLC_CTRL2_AUTO_EN | |
1146 | OV5648_BLC_CTRL2_RESET_FRAME_NUM(5)); |
1147 | if (ret) |
1148 | return ret; |
1149 | |
1150 | ret = ov5648_write(sensor, OV5648_BLC_LINE_NUM_REG, |
1151 | OV5648_BLC_LINE_NUM(4)); |
1152 | if (ret) |
1153 | return ret; |
1154 | |
1155 | return ov5648_update_bits(sensor, OV5648_BLC_CTRL5_REG, |
1156 | OV5648_BLC_CTRL5_UPDATE_EN, |
1157 | OV5648_BLC_CTRL5_UPDATE_EN); |
1158 | } |
1159 | |
1160 | static int ov5648_isp_configure(struct ov5648_sensor *sensor) |
1161 | { |
1162 | u8 bits; |
1163 | int ret; |
1164 | |
1165 | /* Enable black and white level correction. */ |
1166 | bits = OV5648_ISP_CTRL0_BLACK_CORRECT_EN | |
1167 | OV5648_ISP_CTRL0_WHITE_CORRECT_EN; |
1168 | |
1169 | ret = ov5648_update_bits(sensor, OV5648_ISP_CTRL0_REG, mask: bits, bits); |
1170 | if (ret) |
1171 | return ret; |
1172 | |
1173 | /* Enable AWB. */ |
1174 | ret = ov5648_write(sensor, OV5648_ISP_CTRL1_REG, |
1175 | OV5648_ISP_CTRL1_AWB_EN); |
1176 | if (ret) |
1177 | return ret; |
1178 | |
1179 | /* Enable AWB gain and windowing. */ |
1180 | ret = ov5648_write(sensor, OV5648_ISP_CTRL2_REG, |
1181 | OV5648_ISP_CTRL2_WIN_EN | |
1182 | OV5648_ISP_CTRL2_AWB_GAIN_EN); |
1183 | if (ret) |
1184 | return ret; |
1185 | |
1186 | /* Enable buffering and auto-binning. */ |
1187 | ret = ov5648_write(sensor, OV5648_ISP_CTRL3_REG, |
1188 | OV5648_ISP_CTRL3_BUF_EN | |
1189 | OV5648_ISP_CTRL3_BIN_AUTO_EN); |
1190 | if (ret) |
1191 | return ret; |
1192 | |
1193 | ret = ov5648_write(sensor, OV5648_ISP_CTRL4_REG, value: 0); |
1194 | if (ret) |
1195 | return ret; |
1196 | |
1197 | ret = ov5648_write(sensor, OV5648_ISP_CTRL1F_REG, |
1198 | OV5648_ISP_CTRL1F_OUTPUT_EN); |
1199 | if (ret) |
1200 | return ret; |
1201 | |
1202 | /* Enable post-binning filters. */ |
1203 | ret = ov5648_write(sensor, OV5648_ISP_CTRL4B_REG, |
1204 | OV5648_ISP_CTRL4B_POST_BIN_H_EN | |
1205 | OV5648_ISP_CTRL4B_POST_BIN_V_EN); |
1206 | if (ret) |
1207 | return ret; |
1208 | |
1209 | /* Disable debanding and night mode. Debug bit seems necessary. */ |
1210 | ret = ov5648_write(sensor, OV5648_AEC_CTRL0_REG, |
1211 | OV5648_AEC_CTRL0_DEBUG | |
1212 | OV5648_AEC_CTRL0_START_SEL_EN); |
1213 | if (ret) |
1214 | return ret; |
1215 | |
1216 | return ov5648_write(sensor, OV5648_MANUAL_CTRL_REG, |
1217 | OV5648_MANUAL_CTRL_FRAME_DELAY(1)); |
1218 | } |
1219 | |
1220 | static unsigned long ov5648_mode_pll1_rate(struct ov5648_sensor *sensor, |
1221 | const struct ov5648_pll1_config *config) |
1222 | { |
1223 | unsigned long xvclk_rate; |
1224 | unsigned long pll1_rate; |
1225 | |
1226 | xvclk_rate = clk_get_rate(clk: sensor->xvclk); |
1227 | pll1_rate = xvclk_rate * config->pll_mul; |
1228 | |
1229 | switch (config->pll_pre_div) { |
1230 | case 5: |
1231 | pll1_rate *= 3; |
1232 | pll1_rate /= 2; |
1233 | break; |
1234 | case 7: |
1235 | pll1_rate *= 5; |
1236 | pll1_rate /= 2; |
1237 | break; |
1238 | default: |
1239 | pll1_rate /= config->pll_pre_div; |
1240 | break; |
1241 | } |
1242 | |
1243 | return pll1_rate; |
1244 | } |
1245 | |
1246 | static int ov5648_mode_pll1_configure(struct ov5648_sensor *sensor, |
1247 | const struct ov5648_mode *mode, |
1248 | u32 mbus_code) |
1249 | { |
1250 | const struct ov5648_pll1_config *config; |
1251 | u8 value; |
1252 | int ret; |
1253 | |
1254 | value = OV5648_PLL_CTRL0_PLL_CHARGE_PUMP(1); |
1255 | |
1256 | switch (mbus_code) { |
1257 | case MEDIA_BUS_FMT_SBGGR8_1X8: |
1258 | config = mode->pll1_config[0]; |
1259 | value |= OV5648_PLL_CTRL0_BITS(8); |
1260 | break; |
1261 | case MEDIA_BUS_FMT_SBGGR10_1X10: |
1262 | config = mode->pll1_config[1]; |
1263 | value |= OV5648_PLL_CTRL0_BITS(10); |
1264 | break; |
1265 | default: |
1266 | return -EINVAL; |
1267 | } |
1268 | |
1269 | ret = ov5648_write(sensor, OV5648_PLL_CTRL0_REG, value); |
1270 | if (ret) |
1271 | return ret; |
1272 | |
1273 | ret = ov5648_write(sensor, OV5648_PLL_DIV_REG, |
1274 | OV5648_PLL_DIV_ROOT_DIV(config->root_div) | |
1275 | OV5648_PLL_DIV_PLL_PRE_DIV(config->pll_pre_div)); |
1276 | if (ret) |
1277 | return ret; |
1278 | |
1279 | ret = ov5648_write(sensor, OV5648_PLL_MUL_REG, |
1280 | OV5648_PLL_MUL(config->pll_mul)); |
1281 | if (ret) |
1282 | return ret; |
1283 | |
1284 | ret = ov5648_write(sensor, OV5648_PLL_CTRL1_REG, |
1285 | OV5648_PLL_CTRL1_SYS_DIV(config->sys_div) | |
1286 | OV5648_PLL_CTRL1_MIPI_DIV(config->mipi_div)); |
1287 | if (ret) |
1288 | return ret; |
1289 | |
1290 | return ov5648_write(sensor, OV5648_SRB_CTRL_REG, |
1291 | OV5648_SRB_CTRL_SCLK_DIV(config->sclk_div) | |
1292 | OV5648_SRB_CTRL_SCLK_ARBITER_EN); |
1293 | } |
1294 | |
1295 | static int ov5648_mode_pll2_configure(struct ov5648_sensor *sensor, |
1296 | const struct ov5648_mode *mode) |
1297 | { |
1298 | const struct ov5648_pll2_config *config = mode->pll2_config; |
1299 | int ret; |
1300 | |
1301 | ret = ov5648_write(sensor, OV5648_PLLS_DIV_REG, |
1302 | OV5648_PLLS_DIV_PLLS_PRE_DIV(config->plls_pre_div) | |
1303 | OV5648_PLLS_DIV_PLLS_DIV_R(config->plls_div_r) | |
1304 | OV5648_PLLS_DIV_PLLS_SEL_DIV(config->sel_div)); |
1305 | if (ret) |
1306 | return ret; |
1307 | |
1308 | ret = ov5648_write(sensor, OV5648_PLLS_MUL_REG, |
1309 | OV5648_PLLS_MUL(config->plls_mul)); |
1310 | if (ret) |
1311 | return ret; |
1312 | |
1313 | return ov5648_write(sensor, OV5648_PLLS_CTRL_REG, |
1314 | OV5648_PLLS_CTRL_PLL_CHARGE_PUMP(1) | |
1315 | OV5648_PLLS_CTRL_SYS_DIV(config->sys_div)); |
1316 | } |
1317 | |
1318 | static int ov5648_mode_configure(struct ov5648_sensor *sensor, |
1319 | const struct ov5648_mode *mode, u32 mbus_code) |
1320 | { |
1321 | int ret; |
1322 | |
1323 | /* Crop Start X */ |
1324 | |
1325 | ret = ov5648_write(sensor, OV5648_CROP_START_X_H_REG, |
1326 | OV5648_CROP_START_X_H(mode->crop_start_x)); |
1327 | if (ret) |
1328 | return ret; |
1329 | |
1330 | ret = ov5648_write(sensor, OV5648_CROP_START_X_L_REG, |
1331 | OV5648_CROP_START_X_L(mode->crop_start_x)); |
1332 | if (ret) |
1333 | return ret; |
1334 | |
1335 | /* Offset X */ |
1336 | |
1337 | ret = ov5648_write(sensor, OV5648_OFFSET_X_H_REG, |
1338 | OV5648_OFFSET_X_H(mode->offset_x)); |
1339 | if (ret) |
1340 | return ret; |
1341 | |
1342 | ret = ov5648_write(sensor, OV5648_OFFSET_X_L_REG, |
1343 | OV5648_OFFSET_X_L(mode->offset_x)); |
1344 | if (ret) |
1345 | return ret; |
1346 | |
1347 | /* Output Size X */ |
1348 | |
1349 | ret = ov5648_write(sensor, OV5648_OUTPUT_SIZE_X_H_REG, |
1350 | OV5648_OUTPUT_SIZE_X_H(mode->output_size_x)); |
1351 | if (ret) |
1352 | return ret; |
1353 | |
1354 | ret = ov5648_write(sensor, OV5648_OUTPUT_SIZE_X_L_REG, |
1355 | OV5648_OUTPUT_SIZE_X_L(mode->output_size_x)); |
1356 | if (ret) |
1357 | return ret; |
1358 | |
1359 | /* Crop End X */ |
1360 | |
1361 | ret = ov5648_write(sensor, OV5648_CROP_END_X_H_REG, |
1362 | OV5648_CROP_END_X_H(mode->crop_end_x)); |
1363 | if (ret) |
1364 | return ret; |
1365 | |
1366 | ret = ov5648_write(sensor, OV5648_CROP_END_X_L_REG, |
1367 | OV5648_CROP_END_X_L(mode->crop_end_x)); |
1368 | if (ret) |
1369 | return ret; |
1370 | |
1371 | /* Horizontal Total Size */ |
1372 | |
1373 | ret = ov5648_write(sensor, OV5648_HTS_H_REG, OV5648_HTS_H(mode->hts)); |
1374 | if (ret) |
1375 | return ret; |
1376 | |
1377 | ret = ov5648_write(sensor, OV5648_HTS_L_REG, OV5648_HTS_L(mode->hts)); |
1378 | if (ret) |
1379 | return ret; |
1380 | |
1381 | /* Crop Start Y */ |
1382 | |
1383 | ret = ov5648_write(sensor, OV5648_CROP_START_Y_H_REG, |
1384 | OV5648_CROP_START_Y_H(mode->crop_start_y)); |
1385 | if (ret) |
1386 | return ret; |
1387 | |
1388 | ret = ov5648_write(sensor, OV5648_CROP_START_Y_L_REG, |
1389 | OV5648_CROP_START_Y_L(mode->crop_start_y)); |
1390 | if (ret) |
1391 | return ret; |
1392 | |
1393 | /* Offset Y */ |
1394 | |
1395 | ret = ov5648_write(sensor, OV5648_OFFSET_Y_H_REG, |
1396 | OV5648_OFFSET_Y_H(mode->offset_y)); |
1397 | if (ret) |
1398 | return ret; |
1399 | |
1400 | ret = ov5648_write(sensor, OV5648_OFFSET_Y_L_REG, |
1401 | OV5648_OFFSET_Y_L(mode->offset_y)); |
1402 | if (ret) |
1403 | return ret; |
1404 | |
1405 | /* Output Size Y */ |
1406 | |
1407 | ret = ov5648_write(sensor, OV5648_OUTPUT_SIZE_Y_H_REG, |
1408 | OV5648_OUTPUT_SIZE_Y_H(mode->output_size_y)); |
1409 | if (ret) |
1410 | return ret; |
1411 | |
1412 | ret = ov5648_write(sensor, OV5648_OUTPUT_SIZE_Y_L_REG, |
1413 | OV5648_OUTPUT_SIZE_Y_L(mode->output_size_y)); |
1414 | if (ret) |
1415 | return ret; |
1416 | |
1417 | /* Crop End Y */ |
1418 | |
1419 | ret = ov5648_write(sensor, OV5648_CROP_END_Y_H_REG, |
1420 | OV5648_CROP_END_Y_H(mode->crop_end_y)); |
1421 | if (ret) |
1422 | return ret; |
1423 | |
1424 | ret = ov5648_write(sensor, OV5648_CROP_END_Y_L_REG, |
1425 | OV5648_CROP_END_Y_L(mode->crop_end_y)); |
1426 | if (ret) |
1427 | return ret; |
1428 | |
1429 | /* Vertical Total Size */ |
1430 | |
1431 | ret = ov5648_write(sensor, OV5648_VTS_H_REG, OV5648_VTS_H(mode->vts)); |
1432 | if (ret) |
1433 | return ret; |
1434 | |
1435 | ret = ov5648_write(sensor, OV5648_VTS_L_REG, OV5648_VTS_L(mode->vts)); |
1436 | if (ret) |
1437 | return ret; |
1438 | |
1439 | /* Flip/Mirror/Binning */ |
1440 | |
1441 | /* |
1442 | * A debug bit is enabled by default and needs to be cleared for |
1443 | * subsampling to work. |
1444 | */ |
1445 | ret = ov5648_update_bits(sensor, OV5648_TC20_REG, |
1446 | OV5648_TC20_DEBUG | |
1447 | OV5648_TC20_BINNING_VERT_EN, |
1448 | bits: mode->binning_y ? OV5648_TC20_BINNING_VERT_EN : |
1449 | 0); |
1450 | if (ret) |
1451 | return ret; |
1452 | |
1453 | ret = ov5648_update_bits(sensor, OV5648_TC21_REG, |
1454 | OV5648_TC21_BINNING_HORZ_EN, |
1455 | bits: mode->binning_x ? OV5648_TC21_BINNING_HORZ_EN : |
1456 | 0); |
1457 | if (ret) |
1458 | return ret; |
1459 | |
1460 | ret = ov5648_write(sensor, OV5648_SUB_INC_X_REG, |
1461 | OV5648_SUB_INC_X_ODD(mode->inc_x_odd) | |
1462 | OV5648_SUB_INC_X_EVEN(mode->inc_x_even)); |
1463 | if (ret) |
1464 | return ret; |
1465 | |
1466 | ret = ov5648_write(sensor, OV5648_SUB_INC_Y_REG, |
1467 | OV5648_SUB_INC_Y_ODD(mode->inc_y_odd) | |
1468 | OV5648_SUB_INC_Y_EVEN(mode->inc_y_even)); |
1469 | if (ret) |
1470 | return ret; |
1471 | |
1472 | /* PLLs */ |
1473 | |
1474 | ret = ov5648_mode_pll1_configure(sensor, mode, mbus_code); |
1475 | if (ret) |
1476 | return ret; |
1477 | |
1478 | ret = ov5648_mode_pll2_configure(sensor, mode); |
1479 | if (ret) |
1480 | return ret; |
1481 | |
1482 | /* Extra registers */ |
1483 | |
1484 | if (mode->register_values) { |
1485 | ret = ov5648_write_sequence(sensor, sequence: mode->register_values, |
1486 | sequence_count: mode->register_values_count); |
1487 | if (ret) |
1488 | return ret; |
1489 | } |
1490 | |
1491 | return 0; |
1492 | } |
1493 | |
1494 | static unsigned long ov5648_mode_mipi_clk_rate(struct ov5648_sensor *sensor, |
1495 | const struct ov5648_mode *mode, |
1496 | u32 mbus_code) |
1497 | { |
1498 | const struct ov5648_pll1_config *config; |
1499 | unsigned long pll1_rate; |
1500 | |
1501 | switch (mbus_code) { |
1502 | case MEDIA_BUS_FMT_SBGGR8_1X8: |
1503 | config = mode->pll1_config[0]; |
1504 | break; |
1505 | case MEDIA_BUS_FMT_SBGGR10_1X10: |
1506 | config = mode->pll1_config[1]; |
1507 | break; |
1508 | default: |
1509 | return 0; |
1510 | } |
1511 | |
1512 | pll1_rate = ov5648_mode_pll1_rate(sensor, config); |
1513 | |
1514 | return pll1_rate / config->sys_div / config->mipi_div / 2; |
1515 | } |
1516 | |
1517 | /* Exposure */ |
1518 | |
1519 | static int ov5648_exposure_auto_configure(struct ov5648_sensor *sensor, |
1520 | bool enable) |
1521 | { |
1522 | return ov5648_update_bits(sensor, OV5648_MANUAL_CTRL_REG, |
1523 | OV5648_MANUAL_CTRL_AEC_MANUAL_EN, |
1524 | bits: enable ? 0 : OV5648_MANUAL_CTRL_AEC_MANUAL_EN); |
1525 | } |
1526 | |
1527 | static int ov5648_exposure_configure(struct ov5648_sensor *sensor, u32 exposure) |
1528 | { |
1529 | struct ov5648_ctrls *ctrls = &sensor->ctrls; |
1530 | int ret; |
1531 | |
1532 | if (ctrls->exposure_auto->val != V4L2_EXPOSURE_MANUAL) |
1533 | return -EINVAL; |
1534 | |
1535 | ret = ov5648_write(sensor, OV5648_EXPOSURE_CTRL_HH_REG, |
1536 | OV5648_EXPOSURE_CTRL_HH(exposure)); |
1537 | if (ret) |
1538 | return ret; |
1539 | |
1540 | ret = ov5648_write(sensor, OV5648_EXPOSURE_CTRL_H_REG, |
1541 | OV5648_EXPOSURE_CTRL_H(exposure)); |
1542 | if (ret) |
1543 | return ret; |
1544 | |
1545 | return ov5648_write(sensor, OV5648_EXPOSURE_CTRL_L_REG, |
1546 | OV5648_EXPOSURE_CTRL_L(exposure)); |
1547 | } |
1548 | |
1549 | static int ov5648_exposure_value(struct ov5648_sensor *sensor, |
1550 | u32 *exposure) |
1551 | { |
1552 | u8 exposure_hh = 0, exposure_h = 0, exposure_l = 0; |
1553 | int ret; |
1554 | |
1555 | ret = ov5648_read(sensor, OV5648_EXPOSURE_CTRL_HH_REG, value: &exposure_hh); |
1556 | if (ret) |
1557 | return ret; |
1558 | |
1559 | ret = ov5648_read(sensor, OV5648_EXPOSURE_CTRL_H_REG, value: &exposure_h); |
1560 | if (ret) |
1561 | return ret; |
1562 | |
1563 | ret = ov5648_read(sensor, OV5648_EXPOSURE_CTRL_L_REG, value: &exposure_l); |
1564 | if (ret) |
1565 | return ret; |
1566 | |
1567 | *exposure = OV5648_EXPOSURE_CTRL_HH_VALUE((u32)exposure_hh) | |
1568 | OV5648_EXPOSURE_CTRL_H_VALUE((u32)exposure_h) | |
1569 | OV5648_EXPOSURE_CTRL_L_VALUE((u32)exposure_l); |
1570 | |
1571 | return 0; |
1572 | } |
1573 | |
1574 | /* Gain */ |
1575 | |
1576 | static int ov5648_gain_auto_configure(struct ov5648_sensor *sensor, bool enable) |
1577 | { |
1578 | return ov5648_update_bits(sensor, OV5648_MANUAL_CTRL_REG, |
1579 | OV5648_MANUAL_CTRL_AGC_MANUAL_EN, |
1580 | bits: enable ? 0 : OV5648_MANUAL_CTRL_AGC_MANUAL_EN); |
1581 | } |
1582 | |
1583 | static int ov5648_gain_configure(struct ov5648_sensor *sensor, u32 gain) |
1584 | { |
1585 | struct ov5648_ctrls *ctrls = &sensor->ctrls; |
1586 | int ret; |
1587 | |
1588 | if (ctrls->gain_auto->val) |
1589 | return -EINVAL; |
1590 | |
1591 | ret = ov5648_write(sensor, OV5648_GAIN_CTRL_H_REG, |
1592 | OV5648_GAIN_CTRL_H(gain)); |
1593 | if (ret) |
1594 | return ret; |
1595 | |
1596 | return ov5648_write(sensor, OV5648_GAIN_CTRL_L_REG, |
1597 | OV5648_GAIN_CTRL_L(gain)); |
1598 | } |
1599 | |
1600 | static int ov5648_gain_value(struct ov5648_sensor *sensor, u32 *gain) |
1601 | { |
1602 | u8 gain_h = 0, gain_l = 0; |
1603 | int ret; |
1604 | |
1605 | ret = ov5648_read(sensor, OV5648_GAIN_CTRL_H_REG, value: &gain_h); |
1606 | if (ret) |
1607 | return ret; |
1608 | |
1609 | ret = ov5648_read(sensor, OV5648_GAIN_CTRL_L_REG, value: &gain_l); |
1610 | if (ret) |
1611 | return ret; |
1612 | |
1613 | *gain = OV5648_GAIN_CTRL_H_VALUE((u32)gain_h) | |
1614 | OV5648_GAIN_CTRL_L_VALUE((u32)gain_l); |
1615 | |
1616 | return 0; |
1617 | } |
1618 | |
1619 | /* White Balance */ |
1620 | |
1621 | static int ov5648_white_balance_auto_configure(struct ov5648_sensor *sensor, |
1622 | bool enable) |
1623 | { |
1624 | return ov5648_write(sensor, OV5648_AWB_CTRL_REG, |
1625 | value: enable ? 0 : OV5648_AWB_CTRL_GAIN_MANUAL_EN); |
1626 | } |
1627 | |
1628 | static int ov5648_white_balance_configure(struct ov5648_sensor *sensor, |
1629 | u32 red_balance, u32 blue_balance) |
1630 | { |
1631 | struct ov5648_ctrls *ctrls = &sensor->ctrls; |
1632 | int ret; |
1633 | |
1634 | if (ctrls->white_balance_auto->val) |
1635 | return -EINVAL; |
1636 | |
1637 | ret = ov5648_write(sensor, OV5648_GAIN_RED_MAN_H_REG, |
1638 | OV5648_GAIN_RED_MAN_H(red_balance)); |
1639 | if (ret) |
1640 | return ret; |
1641 | |
1642 | ret = ov5648_write(sensor, OV5648_GAIN_RED_MAN_L_REG, |
1643 | OV5648_GAIN_RED_MAN_L(red_balance)); |
1644 | if (ret) |
1645 | return ret; |
1646 | |
1647 | ret = ov5648_write(sensor, OV5648_GAIN_BLUE_MAN_H_REG, |
1648 | OV5648_GAIN_BLUE_MAN_H(blue_balance)); |
1649 | if (ret) |
1650 | return ret; |
1651 | |
1652 | return ov5648_write(sensor, OV5648_GAIN_BLUE_MAN_L_REG, |
1653 | OV5648_GAIN_BLUE_MAN_L(blue_balance)); |
1654 | } |
1655 | |
1656 | /* Flip */ |
1657 | |
1658 | static int ov5648_flip_vert_configure(struct ov5648_sensor *sensor, bool enable) |
1659 | { |
1660 | u8 bits = OV5648_TC20_FLIP_VERT_ISP_EN | |
1661 | OV5648_TC20_FLIP_VERT_SENSOR_EN; |
1662 | |
1663 | return ov5648_update_bits(sensor, OV5648_TC20_REG, mask: bits, |
1664 | bits: enable ? bits : 0); |
1665 | } |
1666 | |
1667 | static int ov5648_flip_horz_configure(struct ov5648_sensor *sensor, bool enable) |
1668 | { |
1669 | u8 bits = OV5648_TC21_FLIP_HORZ_ISP_EN | |
1670 | OV5648_TC21_FLIP_HORZ_SENSOR_EN; |
1671 | |
1672 | return ov5648_update_bits(sensor, OV5648_TC21_REG, mask: bits, |
1673 | bits: enable ? bits : 0); |
1674 | } |
1675 | |
1676 | /* Test Pattern */ |
1677 | |
1678 | static int ov5648_test_pattern_configure(struct ov5648_sensor *sensor, |
1679 | unsigned int index) |
1680 | { |
1681 | if (index >= ARRAY_SIZE(ov5648_test_pattern_bits)) |
1682 | return -EINVAL; |
1683 | |
1684 | return ov5648_write(sensor, OV5648_ISP_CTRL3D_REG, |
1685 | value: ov5648_test_pattern_bits[index]); |
1686 | } |
1687 | |
1688 | /* State */ |
1689 | |
1690 | static int ov5648_state_mipi_configure(struct ov5648_sensor *sensor, |
1691 | const struct ov5648_mode *mode, |
1692 | u32 mbus_code) |
1693 | { |
1694 | struct ov5648_ctrls *ctrls = &sensor->ctrls; |
1695 | struct v4l2_mbus_config_mipi_csi2 *bus_mipi_csi2 = |
1696 | &sensor->endpoint.bus.mipi_csi2; |
1697 | unsigned long mipi_clk_rate; |
1698 | unsigned int bits_per_sample; |
1699 | unsigned int lanes_count; |
1700 | unsigned int i, j; |
1701 | s64 mipi_pixel_rate; |
1702 | |
1703 | mipi_clk_rate = ov5648_mode_mipi_clk_rate(sensor, mode, mbus_code); |
1704 | if (!mipi_clk_rate) |
1705 | return -EINVAL; |
1706 | |
1707 | for (i = 0; i < ARRAY_SIZE(ov5648_link_freq_menu); i++) { |
1708 | s64 freq = ov5648_link_freq_menu[i]; |
1709 | |
1710 | if (freq == mipi_clk_rate) |
1711 | break; |
1712 | } |
1713 | |
1714 | for (j = 0; j < sensor->endpoint.nr_of_link_frequencies; j++) { |
1715 | u64 freq = sensor->endpoint.link_frequencies[j]; |
1716 | |
1717 | if (freq == mipi_clk_rate) |
1718 | break; |
1719 | } |
1720 | |
1721 | if (i == ARRAY_SIZE(ov5648_link_freq_menu)) { |
1722 | dev_err(sensor->dev, |
1723 | "failed to find %lu clk rate in link freq\n" , |
1724 | mipi_clk_rate); |
1725 | } else if (j == sensor->endpoint.nr_of_link_frequencies) { |
1726 | dev_err(sensor->dev, |
1727 | "failed to find %lu clk rate in endpoint link-frequencies\n" , |
1728 | mipi_clk_rate); |
1729 | } else { |
1730 | __v4l2_ctrl_s_ctrl(ctrl: ctrls->link_freq, val: i); |
1731 | } |
1732 | |
1733 | switch (mbus_code) { |
1734 | case MEDIA_BUS_FMT_SBGGR8_1X8: |
1735 | bits_per_sample = 8; |
1736 | break; |
1737 | case MEDIA_BUS_FMT_SBGGR10_1X10: |
1738 | bits_per_sample = 10; |
1739 | break; |
1740 | default: |
1741 | return -EINVAL; |
1742 | } |
1743 | |
1744 | lanes_count = bus_mipi_csi2->num_data_lanes; |
1745 | mipi_pixel_rate = mipi_clk_rate * 2 * lanes_count / bits_per_sample; |
1746 | |
1747 | __v4l2_ctrl_s_ctrl_int64(ctrl: ctrls->pixel_rate, val: mipi_pixel_rate); |
1748 | |
1749 | return 0; |
1750 | } |
1751 | |
1752 | static int ov5648_state_configure(struct ov5648_sensor *sensor, |
1753 | const struct ov5648_mode *mode, |
1754 | u32 mbus_code) |
1755 | { |
1756 | int ret; |
1757 | |
1758 | if (sensor->state.streaming) |
1759 | return -EBUSY; |
1760 | |
1761 | /* State will be configured at first power on otherwise. */ |
1762 | if (pm_runtime_enabled(dev: sensor->dev) && |
1763 | !pm_runtime_suspended(dev: sensor->dev)) { |
1764 | ret = ov5648_mode_configure(sensor, mode, mbus_code); |
1765 | if (ret) |
1766 | return ret; |
1767 | } |
1768 | |
1769 | ret = ov5648_state_mipi_configure(sensor, mode, mbus_code); |
1770 | if (ret) |
1771 | return ret; |
1772 | |
1773 | sensor->state.mode = mode; |
1774 | sensor->state.mbus_code = mbus_code; |
1775 | |
1776 | return 0; |
1777 | } |
1778 | |
1779 | static int ov5648_state_init(struct ov5648_sensor *sensor) |
1780 | { |
1781 | int ret; |
1782 | |
1783 | mutex_lock(&sensor->mutex); |
1784 | ret = ov5648_state_configure(sensor, mode: &ov5648_modes[0], |
1785 | mbus_code: ov5648_mbus_codes[0]); |
1786 | mutex_unlock(lock: &sensor->mutex); |
1787 | |
1788 | return ret; |
1789 | } |
1790 | |
1791 | /* Sensor Base */ |
1792 | |
1793 | static int ov5648_sensor_init(struct ov5648_sensor *sensor) |
1794 | { |
1795 | int ret; |
1796 | |
1797 | ret = ov5648_sw_reset(sensor); |
1798 | if (ret) { |
1799 | dev_err(sensor->dev, "failed to perform sw reset\n" ); |
1800 | return ret; |
1801 | } |
1802 | |
1803 | ret = ov5648_sw_standby(sensor, standby: 1); |
1804 | if (ret) { |
1805 | dev_err(sensor->dev, "failed to set sensor standby\n" ); |
1806 | return ret; |
1807 | } |
1808 | |
1809 | ret = ov5648_chip_id_check(sensor); |
1810 | if (ret) { |
1811 | dev_err(sensor->dev, "failed to check sensor chip id\n" ); |
1812 | return ret; |
1813 | } |
1814 | |
1815 | ret = ov5648_avdd_internal_power(sensor, on: !sensor->avdd); |
1816 | if (ret) { |
1817 | dev_err(sensor->dev, "failed to set internal avdd power\n" ); |
1818 | return ret; |
1819 | } |
1820 | |
1821 | ret = ov5648_write_sequence(sensor, sequence: ov5648_init_sequence, |
1822 | ARRAY_SIZE(ov5648_init_sequence)); |
1823 | if (ret) { |
1824 | dev_err(sensor->dev, "failed to write init sequence\n" ); |
1825 | return ret; |
1826 | } |
1827 | |
1828 | ret = ov5648_pad_configure(sensor); |
1829 | if (ret) { |
1830 | dev_err(sensor->dev, "failed to configure pad\n" ); |
1831 | return ret; |
1832 | } |
1833 | |
1834 | ret = ov5648_mipi_configure(sensor); |
1835 | if (ret) { |
1836 | dev_err(sensor->dev, "failed to configure MIPI\n" ); |
1837 | return ret; |
1838 | } |
1839 | |
1840 | ret = ov5648_isp_configure(sensor); |
1841 | if (ret) { |
1842 | dev_err(sensor->dev, "failed to configure ISP\n" ); |
1843 | return ret; |
1844 | } |
1845 | |
1846 | ret = ov5648_black_level_configure(sensor); |
1847 | if (ret) { |
1848 | dev_err(sensor->dev, "failed to configure black level\n" ); |
1849 | return ret; |
1850 | } |
1851 | |
1852 | /* Configure current mode. */ |
1853 | ret = ov5648_state_configure(sensor, mode: sensor->state.mode, |
1854 | mbus_code: sensor->state.mbus_code); |
1855 | if (ret) { |
1856 | dev_err(sensor->dev, "failed to configure state\n" ); |
1857 | return ret; |
1858 | } |
1859 | |
1860 | return 0; |
1861 | } |
1862 | |
1863 | static int ov5648_sensor_power(struct ov5648_sensor *sensor, bool on) |
1864 | { |
1865 | /* Keep initialized to zero for disable label. */ |
1866 | int ret = 0; |
1867 | |
1868 | /* |
1869 | * General notes about the power sequence: |
1870 | * - power-down GPIO must be active (low) during power-on; |
1871 | * - reset GPIO state does not matter during power-on; |
1872 | * - XVCLK must be provided 1 ms before register access; |
1873 | * - 10 ms are needed between power-down deassert and register access. |
1874 | */ |
1875 | |
1876 | /* Note that regulator-and-GPIO-based power is untested. */ |
1877 | if (on) { |
1878 | gpiod_set_value_cansleep(desc: sensor->reset, value: 1); |
1879 | gpiod_set_value_cansleep(desc: sensor->powerdown, value: 1); |
1880 | |
1881 | ret = regulator_enable(regulator: sensor->dovdd); |
1882 | if (ret) { |
1883 | dev_err(sensor->dev, |
1884 | "failed to enable DOVDD regulator\n" ); |
1885 | goto disable; |
1886 | } |
1887 | |
1888 | if (sensor->avdd) { |
1889 | ret = regulator_enable(regulator: sensor->avdd); |
1890 | if (ret) { |
1891 | dev_err(sensor->dev, |
1892 | "failed to enable AVDD regulator\n" ); |
1893 | goto disable; |
1894 | } |
1895 | } |
1896 | |
1897 | ret = regulator_enable(regulator: sensor->dvdd); |
1898 | if (ret) { |
1899 | dev_err(sensor->dev, |
1900 | "failed to enable DVDD regulator\n" ); |
1901 | goto disable; |
1902 | } |
1903 | |
1904 | /* According to OV5648 power up diagram. */ |
1905 | usleep_range(min: 5000, max: 10000); |
1906 | |
1907 | ret = clk_prepare_enable(clk: sensor->xvclk); |
1908 | if (ret) { |
1909 | dev_err(sensor->dev, "failed to enable XVCLK clock\n" ); |
1910 | goto disable; |
1911 | } |
1912 | |
1913 | gpiod_set_value_cansleep(desc: sensor->reset, value: 0); |
1914 | gpiod_set_value_cansleep(desc: sensor->powerdown, value: 0); |
1915 | |
1916 | usleep_range(min: 20000, max: 25000); |
1917 | } else { |
1918 | disable: |
1919 | gpiod_set_value_cansleep(desc: sensor->powerdown, value: 1); |
1920 | gpiod_set_value_cansleep(desc: sensor->reset, value: 1); |
1921 | |
1922 | clk_disable_unprepare(clk: sensor->xvclk); |
1923 | |
1924 | regulator_disable(regulator: sensor->dvdd); |
1925 | |
1926 | if (sensor->avdd) |
1927 | regulator_disable(regulator: sensor->avdd); |
1928 | |
1929 | regulator_disable(regulator: sensor->dovdd); |
1930 | } |
1931 | |
1932 | return ret; |
1933 | } |
1934 | |
1935 | /* Controls */ |
1936 | |
1937 | static int ov5648_g_volatile_ctrl(struct v4l2_ctrl *ctrl) |
1938 | { |
1939 | struct v4l2_subdev *subdev = ov5648_ctrl_subdev(ctrl); |
1940 | struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); |
1941 | struct ov5648_ctrls *ctrls = &sensor->ctrls; |
1942 | int ret; |
1943 | |
1944 | switch (ctrl->id) { |
1945 | case V4L2_CID_EXPOSURE_AUTO: |
1946 | ret = ov5648_exposure_value(sensor, exposure: &ctrls->exposure->val); |
1947 | if (ret) |
1948 | return ret; |
1949 | break; |
1950 | case V4L2_CID_AUTOGAIN: |
1951 | ret = ov5648_gain_value(sensor, gain: &ctrls->gain->val); |
1952 | if (ret) |
1953 | return ret; |
1954 | break; |
1955 | default: |
1956 | return -EINVAL; |
1957 | } |
1958 | |
1959 | return 0; |
1960 | } |
1961 | |
1962 | static int ov5648_s_ctrl(struct v4l2_ctrl *ctrl) |
1963 | { |
1964 | struct v4l2_subdev *subdev = ov5648_ctrl_subdev(ctrl); |
1965 | struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); |
1966 | struct ov5648_ctrls *ctrls = &sensor->ctrls; |
1967 | unsigned int index; |
1968 | bool enable; |
1969 | int ret; |
1970 | |
1971 | /* Wait for the sensor to be on before setting controls. */ |
1972 | if (pm_runtime_suspended(dev: sensor->dev)) |
1973 | return 0; |
1974 | |
1975 | switch (ctrl->id) { |
1976 | case V4L2_CID_EXPOSURE_AUTO: |
1977 | enable = ctrl->val == V4L2_EXPOSURE_AUTO; |
1978 | |
1979 | ret = ov5648_exposure_auto_configure(sensor, enable); |
1980 | if (ret) |
1981 | return ret; |
1982 | |
1983 | if (!enable && ctrls->exposure->is_new) { |
1984 | ret = ov5648_exposure_configure(sensor, |
1985 | exposure: ctrls->exposure->val); |
1986 | if (ret) |
1987 | return ret; |
1988 | } |
1989 | break; |
1990 | case V4L2_CID_AUTOGAIN: |
1991 | enable = !!ctrl->val; |
1992 | |
1993 | ret = ov5648_gain_auto_configure(sensor, enable); |
1994 | if (ret) |
1995 | return ret; |
1996 | |
1997 | if (!enable) { |
1998 | ret = ov5648_gain_configure(sensor, gain: ctrls->gain->val); |
1999 | if (ret) |
2000 | return ret; |
2001 | } |
2002 | break; |
2003 | case V4L2_CID_AUTO_WHITE_BALANCE: |
2004 | enable = !!ctrl->val; |
2005 | |
2006 | ret = ov5648_white_balance_auto_configure(sensor, enable); |
2007 | if (ret) |
2008 | return ret; |
2009 | |
2010 | if (!enable) { |
2011 | ret = ov5648_white_balance_configure(sensor, |
2012 | red_balance: ctrls->red_balance->val, |
2013 | blue_balance: ctrls->blue_balance->val); |
2014 | if (ret) |
2015 | return ret; |
2016 | } |
2017 | break; |
2018 | case V4L2_CID_HFLIP: |
2019 | enable = !!ctrl->val; |
2020 | return ov5648_flip_horz_configure(sensor, enable); |
2021 | case V4L2_CID_VFLIP: |
2022 | enable = !!ctrl->val; |
2023 | return ov5648_flip_vert_configure(sensor, enable); |
2024 | case V4L2_CID_TEST_PATTERN: |
2025 | index = (unsigned int)ctrl->val; |
2026 | return ov5648_test_pattern_configure(sensor, index); |
2027 | default: |
2028 | return -EINVAL; |
2029 | } |
2030 | |
2031 | return 0; |
2032 | } |
2033 | |
2034 | static const struct v4l2_ctrl_ops ov5648_ctrl_ops = { |
2035 | .g_volatile_ctrl = ov5648_g_volatile_ctrl, |
2036 | .s_ctrl = ov5648_s_ctrl, |
2037 | }; |
2038 | |
2039 | static int ov5648_ctrls_init(struct ov5648_sensor *sensor) |
2040 | { |
2041 | struct ov5648_ctrls *ctrls = &sensor->ctrls; |
2042 | struct v4l2_ctrl_handler *handler = &ctrls->handler; |
2043 | const struct v4l2_ctrl_ops *ops = &ov5648_ctrl_ops; |
2044 | int ret; |
2045 | |
2046 | v4l2_ctrl_handler_init(handler, 32); |
2047 | |
2048 | /* Use our mutex for ctrl locking. */ |
2049 | handler->lock = &sensor->mutex; |
2050 | |
2051 | /* Exposure */ |
2052 | |
2053 | ctrls->exposure_auto = v4l2_ctrl_new_std_menu(hdl: handler, ops, |
2054 | V4L2_CID_EXPOSURE_AUTO, |
2055 | max: V4L2_EXPOSURE_MANUAL, mask: 0, |
2056 | def: V4L2_EXPOSURE_AUTO); |
2057 | |
2058 | ctrls->exposure = v4l2_ctrl_new_std(hdl: handler, ops, V4L2_CID_EXPOSURE, |
2059 | min: 16, max: 1048575, step: 16, def: 512); |
2060 | |
2061 | v4l2_ctrl_auto_cluster(ncontrols: 2, controls: &ctrls->exposure_auto, manual_val: 1, set_volatile: true); |
2062 | |
2063 | /* Gain */ |
2064 | |
2065 | ctrls->gain_auto = |
2066 | v4l2_ctrl_new_std(hdl: handler, ops, V4L2_CID_AUTOGAIN, min: 0, max: 1, step: 1, def: 1); |
2067 | |
2068 | ctrls->gain = v4l2_ctrl_new_std(hdl: handler, ops, V4L2_CID_GAIN, min: 16, max: 1023, |
2069 | step: 16, def: 16); |
2070 | |
2071 | v4l2_ctrl_auto_cluster(ncontrols: 2, controls: &ctrls->gain_auto, manual_val: 0, set_volatile: true); |
2072 | |
2073 | /* White Balance */ |
2074 | |
2075 | ctrls->white_balance_auto = |
2076 | v4l2_ctrl_new_std(hdl: handler, ops, V4L2_CID_AUTO_WHITE_BALANCE, min: 0, |
2077 | max: 1, step: 1, def: 1); |
2078 | |
2079 | ctrls->red_balance = v4l2_ctrl_new_std(hdl: handler, ops, |
2080 | V4L2_CID_RED_BALANCE, min: 0, max: 4095, |
2081 | step: 1, def: 1024); |
2082 | |
2083 | ctrls->blue_balance = v4l2_ctrl_new_std(hdl: handler, ops, |
2084 | V4L2_CID_BLUE_BALANCE, min: 0, max: 4095, |
2085 | step: 1, def: 1024); |
2086 | |
2087 | v4l2_ctrl_auto_cluster(ncontrols: 3, controls: &ctrls->white_balance_auto, manual_val: 0, set_volatile: false); |
2088 | |
2089 | /* Flip */ |
2090 | |
2091 | v4l2_ctrl_new_std(hdl: handler, ops, V4L2_CID_HFLIP, min: 0, max: 1, step: 1, def: 0); |
2092 | v4l2_ctrl_new_std(hdl: handler, ops, V4L2_CID_VFLIP, min: 0, max: 1, step: 1, def: 0); |
2093 | |
2094 | /* Test Pattern */ |
2095 | |
2096 | v4l2_ctrl_new_std_menu_items(hdl: handler, ops, V4L2_CID_TEST_PATTERN, |
2097 | ARRAY_SIZE(ov5648_test_pattern_menu) - 1, |
2098 | mask: 0, def: 0, qmenu: ov5648_test_pattern_menu); |
2099 | |
2100 | /* MIPI CSI-2 */ |
2101 | |
2102 | ctrls->link_freq = |
2103 | v4l2_ctrl_new_int_menu(hdl: handler, NULL, V4L2_CID_LINK_FREQ, |
2104 | ARRAY_SIZE(ov5648_link_freq_menu) - 1, |
2105 | def: 0, qmenu_int: ov5648_link_freq_menu); |
2106 | |
2107 | ctrls->pixel_rate = |
2108 | v4l2_ctrl_new_std(hdl: handler, NULL, V4L2_CID_PIXEL_RATE, min: 1, |
2109 | INT_MAX, step: 1, def: 1); |
2110 | |
2111 | if (handler->error) { |
2112 | ret = handler->error; |
2113 | goto error_ctrls; |
2114 | } |
2115 | |
2116 | ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE; |
2117 | ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE; |
2118 | |
2119 | ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
2120 | ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
2121 | |
2122 | sensor->subdev.ctrl_handler = handler; |
2123 | |
2124 | return 0; |
2125 | |
2126 | error_ctrls: |
2127 | v4l2_ctrl_handler_free(hdl: handler); |
2128 | |
2129 | return ret; |
2130 | } |
2131 | |
2132 | /* Subdev Video Operations */ |
2133 | |
2134 | static int ov5648_s_stream(struct v4l2_subdev *subdev, int enable) |
2135 | { |
2136 | struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); |
2137 | struct ov5648_state *state = &sensor->state; |
2138 | int ret; |
2139 | |
2140 | if (enable) { |
2141 | ret = pm_runtime_resume_and_get(dev: sensor->dev); |
2142 | if (ret < 0) |
2143 | return ret; |
2144 | } |
2145 | |
2146 | mutex_lock(&sensor->mutex); |
2147 | ret = ov5648_sw_standby(sensor, standby: !enable); |
2148 | mutex_unlock(lock: &sensor->mutex); |
2149 | |
2150 | if (ret) |
2151 | return ret; |
2152 | |
2153 | state->streaming = !!enable; |
2154 | |
2155 | if (!enable) |
2156 | pm_runtime_put(dev: sensor->dev); |
2157 | |
2158 | return 0; |
2159 | } |
2160 | |
2161 | static const struct v4l2_subdev_video_ops ov5648_subdev_video_ops = { |
2162 | .s_stream = ov5648_s_stream, |
2163 | }; |
2164 | |
2165 | /* Subdev Pad Operations */ |
2166 | |
2167 | static int ov5648_enum_mbus_code(struct v4l2_subdev *subdev, |
2168 | struct v4l2_subdev_state *sd_state, |
2169 | struct v4l2_subdev_mbus_code_enum *code_enum) |
2170 | { |
2171 | if (code_enum->index >= ARRAY_SIZE(ov5648_mbus_codes)) |
2172 | return -EINVAL; |
2173 | |
2174 | code_enum->code = ov5648_mbus_codes[code_enum->index]; |
2175 | |
2176 | return 0; |
2177 | } |
2178 | |
2179 | static void ov5648_mbus_format_fill(struct v4l2_mbus_framefmt *mbus_format, |
2180 | u32 mbus_code, |
2181 | const struct ov5648_mode *mode) |
2182 | { |
2183 | mbus_format->width = mode->output_size_x; |
2184 | mbus_format->height = mode->output_size_y; |
2185 | mbus_format->code = mbus_code; |
2186 | |
2187 | mbus_format->field = V4L2_FIELD_NONE; |
2188 | mbus_format->colorspace = V4L2_COLORSPACE_RAW; |
2189 | mbus_format->ycbcr_enc = |
2190 | V4L2_MAP_YCBCR_ENC_DEFAULT(mbus_format->colorspace); |
2191 | mbus_format->quantization = V4L2_QUANTIZATION_FULL_RANGE; |
2192 | mbus_format->xfer_func = |
2193 | V4L2_MAP_XFER_FUNC_DEFAULT(mbus_format->colorspace); |
2194 | } |
2195 | |
2196 | static int ov5648_get_fmt(struct v4l2_subdev *subdev, |
2197 | struct v4l2_subdev_state *sd_state, |
2198 | struct v4l2_subdev_format *format) |
2199 | { |
2200 | struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); |
2201 | struct v4l2_mbus_framefmt *mbus_format = &format->format; |
2202 | |
2203 | mutex_lock(&sensor->mutex); |
2204 | |
2205 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) |
2206 | *mbus_format = *v4l2_subdev_state_get_format(sd_state, |
2207 | format->pad); |
2208 | else |
2209 | ov5648_mbus_format_fill(mbus_format, mbus_code: sensor->state.mbus_code, |
2210 | mode: sensor->state.mode); |
2211 | |
2212 | mutex_unlock(lock: &sensor->mutex); |
2213 | |
2214 | return 0; |
2215 | } |
2216 | |
2217 | static int ov5648_set_fmt(struct v4l2_subdev *subdev, |
2218 | struct v4l2_subdev_state *sd_state, |
2219 | struct v4l2_subdev_format *format) |
2220 | { |
2221 | struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); |
2222 | struct v4l2_mbus_framefmt *mbus_format = &format->format; |
2223 | const struct ov5648_mode *mode; |
2224 | u32 mbus_code = 0; |
2225 | unsigned int index; |
2226 | int ret = 0; |
2227 | |
2228 | mutex_lock(&sensor->mutex); |
2229 | |
2230 | if (sensor->state.streaming) { |
2231 | ret = -EBUSY; |
2232 | goto complete; |
2233 | } |
2234 | |
2235 | /* Try to find requested mbus code. */ |
2236 | for (index = 0; index < ARRAY_SIZE(ov5648_mbus_codes); index++) { |
2237 | if (ov5648_mbus_codes[index] == mbus_format->code) { |
2238 | mbus_code = mbus_format->code; |
2239 | break; |
2240 | } |
2241 | } |
2242 | |
2243 | /* Fallback to default. */ |
2244 | if (!mbus_code) |
2245 | mbus_code = ov5648_mbus_codes[0]; |
2246 | |
2247 | /* Find the mode with nearest dimensions. */ |
2248 | mode = v4l2_find_nearest_size(ov5648_modes, ARRAY_SIZE(ov5648_modes), |
2249 | output_size_x, output_size_y, |
2250 | mbus_format->width, mbus_format->height); |
2251 | if (!mode) { |
2252 | ret = -EINVAL; |
2253 | goto complete; |
2254 | } |
2255 | |
2256 | ov5648_mbus_format_fill(mbus_format, mbus_code, mode); |
2257 | |
2258 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) |
2259 | *v4l2_subdev_state_get_format(sd_state, format->pad) = |
2260 | *mbus_format; |
2261 | else if (sensor->state.mode != mode || |
2262 | sensor->state.mbus_code != mbus_code) |
2263 | ret = ov5648_state_configure(sensor, mode, mbus_code); |
2264 | |
2265 | complete: |
2266 | mutex_unlock(lock: &sensor->mutex); |
2267 | |
2268 | return ret; |
2269 | } |
2270 | |
2271 | static int ov5648_get_frame_interval(struct v4l2_subdev *subdev, |
2272 | struct v4l2_subdev_state *sd_state, |
2273 | struct v4l2_subdev_frame_interval *interval) |
2274 | { |
2275 | struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); |
2276 | const struct ov5648_mode *mode; |
2277 | int ret = 0; |
2278 | |
2279 | /* |
2280 | * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2 |
2281 | * subdev active state API. |
2282 | */ |
2283 | if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) |
2284 | return -EINVAL; |
2285 | |
2286 | mutex_lock(&sensor->mutex); |
2287 | |
2288 | mode = sensor->state.mode; |
2289 | |
2290 | switch (sensor->state.mbus_code) { |
2291 | case MEDIA_BUS_FMT_SBGGR8_1X8: |
2292 | interval->interval = mode->frame_interval[0]; |
2293 | break; |
2294 | case MEDIA_BUS_FMT_SBGGR10_1X10: |
2295 | interval->interval = mode->frame_interval[1]; |
2296 | break; |
2297 | default: |
2298 | ret = -EINVAL; |
2299 | } |
2300 | |
2301 | mutex_unlock(lock: &sensor->mutex); |
2302 | |
2303 | return ret; |
2304 | } |
2305 | |
2306 | static int ov5648_enum_frame_size(struct v4l2_subdev *subdev, |
2307 | struct v4l2_subdev_state *sd_state, |
2308 | struct v4l2_subdev_frame_size_enum *size_enum) |
2309 | { |
2310 | const struct ov5648_mode *mode; |
2311 | |
2312 | if (size_enum->index >= ARRAY_SIZE(ov5648_modes)) |
2313 | return -EINVAL; |
2314 | |
2315 | mode = &ov5648_modes[size_enum->index]; |
2316 | |
2317 | size_enum->min_width = size_enum->max_width = mode->output_size_x; |
2318 | size_enum->min_height = size_enum->max_height = mode->output_size_y; |
2319 | |
2320 | return 0; |
2321 | } |
2322 | |
2323 | static int ov5648_enum_frame_interval(struct v4l2_subdev *subdev, |
2324 | struct v4l2_subdev_state *sd_state, |
2325 | struct v4l2_subdev_frame_interval_enum *interval_enum) |
2326 | { |
2327 | const struct ov5648_mode *mode = NULL; |
2328 | unsigned int mode_index; |
2329 | unsigned int interval_index; |
2330 | |
2331 | if (interval_enum->index > 0) |
2332 | return -EINVAL; |
2333 | |
2334 | /* |
2335 | * Multiple modes with the same dimensions may have different frame |
2336 | * intervals, so look up each relevant mode. |
2337 | */ |
2338 | for (mode_index = 0, interval_index = 0; |
2339 | mode_index < ARRAY_SIZE(ov5648_modes); mode_index++) { |
2340 | mode = &ov5648_modes[mode_index]; |
2341 | |
2342 | if (mode->output_size_x == interval_enum->width && |
2343 | mode->output_size_y == interval_enum->height) { |
2344 | if (interval_index == interval_enum->index) |
2345 | break; |
2346 | |
2347 | interval_index++; |
2348 | } |
2349 | } |
2350 | |
2351 | if (mode_index == ARRAY_SIZE(ov5648_modes)) |
2352 | return -EINVAL; |
2353 | |
2354 | switch (interval_enum->code) { |
2355 | case MEDIA_BUS_FMT_SBGGR8_1X8: |
2356 | interval_enum->interval = mode->frame_interval[0]; |
2357 | break; |
2358 | case MEDIA_BUS_FMT_SBGGR10_1X10: |
2359 | interval_enum->interval = mode->frame_interval[1]; |
2360 | break; |
2361 | default: |
2362 | return -EINVAL; |
2363 | } |
2364 | |
2365 | return 0; |
2366 | } |
2367 | |
2368 | static const struct v4l2_subdev_pad_ops ov5648_subdev_pad_ops = { |
2369 | .enum_mbus_code = ov5648_enum_mbus_code, |
2370 | .get_fmt = ov5648_get_fmt, |
2371 | .set_fmt = ov5648_set_fmt, |
2372 | .get_frame_interval = ov5648_get_frame_interval, |
2373 | .set_frame_interval = ov5648_get_frame_interval, |
2374 | .enum_frame_size = ov5648_enum_frame_size, |
2375 | .enum_frame_interval = ov5648_enum_frame_interval, |
2376 | }; |
2377 | |
2378 | static const struct v4l2_subdev_ops ov5648_subdev_ops = { |
2379 | .video = &ov5648_subdev_video_ops, |
2380 | .pad = &ov5648_subdev_pad_ops, |
2381 | }; |
2382 | |
2383 | static int ov5648_suspend(struct device *dev) |
2384 | { |
2385 | struct i2c_client *client = to_i2c_client(dev); |
2386 | struct v4l2_subdev *subdev = i2c_get_clientdata(client); |
2387 | struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); |
2388 | struct ov5648_state *state = &sensor->state; |
2389 | int ret = 0; |
2390 | |
2391 | mutex_lock(&sensor->mutex); |
2392 | |
2393 | if (state->streaming) { |
2394 | ret = ov5648_sw_standby(sensor, standby: true); |
2395 | if (ret) |
2396 | goto complete; |
2397 | } |
2398 | |
2399 | ret = ov5648_sensor_power(sensor, on: false); |
2400 | if (ret) |
2401 | ov5648_sw_standby(sensor, standby: false); |
2402 | |
2403 | complete: |
2404 | mutex_unlock(lock: &sensor->mutex); |
2405 | |
2406 | return ret; |
2407 | } |
2408 | |
2409 | static int ov5648_resume(struct device *dev) |
2410 | { |
2411 | struct i2c_client *client = to_i2c_client(dev); |
2412 | struct v4l2_subdev *subdev = i2c_get_clientdata(client); |
2413 | struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); |
2414 | struct ov5648_state *state = &sensor->state; |
2415 | int ret = 0; |
2416 | |
2417 | mutex_lock(&sensor->mutex); |
2418 | |
2419 | ret = ov5648_sensor_power(sensor, on: true); |
2420 | if (ret) |
2421 | goto complete; |
2422 | |
2423 | ret = ov5648_sensor_init(sensor); |
2424 | if (ret) |
2425 | goto error_power; |
2426 | |
2427 | ret = __v4l2_ctrl_handler_setup(hdl: &sensor->ctrls.handler); |
2428 | if (ret) |
2429 | goto error_power; |
2430 | |
2431 | if (state->streaming) { |
2432 | ret = ov5648_sw_standby(sensor, standby: false); |
2433 | if (ret) |
2434 | goto error_power; |
2435 | } |
2436 | |
2437 | goto complete; |
2438 | |
2439 | error_power: |
2440 | ov5648_sensor_power(sensor, on: false); |
2441 | |
2442 | complete: |
2443 | mutex_unlock(lock: &sensor->mutex); |
2444 | |
2445 | return ret; |
2446 | } |
2447 | |
2448 | static int ov5648_probe(struct i2c_client *client) |
2449 | { |
2450 | struct device *dev = &client->dev; |
2451 | struct fwnode_handle *handle; |
2452 | struct ov5648_sensor *sensor; |
2453 | struct v4l2_subdev *subdev; |
2454 | struct media_pad *pad; |
2455 | unsigned long rate; |
2456 | int ret; |
2457 | |
2458 | sensor = devm_kzalloc(dev, size: sizeof(*sensor), GFP_KERNEL); |
2459 | if (!sensor) |
2460 | return -ENOMEM; |
2461 | |
2462 | sensor->dev = dev; |
2463 | sensor->i2c_client = client; |
2464 | |
2465 | /* Graph Endpoint */ |
2466 | |
2467 | handle = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); |
2468 | if (!handle) { |
2469 | dev_err(dev, "unable to find endpoint node\n" ); |
2470 | return -EINVAL; |
2471 | } |
2472 | |
2473 | sensor->endpoint.bus_type = V4L2_MBUS_CSI2_DPHY; |
2474 | |
2475 | ret = v4l2_fwnode_endpoint_alloc_parse(fwnode: handle, vep: &sensor->endpoint); |
2476 | fwnode_handle_put(fwnode: handle); |
2477 | if (ret) { |
2478 | dev_err(dev, "failed to parse endpoint node\n" ); |
2479 | return ret; |
2480 | } |
2481 | |
2482 | /* GPIOs */ |
2483 | |
2484 | sensor->powerdown = devm_gpiod_get_optional(dev, con_id: "powerdown" , |
2485 | flags: GPIOD_OUT_HIGH); |
2486 | if (IS_ERR(ptr: sensor->powerdown)) { |
2487 | ret = PTR_ERR(ptr: sensor->powerdown); |
2488 | goto error_endpoint; |
2489 | } |
2490 | |
2491 | sensor->reset = devm_gpiod_get_optional(dev, con_id: "reset" , flags: GPIOD_OUT_HIGH); |
2492 | if (IS_ERR(ptr: sensor->reset)) { |
2493 | ret = PTR_ERR(ptr: sensor->reset); |
2494 | goto error_endpoint; |
2495 | } |
2496 | |
2497 | /* Regulators */ |
2498 | |
2499 | /* DVDD: digital core */ |
2500 | sensor->dvdd = devm_regulator_get(dev, id: "dvdd" ); |
2501 | if (IS_ERR(ptr: sensor->dvdd)) { |
2502 | dev_err(dev, "cannot get DVDD (digital core) regulator\n" ); |
2503 | ret = PTR_ERR(ptr: sensor->dvdd); |
2504 | goto error_endpoint; |
2505 | } |
2506 | |
2507 | /* DOVDD: digital I/O */ |
2508 | sensor->dovdd = devm_regulator_get(dev, id: "dovdd" ); |
2509 | if (IS_ERR(ptr: sensor->dovdd)) { |
2510 | dev_err(dev, "cannot get DOVDD (digital I/O) regulator\n" ); |
2511 | ret = PTR_ERR(ptr: sensor->dovdd); |
2512 | goto error_endpoint; |
2513 | } |
2514 | |
2515 | /* AVDD: analog */ |
2516 | sensor->avdd = devm_regulator_get_optional(dev, id: "avdd" ); |
2517 | if (IS_ERR(ptr: sensor->avdd)) { |
2518 | dev_info(dev, "no AVDD regulator provided, using internal\n" ); |
2519 | sensor->avdd = NULL; |
2520 | } |
2521 | |
2522 | /* External Clock */ |
2523 | |
2524 | sensor->xvclk = devm_clk_get(dev, NULL); |
2525 | if (IS_ERR(ptr: sensor->xvclk)) { |
2526 | dev_err(dev, "failed to get external clock\n" ); |
2527 | ret = PTR_ERR(ptr: sensor->xvclk); |
2528 | goto error_endpoint; |
2529 | } |
2530 | |
2531 | rate = clk_get_rate(clk: sensor->xvclk); |
2532 | if (rate != OV5648_XVCLK_RATE) { |
2533 | dev_err(dev, "clock rate %lu Hz is unsupported\n" , rate); |
2534 | ret = -EINVAL; |
2535 | goto error_endpoint; |
2536 | } |
2537 | |
2538 | /* Subdev, entity and pad */ |
2539 | |
2540 | subdev = &sensor->subdev; |
2541 | v4l2_i2c_subdev_init(sd: subdev, client, ops: &ov5648_subdev_ops); |
2542 | |
2543 | subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
2544 | subdev->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
2545 | |
2546 | pad = &sensor->pad; |
2547 | pad->flags = MEDIA_PAD_FL_SOURCE; |
2548 | |
2549 | ret = media_entity_pads_init(entity: &subdev->entity, num_pads: 1, pads: pad); |
2550 | if (ret) |
2551 | goto error_entity; |
2552 | |
2553 | /* Mutex */ |
2554 | |
2555 | mutex_init(&sensor->mutex); |
2556 | |
2557 | /* Sensor */ |
2558 | |
2559 | ret = ov5648_ctrls_init(sensor); |
2560 | if (ret) |
2561 | goto error_mutex; |
2562 | |
2563 | ret = ov5648_state_init(sensor); |
2564 | if (ret) |
2565 | goto error_ctrls; |
2566 | |
2567 | /* Runtime PM */ |
2568 | |
2569 | pm_runtime_enable(dev: sensor->dev); |
2570 | pm_runtime_set_suspended(dev: sensor->dev); |
2571 | |
2572 | /* V4L2 subdev register */ |
2573 | |
2574 | ret = v4l2_async_register_subdev_sensor(sd: subdev); |
2575 | if (ret) |
2576 | goto error_pm; |
2577 | |
2578 | return 0; |
2579 | |
2580 | error_pm: |
2581 | pm_runtime_disable(dev: sensor->dev); |
2582 | |
2583 | error_ctrls: |
2584 | v4l2_ctrl_handler_free(hdl: &sensor->ctrls.handler); |
2585 | |
2586 | error_mutex: |
2587 | mutex_destroy(lock: &sensor->mutex); |
2588 | |
2589 | error_entity: |
2590 | media_entity_cleanup(entity: &sensor->subdev.entity); |
2591 | |
2592 | error_endpoint: |
2593 | v4l2_fwnode_endpoint_free(vep: &sensor->endpoint); |
2594 | |
2595 | return ret; |
2596 | } |
2597 | |
2598 | static void ov5648_remove(struct i2c_client *client) |
2599 | { |
2600 | struct v4l2_subdev *subdev = i2c_get_clientdata(client); |
2601 | struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); |
2602 | |
2603 | v4l2_async_unregister_subdev(sd: subdev); |
2604 | pm_runtime_disable(dev: sensor->dev); |
2605 | v4l2_ctrl_handler_free(hdl: &sensor->ctrls.handler); |
2606 | mutex_destroy(lock: &sensor->mutex); |
2607 | media_entity_cleanup(entity: &subdev->entity); |
2608 | v4l2_fwnode_endpoint_free(vep: &sensor->endpoint); |
2609 | } |
2610 | |
2611 | static const struct dev_pm_ops ov5648_pm_ops = { |
2612 | SET_RUNTIME_PM_OPS(ov5648_suspend, ov5648_resume, NULL) |
2613 | }; |
2614 | |
2615 | static const struct of_device_id ov5648_of_match[] = { |
2616 | { .compatible = "ovti,ov5648" }, |
2617 | { } |
2618 | }; |
2619 | MODULE_DEVICE_TABLE(of, ov5648_of_match); |
2620 | |
2621 | static struct i2c_driver ov5648_driver = { |
2622 | .driver = { |
2623 | .name = "ov5648" , |
2624 | .of_match_table = ov5648_of_match, |
2625 | .pm = &ov5648_pm_ops, |
2626 | }, |
2627 | .probe = ov5648_probe, |
2628 | .remove = ov5648_remove, |
2629 | }; |
2630 | |
2631 | module_i2c_driver(ov5648_driver); |
2632 | |
2633 | MODULE_AUTHOR("Paul Kocialkowski <paul.kocialkowski@bootlin.com>" ); |
2634 | MODULE_DESCRIPTION("V4L2 driver for the OmniVision OV5648 image sensor" ); |
2635 | MODULE_LICENSE("GPL v2" ); |
2636 | |