1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * IMX464 driver
4 *
5 * Copyright (C) 2020 Fuzhou Rockchip Electronics Co., Ltd.
6 *
7 * V0.0X01.0X00 first version
8 * V0.0X01.0X01 add conversion gain control
9 * V0.0X01.0X02 add debug interface for conversion gain control
10 * V0.0X01.0X03 support enum sensor fmt
11 */
12
13 #include <linux/clk.h>
14 #include <linux/device.h>
15 #include <linux/delay.h>
16 #include <linux/gpio/consumer.h>
17 #include <linux/i2c.h>
18 #include <linux/module.h>
19 #include <linux/pm_runtime.h>
20 #include <linux/regulator/consumer.h>
21 #include <linux/sysfs.h>
22 #include <linux/slab.h>
23 #include <linux/version.h>
24 #include <linux/rk-camera-module.h>
25 #include <media/media-entity.h>
26 #include <media/v4l2-async.h>
27 #include <media/v4l2-ctrls.h>
28 #include <media/v4l2-subdev.h>
29 #include <media/v4l2-fwnode.h>
30 #include <media/v4l2-mediabus.h>
31 #include <linux/pinctrl/consumer.h>
32 #include <linux/rk-preisp.h>
33 #include <linux/of_graph.h>
34
35 #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03)
36
37 #ifndef V4L2_CID_DIGITAL_GAIN
38 #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
39 #endif
40
41 #define MIPI_FREQ_360M 360000000
42 #define MIPI_FREQ_445M 445600000
43 #define MIPI_FREQ_594M 594000000
44
45 #define OF_CAMERA_HDR_MODE "rockchip,camera-hdr-mode"
46
47 /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
48 #define IMX464_10BIT_HDR2_PIXEL_RATE (MIPI_FREQ_594M * 2 / 10 * 4)
49 #define IMX464_XVCLK_FREQ_37M 37125000
50 #define IMX464_XVCLK_FREQ_24M 24000000
51
52 #define CHIP_ID 0x06
53 #define IMX464_REG_CHIP_ID 0x3057
54
55 #define IMX464_REG_CTRL_MODE 0x3000
56 #define IMX464_MODE_SW_STANDBY BIT(0)
57 #define IMX464_MODE_STREAMING 0x0
58
59 #define IMX464_REG_MARSTER_MODE 0x3002
60 #define IMX464_MODE_STOP BIT(0)
61 #define IMX464_MODE_START 0x0
62
63 #define IMX464_GAIN_SWITCH_REG 0x3019
64
65 #define IMX464_LF_GAIN_REG_H 0x30E9
66 #define IMX464_LF_GAIN_REG_L 0x30E8
67
68 #define IMX464_SF1_GAIN_REG_H 0x30EB
69 #define IMX464_SF1_GAIN_REG_L 0x30EA
70
71 #define IMX464_SF2_GAIN_REG_H 0x30ED
72 #define IMX464_SF2_GAIN_REG_L 0x30EC
73
74 #define IMX464_LF_EXPO_REG_H 0x305A
75 #define IMX464_LF_EXPO_REG_M 0x3059
76 #define IMX464_LF_EXPO_REG_L 0x3058
77
78 #define IMX464_SF1_EXPO_REG_H 0x305E
79 #define IMX464_SF1_EXPO_REG_M 0x305D
80 #define IMX464_SF1_EXPO_REG_L 0x305C
81
82 #define IMX464_SF2_EXPO_REG_H 0x3062
83 #define IMX464_SF2_EXPO_REG_M 0x3061
84 #define IMX464_SF2_EXPO_REG_L 0x3060
85 #define IMX464_RHS1_DEFAULT 0x06d
86 #define IMX464_RHS1_X3_DEFAULT 0x0a3
87
88 #define IMX464_RHS1_REG_H 0x306a
89 #define IMX464_RHS1_REG_M 0x3069
90 #define IMX464_RHS1_REG_L 0x3068
91
92 #define IMX464_RHS2_REG_H 0x306E
93 #define IMX464_RHS2_REG_M 0x306D
94 #define IMX464_RHS2_REG_L 0x306C
95 #define IMX464_RHS2_X3_DEFAULT 0x0ce
96
97
98 #define IMX464_EXPOSURE_MIN 2
99 #define IMX464_EXPOSURE_STEP 1
100 #define IMX464_VTS_MAX 0x7fff
101
102 #define IMX464_GAIN_MIN 0x00
103 #define IMX464_GAIN_MAX 0xee
104 #define IMX464_GAIN_STEP 1
105 #define IMX464_GAIN_DEFAULT 0x00
106
107 #define IMX464_FETCH_GAIN_H(VAL) (((VAL) >> 8) & 0x07)
108 #define IMX464_FETCH_GAIN_L(VAL) ((VAL) & 0xFF)
109
110 #define IMX464_FETCH_EXP_H(VAL) (((VAL) >> 16) & 0x0F)
111 #define IMX464_FETCH_EXP_M(VAL) (((VAL) >> 8) & 0xFF)
112 #define IMX464_FETCH_EXP_L(VAL) ((VAL) & 0xFF)
113
114 #define IMX464_FETCH_RHS1_H(VAL) (((VAL) >> 16) & 0x0F)
115 #define IMX464_FETCH_RHS1_M(VAL) (((VAL) >> 8) & 0xFF)
116 #define IMX464_FETCH_RHS1_L(VAL) ((VAL) & 0xFF)
117
118 #define IMX464_FETCH_VTS_H(VAL) (((VAL) >> 16) & 0x0F)
119 #define IMX464_FETCH_VTS_M(VAL) (((VAL) >> 8) & 0xFF)
120 #define IMX464_FETCH_VTS_L(VAL) ((VAL) & 0xFF)
121
122 #define IMX464_GROUP_HOLD_REG 0x3001
123 #define IMX464_GROUP_HOLD_START 0x01
124 #define IMX464_GROUP_HOLD_END 0x00
125
126 #define IMX464_VTS_REG_L 0x3030
127 #define IMX464_VTS_REG_M 0x3031
128 #define IMX464_VTS_REG_H 0x3032
129
130 #define REG_NULL 0xFFFF
131
132 #define IMX464_REG_VALUE_08BIT 1
133 #define IMX464_REG_VALUE_16BIT 2
134 #define IMX464_REG_VALUE_24BIT 3
135
136 #define IMX464_BITS_PER_SAMPLE 10
137
138 #define IMX464_VREVERSE_REG 0x304f
139 #define IMX464_HREVERSE_REG 0x304e
140
141 #define BRL 1558
142 #define RHS1_MAX ((BRL * 2 - 1) / 4 * 4 + 1) // <3*BRL=2*1558 && 6n+1
143 #define SHR1_MIN 9u
144
145 /* Readout timing setting of SEF1(DOL3): RHS1 < 3 * BRL and should be 6n + 1 */
146 #define RHS1_MAX_X3 ((BRL * 3 - 1) / 6 * 6 + 1)
147 #define SHR1_MIN_X3 13u
148
149 #define USED_SYS_DEBUG
150
151 #define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default"
152 #define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep"
153
154 #define IMX464_NAME "imx464"
155
156 static const char * const IMX464_supply_names[] = {
157 "avdd", /* Analog power */
158 "dovdd", /* Digital I/O power */
159 "dvdd", /* Digital core power */
160 };
161
162 #define IMX464_NUM_SUPPLIES ARRAY_SIZE(IMX464_supply_names)
163
164 struct regval {
165 u16 addr;
166 u8 val;
167 };
168
169 struct IMX464_mode {
170 u32 bus_fmt;
171 u32 width;
172 u32 height;
173 struct v4l2_fract max_fps;
174 u32 hts_def;
175 u32 vts_def;
176 u32 exp_def;
177 u32 mipi_freq_idx;
178 u32 mclk;
179 u32 bpp;
180 const struct regval *reg_list;
181 u32 hdr_mode;
182 u32 vc[PAD_MAX];
183 };
184
185 struct IMX464 {
186 struct i2c_client *client;
187 struct clk *xvclk;
188 struct gpio_desc *reset_gpio;
189 struct gpio_desc *pwdn_gpio;
190 struct regulator_bulk_data supplies[IMX464_NUM_SUPPLIES];
191
192 struct pinctrl *pinctrl;
193 struct pinctrl_state *pins_default;
194 struct pinctrl_state *pins_sleep;
195
196 struct v4l2_subdev subdev;
197 struct media_pad pad;
198 struct v4l2_ctrl_handler ctrl_handler;
199 struct v4l2_ctrl *exposure;
200 struct v4l2_ctrl *anal_a_gain;
201 struct v4l2_ctrl *digi_gain;
202 struct v4l2_ctrl *hblank;
203 struct v4l2_ctrl *vblank;
204 struct v4l2_ctrl *pixel_rate;
205 struct v4l2_ctrl *link_freq;
206 struct mutex mutex;
207 struct v4l2_fwnode_endpoint bus_cfg;
208 bool streaming;
209 bool power_on;
210 bool has_init_exp;
211 const struct IMX464_mode *support_modes;
212 const struct IMX464_mode *cur_mode;
213 u32 module_index;
214 u32 cfg_num;
215 u32 cur_vts;
216 u32 cur_mclk;
217 const char *module_facing;
218 const char *module_name;
219 const char *len_name;
220 enum rkmodule_sync_mode sync_mode;
221 struct preisp_hdrae_exp_s init_hdrae_exp;
222 bool isHCG;
223 };
224
225 #define to_IMX464(sd) container_of(sd, struct IMX464, subdev)
226
227 /*
228 * Xclk 37.125Mhz
229 */
230 static const struct regval IMX464_global_regs[] = {
231 {REG_NULL, 0x00},
232 };
233
234 static __maybe_unused const struct regval IMX464_linear_10bit_2688x1520_2lane_37m_regs[] = {
235 {0x3000, 0x01},
236 {0x3002, 0x01},
237 {0x300C, 0x5B},
238 {0x300D, 0x40},
239 {0x3034, 0xDC},
240 {0x3035, 0x05},
241 {0x3050, 0x00},
242 {0x3058, 0x83},
243 {0x3059, 0x04},
244 {0x30BE, 0x5E},
245 {0x30E8, 0x14},
246 {0x3110, 0x02},
247 {0x314C, 0xC0},
248 {0x315A, 0x06},
249 {0x316A, 0x7E},
250 {0x319D, 0x00},
251 {0x319E, 0x02},
252 {0x31A1, 0x00},
253 {0x3288, 0x22},
254 {0x328A, 0x02},
255 {0x328C, 0xA2},
256 {0x328E, 0x22},
257 {0x3415, 0x27},
258 {0x3418, 0x27},
259 {0x3428, 0xFE},
260 {0x349E, 0x6A},
261 {0x34A2, 0x9A},
262 {0x34A4, 0x8A},
263 {0x34A6, 0x8E},
264 {0x34AA, 0xD8},
265 {0x35BC, 0x00},
266 {0x35BE, 0xFF},
267 {0x35CC, 0x1B},
268 {0x35CD, 0x00},
269 {0x35CE, 0x2A},
270 {0x35CF, 0x00},
271 {0x35DC, 0x07},
272 {0x35DE, 0x1A},
273 {0x35DF, 0x00},
274 {0x35E4, 0x2B},
275 {0x35E5, 0x00},
276 {0x35E6, 0x07},
277 {0x35E7, 0x01},
278 {0x3648, 0x01},
279 {0x3678, 0x01},
280 {0x367C, 0x69},
281 {0x367E, 0x69},
282 {0x3680, 0x69},
283 {0x3682, 0x69},
284 {0x3718, 0x1C},
285 {0x371D, 0x05},
286 {0x375D, 0x11},
287 {0x375E, 0x43},
288 {0x375F, 0x76},
289 {0x3760, 0x07},
290 {0x3768, 0x1B},
291 {0x3769, 0x1B},
292 {0x376A, 0x1A},
293 {0x376B, 0x19},
294 {0x376C, 0x17},
295 {0x376D, 0x0F},
296 {0x376E, 0x0B},
297 {0x376F, 0x0B},
298 {0x3770, 0x0B},
299 {0x3776, 0x89},
300 {0x3777, 0x00},
301 {0x3778, 0xCA},
302 {0x3779, 0x00},
303 {0x377A, 0x45},
304 {0x377B, 0x01},
305 {0x377C, 0x56},
306 {0x377D, 0x02},
307 {0x377E, 0xFE},
308 {0x377F, 0x03},
309 {0x3780, 0xFE},
310 {0x3781, 0x05},
311 {0x3782, 0xFE},
312 {0x3783, 0x06},
313 {0x3784, 0x7F},
314 {0x3788, 0x1F},
315 {0x378A, 0xCA},
316 {0x378B, 0x00},
317 {0x378C, 0x45},
318 {0x378D, 0x01},
319 {0x378E, 0x56},
320 {0x378F, 0x02},
321 {0x3790, 0xFE},
322 {0x3791, 0x03},
323 {0x3792, 0xFE},
324 {0x3793, 0x05},
325 {0x3794, 0xFE},
326 {0x3795, 0x06},
327 {0x3796, 0x7F},
328 {0x3798, 0xBF},
329 {0x3A01, 0x01},
330 {0x3A18, 0x7F},
331 {0x3A1A, 0x37},
332 {0x3A1C, 0x37},
333 {0x3A1E, 0xF7},
334 {0x3A1F, 0x00},
335 {0x3A20, 0x3F},
336 {0x3A22, 0x6F},
337 {0x3A24, 0x3F},
338 {0x3A26, 0x5F},
339 {0x3A28, 0x2F},
340 {REG_NULL, 0x00},
341 };
342
343 static __maybe_unused const struct regval IMX464_hdr_2x_10bit_2688x1520_2lane_37m_regs[] = {
344 {0x3000, 0x01},
345 {0x3002, 0x01},
346 {0x300C, 0x5B},
347 {0x300D, 0x40},
348 {0x3034, 0xDC},
349 {0x3035, 0x05},
350 {0x3048, 0x01},
351 {0x3049, 0x01},
352 {0x304A, 0x01},
353 {0x304B, 0x01},
354 {0x304C, 0x13},
355 {0x304D, 0x00},
356 {0x3050, 0x00},
357 {0x3058, 0xF4},
358 {0x3059, 0x0A},
359 {0x3068, 0x3D},
360 {0x30BE, 0x5E},
361 {0x30E8, 0x0A},
362 {0x3110, 0x02},
363 {0x314C, 0x80},//
364 {0x315A, 0x02},
365 {0x316A, 0x7E},
366 {0x319D, 0x00},
367 {0x319E, 0x01},//1188M
368 {0x31A1, 0x00},
369 {0x31D7, 0x01},
370 {0x3200, 0x10},
371 {0x3288, 0x22},
372 {0x328A, 0x02},
373 {0x328C, 0xA2},
374 {0x328E, 0x22},
375 {0x3415, 0x27},
376 {0x3418, 0x27},
377 {0x3428, 0xFE},
378 {0x349E, 0x6A},
379 {0x34A2, 0x9A},
380 {0x34A4, 0x8A},
381 {0x34A6, 0x8E},
382 {0x34AA, 0xD8},
383 {0x35BC, 0x00},
384 {0x35BE, 0xFF},
385 {0x35CC, 0x1B},
386 {0x35CD, 0x00},
387 {0x35CE, 0x2A},
388 {0x35CF, 0x00},
389 {0x35DC, 0x07},
390 {0x35DE, 0x1A},
391 {0x35DF, 0x00},
392 {0x35E4, 0x2B},
393 {0x35E5, 0x00},
394 {0x35E6, 0x07},
395 {0x35E7, 0x01},
396 {0x3648, 0x01},
397 {0x3678, 0x01},
398 {0x367C, 0x69},
399 {0x367E, 0x69},
400 {0x3680, 0x69},
401 {0x3682, 0x69},
402 {0x3718, 0x1C},
403 {0x371D, 0x05},
404 {0x375D, 0x11},
405 {0x375E, 0x43},
406 {0x375F, 0x76},
407 {0x3760, 0x07},
408 {0x3768, 0x1B},
409 {0x3769, 0x1B},
410 {0x376A, 0x1A},
411 {0x376B, 0x19},
412 {0x376C, 0x17},
413 {0x376D, 0x0F},
414 {0x376E, 0x0B},
415 {0x376F, 0x0B},
416 {0x3770, 0x0B},
417 {0x3776, 0x89},
418 {0x3777, 0x00},
419 {0x3778, 0xCA},
420 {0x3779, 0x00},
421 {0x377A, 0x45},
422 {0x377B, 0x01},
423 {0x377C, 0x56},
424 {0x377D, 0x02},
425 {0x377E, 0xFE},
426 {0x377F, 0x03},
427 {0x3780, 0xFE},
428 {0x3781, 0x05},
429 {0x3782, 0xFE},
430 {0x3783, 0x06},
431 {0x3784, 0x7F},
432 {0x3788, 0x1F},
433 {0x378A, 0xCA},
434 {0x378B, 0x00},
435 {0x378C, 0x45},
436 {0x378D, 0x01},
437 {0x378E, 0x56},
438 {0x378F, 0x02},
439 {0x3790, 0xFE},
440 {0x3791, 0x03},
441 {0x3792, 0xFE},
442 {0x3793, 0x05},
443 {0x3794, 0xFE},
444 {0x3795, 0x06},
445 {0x3796, 0x7F},
446 {0x3798, 0xBF},
447 {0x3A01, 0x01},
448 {0x3A18, 0x8F},
449 {0x3A1A, 0x4F},
450 {0x3A1C, 0x47},
451 {0x3A1E, 0x37},
452 {0x3A1F, 0x01},
453 {0x3A20, 0x4F},
454 {0x3A22, 0x87},
455 {0x3A24, 0x4F},
456 {0x3A26, 0x7F},
457 {0x3A28, 0x3F},
458 {REG_NULL, 0x00},
459 };
460
461 static const struct regval IMX464_linear_10bit_2688x1520_2lane_regs[] = {
462 {0x3000, 0x01},
463 {0x3002, 0x01},
464 {0x300C, 0x3b},
465 {0x300D, 0x2a},
466 {0x3034, 0xDC},
467 {0x3035, 0x05},
468 {0x3048, 0x00},
469 {0x3049, 0x00},
470 {0x304A, 0x03},
471 {0x304B, 0x02},
472 {0x304C, 0x14},
473 {0x304D, 0x03},
474 {0x3050, 0x00},
475 {0x3058, 0x83},
476 {0x3059, 0x04},
477 {0x3068, 0xc9},
478 {0x30BE, 0x5E},
479 {0x30E8, 0x14},
480 {0x3110, 0x02},
481 {0x314C, 0x29},
482 {0x314D, 0x01},
483 {0x315A, 0x06},
484 {0x3168, 0xA0},
485 {0x316A, 0x7E},
486 {0x319D, 0x00},
487 {0x319E, 0x02},
488 {0x31A1, 0x00},
489 {0x31D7, 0x00},
490 {0x3200, 0x11},
491 {0x3288, 0x22},
492 {0x328A, 0x02},
493 {0x328C, 0xA2},
494 {0x328E, 0x22},
495 {0x3415, 0x27},
496 {0x3418, 0x27},
497 {0x3428, 0xFE},
498 {0x349E, 0x6A},
499 {0x34A2, 0x9A},
500 {0x34A4, 0x8A},
501 {0x34A6, 0x8E},
502 {0x34AA, 0xD8},
503 {0x35BC, 0x00},
504 {0x35BE, 0xFF},
505 {0x35CC, 0x1B},
506 {0x35CD, 0x00},
507 {0x35CE, 0x2A},
508 {0x35CF, 0x00},
509 {0x35DC, 0x07},
510 {0x35DE, 0x1A},
511 {0x35DF, 0x00},
512 {0x35E4, 0x2B},
513 {0x35E5, 0x00},
514 {0x35E6, 0x07},
515 {0x35E7, 0x01},
516 {0x3648, 0x01},
517 {0x3678, 0x01},
518 {0x367C, 0x69},
519 {0x367E, 0x69},
520 {0x3680, 0x69},
521 {0x3682, 0x69},
522 {0x3718, 0x1C},
523 {0x371D, 0x05},
524 {0x375D, 0x11},
525 {0x375E, 0x43},
526 {0x375F, 0x76},
527 {0x3760, 0x07},
528 {0x3768, 0x1B},
529 {0x3769, 0x1B},
530 {0x376A, 0x1A},
531 {0x376B, 0x19},
532 {0x376C, 0x17},
533 {0x376D, 0x0F},
534 {0x376E, 0x0B},
535 {0x376F, 0x0B},
536 {0x3770, 0x0B},
537 {0x3776, 0x89},
538 {0x3777, 0x00},
539 {0x3778, 0xCA},
540 {0x3779, 0x00},
541 {0x377A, 0x45},
542 {0x377B, 0x01},
543 {0x377C, 0x56},
544 {0x377D, 0x02},
545 {0x377E, 0xFE},
546 {0x377F, 0x03},
547 {0x3780, 0xFE},
548 {0x3781, 0x05},
549 {0x3782, 0xFE},
550 {0x3783, 0x06},
551 {0x3784, 0x7F},
552 {0x3788, 0x1F},
553 {0x378A, 0xCA},
554 {0x378B, 0x00},
555 {0x378C, 0x45},
556 {0x378D, 0x01},
557 {0x378E, 0x56},
558 {0x378F, 0x02},
559 {0x3790, 0xFE},
560 {0x3791, 0x03},
561 {0x3792, 0xFE},
562 {0x3793, 0x05},
563 {0x3794, 0xFE},
564 {0x3795, 0x06},
565 {0x3796, 0x7F},
566 {0x3798, 0xBF},
567 {0x3A01, 0x01},
568 {0x3A18, 0x7F},
569 {0x3A1A, 0x37},
570 {0x3A1C, 0x37},
571 {0x3A1E, 0xF7},
572 {0x3A1F, 0x00},
573 {0x3A20, 0x3F},
574 {0x3A22, 0x6F},
575 {0x3A24, 0x3F},
576 {0x3A26, 0x5F},
577 {0x3A28, 0x2F},
578 {REG_NULL, 0x00},
579 };
580
581 static const struct regval IMX464_hdr_2x_10bit_2688x1520_2lane_regs[] = {
582 {0x3000, 0x01},
583 {0x3002, 0x01},
584 {0x300C, 0x3B},
585 {0x300D, 0x2A},
586 {0x3034, 0xDC},
587 {0x3035, 0x05},
588 {0x3048, 0x01},
589 {0x3049, 0x01},
590 {0x304A, 0x04},
591 {0x304B, 0x04},
592 {0x304C, 0x13},
593 {0x304D, 0x00},
594 {0x3050, 0x00},
595 {0x3058, 0xF4},
596 {0x3059, 0x0A},
597 {0x3068, 0x3D},
598 {0x30BE, 0x5E},
599 {0x30E8, 0x14},
600 {0x3110, 0x02},
601 {0x314C, 0x29},//
602 {0x314D, 0x01},//
603 {0x315A, 0x06},
604 {0x3168, 0xA0},
605 {0x316A, 0x7E},
606 {0x319D, 0x00},
607 {0x319E, 0x02},//1188M
608 {0x31A1, 0x00},
609 {0x31D7, 0x01},
610 {0x3200, 0x10},
611 {0x3288, 0x22},
612 {0x328A, 0x02},
613 {0x328C, 0xA2},
614 {0x328E, 0x22},
615 {0x3415, 0x27},
616 {0x3418, 0x27},
617 {0x3428, 0xFE},
618 {0x349E, 0x6A},
619 {0x34A2, 0x9A},
620 {0x34A4, 0x8A},
621 {0x34A6, 0x8E},
622 {0x34AA, 0xD8},
623 {0x35BC, 0x00},
624 {0x35BE, 0xFF},
625 {0x35CC, 0x1B},
626 {0x35CD, 0x00},
627 {0x35CE, 0x2A},
628 {0x35CF, 0x00},
629 {0x35DC, 0x07},
630 {0x35DE, 0x1A},
631 {0x35DF, 0x00},
632 {0x35E4, 0x2B},
633 {0x35E5, 0x00},
634 {0x35E6, 0x07},
635 {0x35E7, 0x01},
636 {0x3648, 0x01},
637 {0x3678, 0x01},
638 {0x367C, 0x69},
639 {0x367E, 0x69},
640 {0x3680, 0x69},
641 {0x3682, 0x69},
642 {0x3718, 0x1C},
643 {0x371D, 0x05},
644 {0x375D, 0x11},
645 {0x375E, 0x43},
646 {0x375F, 0x76},
647 {0x3760, 0x07},
648 {0x3768, 0x1B},
649 {0x3769, 0x1B},
650 {0x376A, 0x1A},
651 {0x376B, 0x19},
652 {0x376C, 0x17},
653 {0x376D, 0x0F},
654 {0x376E, 0x0B},
655 {0x376F, 0x0B},
656 {0x3770, 0x0B},
657 {0x3776, 0x89},
658 {0x3777, 0x00},
659 {0x3778, 0xCA},
660 {0x3779, 0x00},
661 {0x377A, 0x45},
662 {0x377B, 0x01},
663 {0x377C, 0x56},
664 {0x377D, 0x02},
665 {0x377E, 0xFE},
666 {0x377F, 0x03},
667 {0x3780, 0xFE},
668 {0x3781, 0x05},
669 {0x3782, 0xFE},
670 {0x3783, 0x06},
671 {0x3784, 0x7F},
672 {0x3788, 0x1F},
673 {0x378A, 0xCA},
674 {0x378B, 0x00},
675 {0x378C, 0x45},
676 {0x378D, 0x01},
677 {0x378E, 0x56},
678 {0x378F, 0x02},
679 {0x3790, 0xFE},
680 {0x3791, 0x03},
681 {0x3792, 0xFE},
682 {0x3793, 0x05},
683 {0x3794, 0xFE},
684 {0x3795, 0x06},
685 {0x3796, 0x7F},
686 {0x3798, 0xBF},
687 {0x3A01, 0x01},
688 {0x3A18, 0x7F},
689 {0x3A1A, 0x37},
690 {0x3A1C, 0x37},
691 {0x3A1E, 0xF7},
692 {0x3A1F, 0x00},
693 {0x3A20, 0x3F},
694 {0x3A22, 0x6F},
695 {0x3A24, 0x3F},
696 {0x3A26, 0x5F},
697 {0x3A28, 0x2F},
698 {REG_NULL, 0x00},
699 };
700
701 static const struct regval IMX464_linear_10bit_2688x1520_regs[] = {
702 {0x3000, 0x01},
703 {0x3002, 0x01},
704 {0x300C, 0x5B},
705 {0x300D, 0x40},
706 {0x3030, 0xE4},
707 {0x3031, 0x0C},
708 {0x3034, 0xee},
709 {0x3035, 0x02},
710 {0x3048, 0x00},
711 {0x3049, 0x00},
712 {0x304A, 0x03},
713 {0x304B, 0x02},
714 {0x304C, 0x14},
715 {0x3050, 0x00},
716 {0x3058, 0x06},
717 {0x3059, 0x09},
718 {0x305C, 0x09},
719 {0x3060, 0x21},
720 {0x3061, 0x01},
721 {0x3068, 0xc9},
722 {0x306C, 0x56},
723 {0x306D, 0x09},
724 {0x30BE, 0x5E},
725 {0x30E8, 0x14},
726 {0x3110, 0x02},
727 {0x314C, 0xC0},
728 {0x315A, 0x06},
729 {0x316A, 0x7E},
730 {0x319D, 0x00},
731 {0x319E, 0x02},
732 {0x31A1, 0x00},
733 {0x31D7, 0x00},
734 {0x3200, 0x11},
735 {0x3288, 0x22},
736 {0x328A, 0x02},
737 {0x328C, 0xA2},
738 {0x328E, 0x22},
739 {0x3415, 0x27},
740 {0x3418, 0x27},
741 {0x3428, 0xFE},
742 {0x349E, 0x6A},
743 {0x34A2, 0x9A},
744 {0x34A4, 0x8A},
745 {0x34A6, 0x8E},
746 {0x34AA, 0xD8},
747 {0x35BC, 0x00},
748 {0x35BE, 0xFF},
749 {0x35CC, 0x1B},
750 {0x35CD, 0x00},
751 {0x35CE, 0x2A},
752 {0x35CF, 0x00},
753 {0x35DC, 0x07},
754 {0x35DE, 0x1A},
755 {0x35DF, 0x00},
756 {0x35E4, 0x2B},
757 {0x35E5, 0x00},
758 {0x35E6, 0x07},
759 {0x35E7, 0x01},
760 {0x3648, 0x01},
761 {0x3678, 0x01},
762 {0x367C, 0x69},
763 {0x367E, 0x69},
764 {0x3680, 0x69},
765 {0x3682, 0x69},
766 {0x3718, 0x1C},
767 {0x371D, 0x05},
768 {0x375D, 0x11},
769 {0x375E, 0x43},
770 {0x375F, 0x76},
771 {0x3760, 0x07},
772 {0x3768, 0x1B},
773 {0x3769, 0x1B},
774 {0x376A, 0x1A},
775 {0x376B, 0x19},
776 {0x376C, 0x17},
777 {0x376D, 0x0F},
778 {0x376E, 0x0B},
779 {0x376F, 0x0B},
780 {0x3770, 0x0B},
781 {0x3776, 0x89},
782 {0x3777, 0x00},
783 {0x3778, 0xCA},
784 {0x3779, 0x00},
785 {0x377A, 0x45},
786 {0x377B, 0x01},
787 {0x377C, 0x56},
788 {0x377D, 0x02},
789 {0x377E, 0xFE},
790 {0x377F, 0x03},
791 {0x3780, 0xFE},
792 {0x3781, 0x05},
793 {0x3782, 0xFE},
794 {0x3783, 0x06},
795 {0x3784, 0x7F},
796 {0x3788, 0x1F},
797 {0x378A, 0xCA},
798 {0x378B, 0x00},
799 {0x378C, 0x45},
800 {0x378D, 0x01},
801 {0x378E, 0x56},
802 {0x378F, 0x02},
803 {0x3790, 0xFE},
804 {0x3791, 0x03},
805 {0x3792, 0xFE},
806 {0x3793, 0x05},
807 {0x3794, 0xFE},
808 {0x3795, 0x06},
809 {0x3796, 0x7F},
810 {0x3798, 0xBF},
811 {0x3A18, 0x7F},
812 {0x3A1A, 0x37},
813 {0x3A1C, 0x37},
814 {0x3A1E, 0xF7},
815 {0x3A1F, 0x00},
816 {0x3A20, 0x3F},
817 {0x3A22, 0x6F},
818 {0x3A24, 0x3F},
819 {0x3A26, 0x5F},
820 {0x3A28, 0x2F},
821 {REG_NULL, 0x00},
822 };
823
824 static const struct regval IMX464_hdr_2x_10bit_2688x1520_regs[] = {
825 {0x3000, 0x01},
826 {0x3002, 0x01},
827 {0x300C, 0x5B},
828 {0x300D, 0x40},
829 {0x3030, 0x72},
830 {0x3031, 0x06},
831 {0x3034, 0xee},
832 {0x3035, 0x02},
833 {0x3048, 0x01},
834 {0x3049, 0x01},
835 {0x304A, 0x04},
836 {0x304B, 0x04},
837 {0x304C, 0x13},
838 {0x3050, 0x00},
839 {0x3058, 0x06},
840 {0x3059, 0x09},
841 {0x305C, 0x09},
842 {0x3060, 0x21},
843 {0x3061, 0x01},
844 {0x3068, 0x6D},
845 {0x306C, 0x56},
846 {0x306D, 0x09},
847 {0x30BE, 0x5E},
848 {0x30E8, 0x14},
849 {0x3110, 0x02},
850 {0x314C, 0xC0},
851 {0x315A, 0x06},
852 {0x316A, 0x7E},
853 {0x319D, 0x00},
854 {0x319E, 0x02},
855 {0x31A1, 0x00},
856 {0x31D7, 0x01},
857 {0x3200, 0x10},
858 {0x3288, 0x22},
859 {0x328A, 0x02},
860 {0x328C, 0xA2},
861 {0x328E, 0x22},
862 {0x3415, 0x27},
863 {0x3418, 0x27},
864 {0x3428, 0xFE},
865 {0x349E, 0x6A},
866 {0x34A2, 0x9A},
867 {0x34A4, 0x8A},
868 {0x34A6, 0x8E},
869 {0x34AA, 0xD8},
870 {0x35BC, 0x00},
871 {0x35BE, 0xFF},
872 {0x35CC, 0x1B},
873 {0x35CD, 0x00},
874 {0x35CE, 0x2A},
875 {0x35CF, 0x00},
876 {0x35DC, 0x07},
877 {0x35DE, 0x1A},
878 {0x35DF, 0x00},
879 {0x35E4, 0x2B},
880 {0x35E5, 0x00},
881 {0x35E6, 0x07},
882 {0x35E7, 0x01},
883 {0x3648, 0x01},
884 {0x3678, 0x01},
885 {0x367C, 0x69},
886 {0x367E, 0x69},
887 {0x3680, 0x69},
888 {0x3682, 0x69},
889 {0x3718, 0x1C},
890 {0x371D, 0x05},
891 {0x375D, 0x11},
892 {0x375E, 0x43},
893 {0x375F, 0x76},
894 {0x3760, 0x07},
895 {0x3768, 0x1B},
896 {0x3769, 0x1B},
897 {0x376A, 0x1A},
898 {0x376B, 0x19},
899 {0x376C, 0x17},
900 {0x376D, 0x0F},
901 {0x376E, 0x0B},
902 {0x376F, 0x0B},
903 {0x3770, 0x0B},
904 {0x3776, 0x89},
905 {0x3777, 0x00},
906 {0x3778, 0xCA},
907 {0x3779, 0x00},
908 {0x377A, 0x45},
909 {0x377B, 0x01},
910 {0x377C, 0x56},
911 {0x377D, 0x02},
912 {0x377E, 0xFE},
913 {0x377F, 0x03},
914 {0x3780, 0xFE},
915 {0x3781, 0x05},
916 {0x3782, 0xFE},
917 {0x3783, 0x06},
918 {0x3784, 0x7F},
919 {0x3788, 0x1F},
920 {0x378A, 0xCA},
921 {0x378B, 0x00},
922 {0x378C, 0x45},
923 {0x378D, 0x01},
924 {0x378E, 0x56},
925 {0x378F, 0x02},
926 {0x3790, 0xFE},
927 {0x3791, 0x03},
928 {0x3792, 0xFE},
929 {0x3793, 0x05},
930 {0x3794, 0xFE},
931 {0x3795, 0x06},
932 {0x3796, 0x7F},
933 {0x3798, 0xBF},
934 {0x3A18, 0x7F},
935 {0x3A1A, 0x37},
936 {0x3A1C, 0x37},
937 {0x3A1E, 0xF7},
938 {0x3A1F, 0x00},
939 {0x3A20, 0x3F},
940 {0x3A22, 0x6F},
941 {0x3A24, 0x3F},
942 {0x3A26, 0x5F},
943 {0x3A28, 0x2F},
944 {REG_NULL, 0x00},
945 };
946
947 static const struct regval IMX464_hdr_3x_10bit_2688x1520_regs[] = {
948 {0x3000, 0x01},
949 {0x3002, 0x01},
950 {0x300C, 0x5B},
951 {0x300D, 0x40},
952 #ifdef FRAME_15_FPS
953 {0x3030, 0xA2},
954 {0x3031, 0x09},
955 #else
956 {0x3030, 0xD1},
957 {0x3031, 0x04},
958 #endif
959 //add for default
960 {0x3034, 0xF4},
961 {0x3035, 0x01},
962 {0x3048, 0x01},
963 {0x3049, 0x02},
964 {0x304A, 0x05},
965 {0x304B, 0x04},
966 {0x304C, 0x13},
967 {0x3050, 0x00},
968 {0x3058, 0x77},
969 {0x3059, 0x0D},
970 {0x305C, 0x0D},
971 {0x3060, 0xB0},
972 {0x3061, 0x00},
973 {0x3068, 0xA3},
974 {0x306C, 0xCE},
975 {0x306D, 0x00},
976 {0x30BE, 0x5E},
977 {0x30E8, 0x14},
978 {0x3110, 0x02},
979 {0x314C, 0x80},
980 {0x315A, 0x02},
981 {0x316A, 0x7E},
982 {0x319D, 0x00},
983 {0x319E, 0x01},
984 {0x31A1, 0x00},
985 {0x31D7, 0x03},
986 {0x3200, 0x10},
987 {0x3288, 0x22},
988 {0x328A, 0x02},
989 {0x328C, 0xA2},
990 {0x328E, 0x22},
991 {0x3415, 0x27},
992 {0x3418, 0x27},
993 {0x3428, 0xFE},
994 {0x349E, 0x6A},
995 {0x34A2, 0x9A},
996 {0x34A4, 0x8A},
997 {0x34A6, 0x8E},
998 {0x34AA, 0xD8},
999 {0x35BC, 0x00},
1000 {0x35BE, 0xFF},
1001 {0x35CC, 0x1B},
1002 {0x35CD, 0x00},
1003 {0x35CE, 0x2A},
1004 {0x35CF, 0x00},
1005 {0x35DC, 0x07},
1006 {0x35DE, 0x1A},
1007 {0x35DF, 0x00},
1008 {0x35E4, 0x2B},
1009 {0x35E5, 0x00},
1010 {0x35E6, 0x07},
1011 {0x35E7, 0x01},
1012 {0x3648, 0x01},
1013 {0x3678, 0x01},
1014 {0x367C, 0x69},
1015 {0x367E, 0x69},
1016 {0x3680, 0x69},
1017 {0x3682, 0x69},
1018 {0x3718, 0x1C},
1019 {0x371D, 0x05},
1020 {0x375D, 0x11},
1021 {0x375E, 0x43},
1022 {0x375F, 0x76},
1023 {0x3760, 0x07},
1024 {0x3768, 0x1B},
1025 {0x3769, 0x1B},
1026 {0x376A, 0x1A},
1027 {0x376B, 0x19},
1028 {0x376C, 0x17},
1029 {0x376D, 0x0F},
1030 {0x376E, 0x0B},
1031 {0x376F, 0x0B},
1032 {0x3770, 0x0B},
1033 {0x3776, 0x89},
1034 {0x3777, 0x00},
1035 {0x3778, 0xCA},
1036 {0x3779, 0x00},
1037 {0x377A, 0x45},
1038 {0x377B, 0x01},
1039 {0x377C, 0x56},
1040 {0x377D, 0x02},
1041 {0x377E, 0xFE},
1042 {0x377F, 0x03},
1043 {0x3780, 0xFE},
1044 {0x3781, 0x05},
1045 {0x3782, 0xFE},
1046 {0x3783, 0x06},
1047 {0x3784, 0x7F},
1048 {0x3788, 0x1F},
1049 {0x378A, 0xCA},
1050 {0x378B, 0x00},
1051 {0x378C, 0x45},
1052 {0x378D, 0x01},
1053 {0x378E, 0x56},
1054 {0x378F, 0x02},
1055 {0x3790, 0xFE},
1056 {0x3791, 0x03},
1057 {0x3792, 0xFE},
1058 {0x3793, 0x05},
1059 {0x3794, 0xFE},
1060 {0x3795, 0x06},
1061 {0x3796, 0x7F},
1062 {0x3798, 0xBF},
1063 {0x3A18, 0x8F},
1064 {0x3A1A, 0x4F},
1065 {0x3A1C, 0x47},
1066 {0x3A1E, 0xF7},
1067 {0x3A1F, 0x01},
1068 {0x3A20, 0x4F},
1069 {0x3A22, 0x87},
1070 {0x3A24, 0x4F},
1071 {0x3A26, 0x5F},
1072 {0x3A28, 0x3F},
1073 {REG_NULL, 0x00},
1074 };
1075
1076 static __maybe_unused const struct regval IMX464_linear_12bit_2688x1520_regs[] = {
1077 {0x3000, 0x01},
1078 {0x3002, 0x00},
1079 {0x300C, 0x3B},
1080 {0x300D, 0x2A},
1081 {0x3018, 0x04},
1082 {0x302C, 0x30},
1083 {0x302E, 0x80},
1084 {0x302F, 0x0A},
1085 {0x3030, 0x6B},
1086 {0x3031, 0x0A},
1087 {0x3032, 0x00},
1088 {0x3034, 0xee},
1089 {0x3035, 0x02},
1090 {0x3048, 0x00},
1091 {0x3049, 0x00},
1092 {0x304A, 0x03},
1093 {0x304B, 0x02},
1094 {0x304C, 0x14},
1095 {0x3050, 0x01},
1096 {0x3056, 0x02},
1097 {0x3057, 0x06},
1098 {0x3058, 0x03},
1099 {0x3059, 0x00},
1100 {0x3068, 0xc9},
1101 {0x3069, 0x00},
1102 {0x30BE, 0x5E},
1103 {0x30C6, 0x00},
1104 {0x30CE, 0x00},
1105 {0x30D8, 0x4F},
1106 {0x30D9, 0x64},
1107 {0x3110, 0x02},
1108 {0x314C, 0xF0},
1109 {0x315A, 0x06},
1110 {0x3168, 0x82},
1111 {0x316A, 0x7E},
1112 {0x319D, 0x01},
1113 {0x319E, 0x02},
1114 {0x31A1, 0x00},
1115 {0x31D7, 0x00},
1116 {0x3202, 0x02},
1117 {0x3288, 0x22},
1118 {0x328A, 0x02},
1119 {0x328C, 0xA2},
1120 {0x328E, 0x22},
1121 {0x3415, 0x27},
1122 {0x3418, 0x27},
1123 {0x3428, 0xFE},
1124 {0x349E, 0x6A},
1125 {0x34A2, 0x9A},
1126 {0x34A4, 0x8A},
1127 {0x34A6, 0x8E},
1128 {0x34AA, 0xD8},
1129 {0x3648, 0x01},
1130 {0x3678, 0x01},
1131 {0x367C, 0x69},
1132 {0x367E, 0x69},
1133 {0x3680, 0x69},
1134 {0x3682, 0x69},
1135 {0x371D, 0x05},
1136 {0x375D, 0x11},
1137 {0x375E, 0x43},
1138 {0x375F, 0x76},
1139 {0x3760, 0x07},
1140 {0x3768, 0x1B},
1141 {0x3769, 0x1B},
1142 {0x376A, 0x1A},
1143 {0x376B, 0x19},
1144 {0x376C, 0x17},
1145 {0x376D, 0x0F},
1146 {0x376E, 0x0B},
1147 {0x376F, 0x0B},
1148 {0x3770, 0x0B},
1149 {0x3776, 0x89},
1150 {0x3777, 0x00},
1151 {0x3778, 0xCA},
1152 {0x3779, 0x00},
1153 {0x377A, 0x45},
1154 {0x377B, 0x01},
1155 {0x377C, 0x56},
1156 {0x377D, 0x02},
1157 {0x377E, 0xFE},
1158 {0x377F, 0x03},
1159 {0x3780, 0xFE},
1160 {0x3781, 0x05},
1161 {0x3782, 0xFE},
1162 {0x3783, 0x06},
1163 {0x3784, 0x7F},
1164 {0x3788, 0x1F},
1165 {0x378A, 0xCA},
1166 {0x378B, 0x00},
1167 {0x378C, 0x45},
1168 {0x378D, 0x01},
1169 {0x378E, 0x56},
1170 {0x378F, 0x02},
1171 {0x3790, 0xFE},
1172 {0x3791, 0x03},
1173 {0x3792, 0xFE},
1174 {0x3793, 0x05},
1175 {0x3794, 0xFE},
1176 {0x3795, 0x06},
1177 {0x3796, 0x7F},
1178 {0x3200, 0x11},
1179 {0x3798, 0xBF},
1180 {0x3A01, 0x03},
1181 {0x3A18, 0x6F},
1182 {0x3A1A, 0x2F},
1183 {0x3A1C, 0x2F},
1184 {0x3A1E, 0xBF},
1185 {0x3A1F, 0x00},
1186 {0x3A20, 0x2F},
1187 {0x3A22, 0x57},
1188 {0x3A24, 0x2F},
1189 {0x3A26, 0x4F},
1190 {0x3A28, 0x27},
1191 {REG_NULL, 0x00},
1192 };
1193
1194 static __maybe_unused const struct regval IMX464_hdr_2x_12bit_2688x1520_regs[] = {
1195 {0x3000, 0x01},
1196 {0x3002, 0x00},
1197 {0x300C, 0x3B},
1198 {0x300D, 0x2A},
1199 {0x3018, 0x04},
1200 {0x302C, 0x30},
1201 {0x302E, 0x80},
1202 {0x302F, 0x0A},
1203 {0x3030, 0x40},
1204 {0x3031, 0x06},
1205 {0x3032, 0x00},
1206 {0x3034, 0xee},
1207 {0x3035, 0x02},
1208 {0x3048, 0x01},
1209 {0x3049, 0x01},
1210 {0x304A, 0x04},
1211 {0x304B, 0x04},
1212 {0x304C, 0x13},
1213 {0x3050, 0x01},
1214 {0x3056, 0x02},
1215 {0x3057, 0x06},
1216 {0x3058, 0x20},
1217 {0x3059, 0x03},
1218 {0x3068, 0xD9},
1219 {0x3069, 0x02},
1220 {0x30BE, 0x5E},
1221 {0x30C6, 0x00},
1222 {0x30CE, 0x00},
1223 {0x30D8, 0x4F},
1224 {0x30D9, 0x64},
1225 {0x3110, 0x02},
1226 {0x314C, 0xF0},
1227 {0x315A, 0x06},
1228 {0x3168, 0x82},
1229 {0x316A, 0x7E},
1230 {0x319D, 0x01},
1231 {0x319E, 0x02},
1232 {0x31A1, 0x00},
1233 {0x31D7, 0x01},
1234 {0x3202, 0x02},
1235 {0x3288, 0x22},
1236 {0x328A, 0x02},
1237 {0x328C, 0xA2},
1238 {0x328E, 0x22},
1239 {0x3415, 0x27},
1240 {0x3418, 0x27},
1241 {0x3428, 0xFE},
1242 {0x349E, 0x6A},
1243 {0x34A2, 0x9A},
1244 {0x34A4, 0x8A},
1245 {0x34A6, 0x8E},
1246 {0x34AA, 0xD8},
1247 {0x3648, 0x01},
1248 {0x3678, 0x01},
1249 {0x367C, 0x69},
1250 {0x367E, 0x69},
1251 {0x3680, 0x69},
1252 {0x3682, 0x69},
1253 {0x371D, 0x05},
1254 {0x375D, 0x11},
1255 {0x375E, 0x43},
1256 {0x375F, 0x76},
1257 {0x3760, 0x07},
1258 {0x3768, 0x1B},
1259 {0x3769, 0x1B},
1260 {0x376A, 0x1A},
1261 {0x376B, 0x19},
1262 {0x376C, 0x17},
1263 {0x376D, 0x0F},
1264 {0x376E, 0x0B},
1265 {0x376F, 0x0B},
1266 {0x3770, 0x0B},
1267 {0x3776, 0x89},
1268 {0x3777, 0x00},
1269 {0x3778, 0xCA},
1270 {0x3779, 0x00},
1271 {0x377A, 0x45},
1272 {0x377B, 0x01},
1273 {0x377C, 0x56},
1274 {0x377D, 0x02},
1275 {0x377E, 0xFE},
1276 {0x377F, 0x03},
1277 {0x3780, 0xFE},
1278 {0x3781, 0x05},
1279 {0x3782, 0xFE},
1280 {0x3783, 0x06},
1281 {0x3784, 0x7F},
1282 {0x3788, 0x1F},
1283 {0x378A, 0xCA},
1284 {0x378B, 0x00},
1285 {0x378C, 0x45},
1286 {0x378D, 0x01},
1287 {0x378E, 0x56},
1288 {0x378F, 0x02},
1289 {0x3790, 0xFE},
1290 {0x3791, 0x03},
1291 {0x3792, 0xFE},
1292 {0x3793, 0x05},
1293 {0x3794, 0xFE},
1294 {0x3795, 0x06},
1295 {0x3796, 0x7F},
1296 {0x3200, 0x10},
1297 {0x3798, 0xBF},
1298 {0x3A01, 0x03},
1299 {0x3A18, 0x6F},
1300 {0x3A1A, 0x2F},
1301 {0x3A1C, 0x2F},
1302 {0x3A1E, 0xBF},
1303 {0x3A1F, 0x00},
1304 {0x3A20, 0x2F},
1305 {0x3A22, 0x57},
1306 {0x3A24, 0x2F},
1307 {0x3A26, 0x4F},
1308 {0x3A28, 0x27},
1309 {REG_NULL, 0x00},
1310 };
1311
1312 static __maybe_unused const struct regval IMX464_interal_sync_master_start_regs[] = {
1313 {0x3010, 0x07},
1314 {0x31a1, 0x00},
1315 {REG_NULL, 0x00},
1316 };
1317 static __maybe_unused const struct regval IMX464_interal_sync_master_stop_regs[] = {
1318 {0x31a1, 0x0f},
1319 {REG_NULL, 0x00},
1320 };
1321
1322 static __maybe_unused const struct regval IMX464_external_sync_master_start_regs[] = {
1323 {0x3010, 0x05},
1324 {0x31a1, 0x03},
1325 {0x31d9, 0x01},
1326 {REG_NULL, 0x00},
1327 };
1328 static __maybe_unused const struct regval IMX464_external_sync_master_stop_regs[] = {
1329 {0x31a1, 0x0f},
1330 {REG_NULL, 0x00},
1331 };
1332
1333 static __maybe_unused const struct regval IMX464_slave_start_regs[] = {
1334 {0x3010, 0x05},
1335 {0x31a1, 0x0f},
1336 {REG_NULL, 0x00},
1337 };
1338
1339 /*
1340 * The width and height must be configured to be
1341 * the same as the current output resolution of the sensor.
1342 * The input width of the isp needs to be 16 aligned.
1343 * The input height of the isp needs to be 8 aligned.
1344 * If the width or height does not meet the alignment rules,
1345 * you can configure the cropping parameters with the following function to
1346 * crop out the appropriate resolution.
1347 * struct v4l2_subdev_pad_ops {
1348 * .get_selection
1349 * }
1350 */
1351 static const struct IMX464_mode supported_modes[] = {
1352 {
1353 .bus_fmt = MEDIA_BUS_FMT_SRGGB10_1X10,
1354 .width = 2712,
1355 .height = 1536,
1356 .max_fps = {
1357 .numerator = 10000,
1358 .denominator = 300000,
1359 },
1360 .exp_def = 0x0906,
1361 .hts_def = 0x05dc * 2,
1362 .vts_def = 0x0ce4,
1363 .mipi_freq_idx = 0,
1364 .bpp = 10,
1365 .mclk = 37125000,
1366 .reg_list = IMX464_linear_10bit_2688x1520_regs,
1367 .hdr_mode = NO_HDR,
1368 .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
1369 },
1370 {
1371 .bus_fmt = MEDIA_BUS_FMT_SRGGB10_1X10,
1372 .width = 2712,
1373 .height = 1536,
1374 .max_fps = {
1375 .numerator = 10000,
1376 .denominator = 300000,
1377 },
1378 .exp_def = 0x03de,
1379 .hts_def = 0x02ee * 4,
1380 .vts_def = 0x0672 * 2,
1381 .mipi_freq_idx = 1,
1382 .bpp = 10,
1383 .mclk = 37125000,
1384 .reg_list = IMX464_hdr_2x_10bit_2688x1520_regs,
1385 .hdr_mode = HDR_X2,
1386 .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1,
1387 .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
1388 .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
1389 .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
1390 },
1391 {
1392 .bus_fmt = MEDIA_BUS_FMT_SRGGB10_1X10,
1393 .width = 2712,
1394 .height = 1536,
1395 .max_fps = {
1396 .numerator = 10000,
1397 #ifdef FRAME_15_FPS
1398 .denominator = 150000,
1399 #else
1400 .denominator = 300000,
1401 #endif
1402 },
1403 .exp_def = 0x05cd,
1404 .hts_def = 0x01F4 * 8,
1405 #ifdef FRAME_15_FPS
1406 .vts_def = 0x09A2 * 4,
1407 #else
1408 .vts_def = 0x04D1 * 4,
1409 #endif
1410 .mipi_freq_idx = 1,
1411 .bpp = 10,
1412 .mclk = 37125000,
1413 .reg_list = IMX464_hdr_3x_10bit_2688x1520_regs,
1414 .hdr_mode = HDR_X3,
1415 .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_2,
1416 .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr0
1417 .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr1
1418 .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_2,//S->csi wr2
1419 },
1420 };
1421
1422 static const struct IMX464_mode supported_modes_2lane[] = {
1423 {
1424 .bus_fmt = MEDIA_BUS_FMT_SRGGB10_1X10,
1425 .width = 2712,
1426 .height = 1538,
1427 .max_fps = {
1428 .numerator = 10000,
1429 .denominator = 300000,
1430 },
1431 .exp_def = 0x0600,
1432 .hts_def = 0x05dc * 2,
1433 .vts_def = 0x672,
1434 .mipi_freq_idx = 0,
1435 .bpp = 10,
1436 .mclk = 24000000,
1437 .reg_list = IMX464_linear_10bit_2688x1520_2lane_regs,
1438 .hdr_mode = NO_HDR,
1439 .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
1440 },
1441 {
1442 .bus_fmt = MEDIA_BUS_FMT_SRGGB10_1X10,
1443 .width = 2712,
1444 .height = 1538,
1445 .max_fps = {
1446 .numerator = 10000,
1447 .denominator = 150000,
1448 },
1449 .exp_def = 0x0600,
1450 .hts_def = 0x05dc * 4,
1451 .vts_def = 0x0672 * 2,
1452 .mipi_freq_idx = 0,
1453 .bpp = 10,
1454 .mclk = 24000000,
1455 .reg_list = IMX464_hdr_2x_10bit_2688x1520_2lane_regs,
1456 .hdr_mode = HDR_X2,
1457 .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1,
1458 .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
1459 .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
1460 .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
1461 },
1462 };
1463
1464 static const s64 link_freq_menu_items[] = {
1465 MIPI_FREQ_445M,
1466 MIPI_FREQ_594M,
1467 };
1468
1469 /* Write registers up to 4 at a time */
imx464_write_reg(struct i2c_client * client,u16 reg,u32 len,u32 val)1470 static int imx464_write_reg(struct i2c_client *client, u16 reg,
1471 u32 len, u32 val)
1472 {
1473 u32 buf_i, val_i;
1474 u8 buf[6];
1475 u8 *val_p;
1476 __be32 val_be;
1477
1478 if (len > 4)
1479 return -EINVAL;
1480
1481 buf[0] = reg >> 8;
1482 buf[1] = reg & 0xff;
1483
1484 val_be = cpu_to_be32(val);
1485 val_p = (u8 *)&val_be;
1486 buf_i = 2;
1487 val_i = 4 - len;
1488
1489 while (val_i < 4)
1490 buf[buf_i++] = val_p[val_i++];
1491
1492 if (i2c_master_send(client, buf, len + 2) != len + 2)
1493 return -EIO;
1494
1495 return 0;
1496 }
1497
IMX464_write_array(struct i2c_client * client,const struct regval * regs)1498 static int IMX464_write_array(struct i2c_client *client,
1499 const struct regval *regs)
1500 {
1501 u32 i;
1502 int ret = 0;
1503
1504 for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) {
1505 ret = imx464_write_reg(client, regs[i].addr,
1506 IMX464_REG_VALUE_08BIT, regs[i].val);
1507 }
1508 return ret;
1509 }
1510
1511 /* Read registers up to 4 at a time */
IMX464_read_reg(struct i2c_client * client,u16 reg,unsigned int len,u32 * val)1512 static int IMX464_read_reg(struct i2c_client *client, u16 reg, unsigned int len,
1513 u32 *val)
1514 {
1515 struct i2c_msg msgs[2];
1516 u8 *data_be_p;
1517 __be32 data_be = 0;
1518 __be16 reg_addr_be = cpu_to_be16(reg);
1519 int ret;
1520
1521 if (len > 4 || !len)
1522 return -EINVAL;
1523
1524 data_be_p = (u8 *)&data_be;
1525 /* Write register address */
1526 msgs[0].addr = client->addr;
1527 msgs[0].flags = 0;
1528 msgs[0].len = 2;
1529 msgs[0].buf = (u8 *)®_addr_be;
1530
1531 /* Read data from register */
1532 msgs[1].addr = client->addr;
1533 msgs[1].flags = I2C_M_RD;
1534 msgs[1].len = len;
1535 msgs[1].buf = &data_be_p[4 - len];
1536
1537 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
1538 if (ret != ARRAY_SIZE(msgs))
1539 return -EIO;
1540
1541 *val = be32_to_cpu(data_be);
1542
1543 return 0;
1544 }
1545
IMX464_get_reso_dist(const struct IMX464_mode * mode,struct v4l2_mbus_framefmt * framefmt)1546 static int IMX464_get_reso_dist(const struct IMX464_mode *mode,
1547 struct v4l2_mbus_framefmt *framefmt)
1548 {
1549 return abs(mode->width - framefmt->width) +
1550 abs(mode->height - framefmt->height);
1551 }
1552
1553 static const struct IMX464_mode *
IMX464_find_best_fit(struct IMX464 * IMX464,struct v4l2_subdev_format * fmt)1554 IMX464_find_best_fit(struct IMX464 *IMX464, struct v4l2_subdev_format *fmt)
1555 {
1556 struct v4l2_mbus_framefmt *framefmt = &fmt->format;
1557 int dist;
1558 int cur_best_fit = 0;
1559 int cur_best_fit_dist = -1;
1560 unsigned int i;
1561
1562 for (i = 0; i < IMX464->cfg_num; i++) {
1563 dist = IMX464_get_reso_dist(&IMX464->support_modes[i], framefmt);
1564 if ((cur_best_fit_dist == -1 || dist <= cur_best_fit_dist) &&
1565 IMX464->support_modes[i].bus_fmt == framefmt->code) {
1566 cur_best_fit_dist = dist;
1567 cur_best_fit = i;
1568 }
1569 }
1570
1571 return &IMX464->support_modes[cur_best_fit];
1572 }
1573
IMX464_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)1574 static int IMX464_set_fmt(struct v4l2_subdev *sd,
1575 struct v4l2_subdev_pad_config *cfg,
1576 struct v4l2_subdev_format *fmt)
1577 {
1578 struct IMX464 *IMX464 = to_IMX464(sd);
1579 const struct IMX464_mode *mode;
1580 s64 h_blank, vblank_def;
1581 u64 pixel_rate = 0;
1582
1583 mutex_lock(&IMX464->mutex);
1584
1585 mode = IMX464_find_best_fit(IMX464, fmt);
1586 fmt->format.code = mode->bus_fmt;
1587 fmt->format.width = mode->width;
1588 fmt->format.height = mode->height;
1589 fmt->format.field = V4L2_FIELD_NONE;
1590 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1591 #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
1592 *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
1593 #else
1594 mutex_unlock(&IMX464->mutex);
1595 return -ENOTTY;
1596 #endif
1597 } else {
1598 IMX464->cur_mode = mode;
1599 h_blank = mode->hts_def - mode->width;
1600 __v4l2_ctrl_modify_range(IMX464->hblank, h_blank,
1601 h_blank, 1, h_blank);
1602 vblank_def = mode->vts_def - mode->height;
1603 __v4l2_ctrl_modify_range(IMX464->vblank, vblank_def,
1604 IMX464_VTS_MAX - mode->height,
1605 1, vblank_def);
1606 IMX464->cur_vts = IMX464->cur_mode->vts_def;
1607 pixel_rate = (u32)link_freq_menu_items[mode->mipi_freq_idx] / mode->bpp * 2 *
1608 IMX464->bus_cfg.bus.mipi_csi2.num_data_lanes;
1609 __v4l2_ctrl_s_ctrl_int64(IMX464->pixel_rate,
1610 pixel_rate);
1611 __v4l2_ctrl_s_ctrl(IMX464->link_freq,
1612 mode->mipi_freq_idx);
1613 }
1614
1615 mutex_unlock(&IMX464->mutex);
1616
1617 return 0;
1618 }
1619
IMX464_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)1620 static int IMX464_get_fmt(struct v4l2_subdev *sd,
1621 struct v4l2_subdev_pad_config *cfg,
1622 struct v4l2_subdev_format *fmt)
1623 {
1624 struct IMX464 *IMX464 = to_IMX464(sd);
1625 const struct IMX464_mode *mode = IMX464->cur_mode;
1626
1627 mutex_lock(&IMX464->mutex);
1628 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1629 #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
1630 fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
1631 #else
1632 mutex_unlock(&IMX464->mutex);
1633 return -ENOTTY;
1634 #endif
1635 } else {
1636 fmt->format.width = mode->width;
1637 fmt->format.height = mode->height;
1638 fmt->format.code = mode->bus_fmt;
1639 fmt->format.field = V4L2_FIELD_NONE;
1640 if (fmt->pad < PAD_MAX && mode->hdr_mode != NO_HDR)
1641 fmt->reserved[0] = mode->vc[fmt->pad];
1642 else
1643 fmt->reserved[0] = mode->vc[PAD0];
1644 }
1645 mutex_unlock(&IMX464->mutex);
1646
1647 return 0;
1648 }
1649
IMX464_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_mbus_code_enum * code)1650 static int IMX464_enum_mbus_code(struct v4l2_subdev *sd,
1651 struct v4l2_subdev_pad_config *cfg,
1652 struct v4l2_subdev_mbus_code_enum *code)
1653 {
1654 struct IMX464 *IMX464 = to_IMX464(sd);
1655
1656 if (code->index != 0)
1657 return -EINVAL;
1658 code->code = IMX464->cur_mode->bus_fmt;
1659
1660 return 0;
1661 }
1662
IMX464_enum_frame_sizes(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_frame_size_enum * fse)1663 static int IMX464_enum_frame_sizes(struct v4l2_subdev *sd,
1664 struct v4l2_subdev_pad_config *cfg,
1665 struct v4l2_subdev_frame_size_enum *fse)
1666 {
1667 struct IMX464 *IMX464 = to_IMX464(sd);
1668
1669 if (fse->index >= IMX464->cfg_num)
1670 return -EINVAL;
1671
1672 if (fse->code != IMX464->support_modes[fse->index].bus_fmt)
1673 return -EINVAL;
1674
1675 fse->min_width = IMX464->support_modes[fse->index].width;
1676 fse->max_width = IMX464->support_modes[fse->index].width;
1677 fse->max_height = IMX464->support_modes[fse->index].height;
1678 fse->min_height = IMX464->support_modes[fse->index].height;
1679
1680 return 0;
1681 }
1682
IMX464_g_frame_interval(struct v4l2_subdev * sd,struct v4l2_subdev_frame_interval * fi)1683 static int IMX464_g_frame_interval(struct v4l2_subdev *sd,
1684 struct v4l2_subdev_frame_interval *fi)
1685 {
1686 struct IMX464 *IMX464 = to_IMX464(sd);
1687 const struct IMX464_mode *mode = IMX464->cur_mode;
1688
1689 fi->interval = mode->max_fps;
1690
1691 return 0;
1692 }
1693
IMX464_g_mbus_config(struct v4l2_subdev * sd,unsigned int pad_id,struct v4l2_mbus_config * config)1694 static int IMX464_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
1695 struct v4l2_mbus_config *config)
1696 {
1697 struct IMX464 *IMX464 = to_IMX464(sd);
1698 const struct IMX464_mode *mode = IMX464->cur_mode;
1699 u32 val = 0;
1700 u32 lane_num = IMX464->bus_cfg.bus.mipi_csi2.num_data_lanes;
1701
1702 if (mode->hdr_mode == NO_HDR) {
1703 val = 1 << (lane_num - 1) |
1704 V4L2_MBUS_CSI2_CHANNEL_0 |
1705 V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
1706 }
1707 if (mode->hdr_mode == HDR_X2)
1708 val = 1 << (lane_num - 1) |
1709 V4L2_MBUS_CSI2_CHANNEL_0 |
1710 V4L2_MBUS_CSI2_CONTINUOUS_CLOCK |
1711 V4L2_MBUS_CSI2_CHANNEL_1;
1712 if (mode->hdr_mode == HDR_X3)
1713 val = 1 << (lane_num - 1) |
1714 V4L2_MBUS_CSI2_CHANNEL_0 |
1715 V4L2_MBUS_CSI2_CONTINUOUS_CLOCK |
1716 V4L2_MBUS_CSI2_CHANNEL_1 |
1717 V4L2_MBUS_CSI2_CHANNEL_2;
1718
1719 config->type = V4L2_MBUS_CSI2_DPHY;
1720 config->flags = val;
1721
1722 return 0;
1723 }
1724
IMX464_get_module_inf(struct IMX464 * IMX464,struct rkmodule_inf * inf)1725 static void IMX464_get_module_inf(struct IMX464 *IMX464,
1726 struct rkmodule_inf *inf)
1727 {
1728 memset(inf, 0, sizeof(*inf));
1729 strscpy(inf->base.sensor, IMX464_NAME, sizeof(inf->base.sensor));
1730 strscpy(inf->base.module, IMX464->module_name,
1731 sizeof(inf->base.module));
1732 strscpy(inf->base.lens, IMX464->len_name, sizeof(inf->base.lens));
1733 }
1734
IMX464_set_hdrae(struct IMX464 * IMX464,struct preisp_hdrae_exp_s * ae)1735 static int IMX464_set_hdrae(struct IMX464 *IMX464,
1736 struct preisp_hdrae_exp_s *ae)
1737 {
1738 struct i2c_client *client = IMX464->client;
1739 u32 l_exp_time, m_exp_time, s_exp_time;
1740 u32 l_a_gain, m_a_gain, s_a_gain;
1741 u32 gain_switch = 0;
1742 u32 shr1 = 0;
1743 u32 shr0 = 0;
1744 u32 rhs1 = 0;
1745 u32 rhs1_max = 0;
1746 static int rhs1_old = IMX464_RHS1_DEFAULT;
1747 int rhs1_change_limit;
1748 int ret = 0;
1749 u32 fsc = IMX464->cur_vts;
1750 u8 cg_mode = 0;
1751
1752 if (!IMX464->has_init_exp && !IMX464->streaming) {
1753 IMX464->init_hdrae_exp = *ae;
1754 IMX464->has_init_exp = true;
1755 dev_dbg(&IMX464->client->dev, "IMX464 don't stream, record exp for hdr!\n");
1756 return ret;
1757 }
1758 l_exp_time = ae->long_exp_reg;
1759 m_exp_time = ae->middle_exp_reg;
1760 s_exp_time = ae->short_exp_reg;
1761 l_a_gain = ae->long_gain_reg;
1762 m_a_gain = ae->middle_gain_reg;
1763 s_a_gain = ae->short_gain_reg;
1764 dev_dbg(&client->dev,
1765 "rev exp req: L_exp: 0x%x, 0x%x, M_exp: 0x%x, 0x%x S_exp: 0x%x, 0x%x\n",
1766 l_exp_time, m_exp_time, s_exp_time,
1767 l_a_gain, m_a_gain, s_a_gain);
1768
1769 if (IMX464->cur_mode->hdr_mode == HDR_X2) {
1770 //2 stagger
1771 l_a_gain = m_a_gain;
1772 l_exp_time = m_exp_time;
1773 cg_mode = ae->middle_cg_mode;
1774 }
1775 if (!IMX464->isHCG && cg_mode == GAIN_MODE_HCG) {
1776 gain_switch = 0x01 | 0x100;
1777 IMX464->isHCG = true;
1778 } else if (IMX464->isHCG && cg_mode == GAIN_MODE_LCG) {
1779 gain_switch = 0x00 | 0x100;
1780 IMX464->isHCG = false;
1781 }
1782 ret = imx464_write_reg(client,
1783 IMX464_GROUP_HOLD_REG,
1784 IMX464_REG_VALUE_08BIT,
1785 IMX464_GROUP_HOLD_START);
1786 //gain effect n+1
1787 ret |= imx464_write_reg(client,
1788 IMX464_LF_GAIN_REG_H,
1789 IMX464_REG_VALUE_08BIT,
1790 IMX464_FETCH_GAIN_H(l_a_gain));
1791 ret |= imx464_write_reg(client,
1792 IMX464_LF_GAIN_REG_L,
1793 IMX464_REG_VALUE_08BIT,
1794 IMX464_FETCH_GAIN_L(l_a_gain));
1795 ret |= imx464_write_reg(client,
1796 IMX464_SF1_GAIN_REG_H,
1797 IMX464_REG_VALUE_08BIT,
1798 IMX464_FETCH_GAIN_H(s_a_gain));
1799 ret |= imx464_write_reg(client,
1800 IMX464_SF1_GAIN_REG_L,
1801 IMX464_REG_VALUE_08BIT,
1802 IMX464_FETCH_GAIN_L(s_a_gain));
1803 if (gain_switch & 0x100)
1804 ret |= imx464_write_reg(client,
1805 IMX464_GAIN_SWITCH_REG,
1806 IMX464_REG_VALUE_08BIT,
1807 gain_switch & 0xff);
1808 /* Restrictions
1809 * FSC = 2 * VMAX = 4n (4n, align with 4)
1810 * SHR1 + 9 <= SHR0 <= (FSC - 2)
1811 *
1812 * exp_l = FSC - SHR0
1813 * SHR0 = FSC - exp_l (2n, align with 2)
1814 *
1815 * exp_s = RHS1 - SHR1
1816 * SHR1 + 2 <= RHS1 < BRL * 2 (4n + 1)
1817 * SHR1 + 2 <= RHS1 <= SHR0 - 9
1818 * 9 <= SHR1 <= RHS1 - 2 (2n + 1)
1819 *
1820 * RHS1(n+1) >= (RHS1(n) + BRL * 2) - FSC + 2
1821 *
1822 * RHS1 and SHR1 shall be even value.
1823 *
1824 * T(l_exp) = FSC - SHR0, unit: H
1825 * T(s_exp) = RHS1 - SHR1, unit: H
1826 * Exposure ratio: T(l_exp) / T(s_exp) >= 1
1827 */
1828
1829 /* The HDR mode vts is already double by default to workaround T-line */
1830
1831 //long exposure and short exposure
1832 shr0 = fsc - l_exp_time;
1833 rhs1_max = (RHS1_MAX > (shr0 - 9)) ? (shr0 - 9) : RHS1_MAX;
1834 rhs1 = SHR1_MIN + s_exp_time;
1835 dev_err(&client->dev, "line(%d) rhs1 %d\n", __LINE__, rhs1);
1836 if (rhs1 < 11)
1837 rhs1 = 11;
1838 else if (rhs1 > rhs1_max)
1839 rhs1 = rhs1_max;
1840 dev_dbg(&client->dev, "line(%d) rhs1 %d\n", __LINE__, rhs1);
1841
1842 //Dynamic adjustment rhs1 must meet the following conditions
1843 rhs1_change_limit = rhs1_old + 2 * BRL - fsc + 2;
1844 rhs1_change_limit = (rhs1_change_limit < 11) ? 11 : rhs1_change_limit;
1845 if (rhs1_max < rhs1_change_limit)
1846 dev_err(&client->dev,
1847 "The total exposure limit makes rhs1 max is %d,but old rhs1 limit makes rhs1 min is %d\n",
1848 rhs1_max, rhs1_change_limit);
1849 if (rhs1 < rhs1_change_limit)
1850 rhs1 = rhs1_change_limit;
1851
1852 dev_dbg(&client->dev,
1853 "line(%d) rhs1 %d,short time %d rhs1_old %d test %d\n",
1854 __LINE__, rhs1, s_exp_time, rhs1_old,
1855 (rhs1_old + 2 * BRL - fsc + 2));
1856
1857 rhs1 = (rhs1 >> 2) * 4 + 1;
1858 rhs1_old = rhs1;
1859
1860 if (rhs1 - s_exp_time <= SHR1_MIN) {
1861 shr1 = SHR1_MIN;
1862 s_exp_time = rhs1 - shr1;
1863 } else {
1864 shr1 = rhs1 - s_exp_time;
1865 }
1866
1867 if (shr1 < 9)
1868 shr1 = 9;
1869 else if (shr1 > (rhs1 - 2))
1870 shr1 = rhs1 - 2;
1871
1872 if (shr0 < (rhs1 + 9))
1873 shr0 = rhs1 + 9;
1874 else if (shr0 > (fsc - 2))
1875 shr0 = fsc - 2;
1876
1877 dev_dbg(&client->dev,
1878 "fsc=%d,RHS1_MAX=%d,SHR1_MIN=%d,rhs1_max=%d\n",
1879 fsc, RHS1_MAX, SHR1_MIN, rhs1_max);
1880 dev_dbg(&client->dev,
1881 "l_exp_time=%d,s_exp_time=%d,shr0=%d,shr1=%d,rhs1=%d,l_a_gain=%d,s_a_gain=%d\n",
1882 l_exp_time, s_exp_time, shr0, shr1, rhs1, l_a_gain, s_a_gain);
1883 //time effect n+2
1884 ret |= imx464_write_reg(client,
1885 IMX464_RHS1_REG_L,
1886 IMX464_REG_VALUE_08BIT,
1887 IMX464_FETCH_RHS1_L(rhs1));
1888 ret |= imx464_write_reg(client,
1889 IMX464_RHS1_REG_M,
1890 IMX464_REG_VALUE_08BIT,
1891 IMX464_FETCH_RHS1_M(rhs1));
1892 ret |= imx464_write_reg(client,
1893 IMX464_RHS1_REG_H,
1894 IMX464_REG_VALUE_08BIT,
1895 IMX464_FETCH_RHS1_H(rhs1));
1896
1897 ret |= imx464_write_reg(client,
1898 IMX464_SF1_EXPO_REG_L,
1899 IMX464_REG_VALUE_08BIT,
1900 IMX464_FETCH_EXP_L(shr1));
1901 ret |= imx464_write_reg(client,
1902 IMX464_SF1_EXPO_REG_M,
1903 IMX464_REG_VALUE_08BIT,
1904 IMX464_FETCH_EXP_M(shr1));
1905 ret |= imx464_write_reg(client,
1906 IMX464_SF1_EXPO_REG_H,
1907 IMX464_REG_VALUE_08BIT,
1908 IMX464_FETCH_EXP_H(shr1));
1909 ret |= imx464_write_reg(client,
1910 IMX464_LF_EXPO_REG_L,
1911 IMX464_REG_VALUE_08BIT,
1912 IMX464_FETCH_EXP_L(shr0));
1913 ret |= imx464_write_reg(client,
1914 IMX464_LF_EXPO_REG_M,
1915 IMX464_REG_VALUE_08BIT,
1916 IMX464_FETCH_EXP_M(shr0));
1917 ret |= imx464_write_reg(client,
1918 IMX464_LF_EXPO_REG_H,
1919 IMX464_REG_VALUE_08BIT,
1920 IMX464_FETCH_EXP_H(shr0));
1921 ret |= imx464_write_reg(client,
1922 IMX464_GROUP_HOLD_REG,
1923 IMX464_REG_VALUE_08BIT,
1924 IMX464_GROUP_HOLD_END);
1925 return ret;
1926 }
1927
IMX464_set_hdrae_3frame(struct IMX464 * IMX464,struct preisp_hdrae_exp_s * ae)1928 static int IMX464_set_hdrae_3frame(struct IMX464 *IMX464,
1929 struct preisp_hdrae_exp_s *ae)
1930 {
1931 struct i2c_client *client = IMX464->client;
1932 u32 l_exp_time, m_exp_time, s_exp_time;
1933 u32 l_a_gain, m_a_gain, s_a_gain;
1934 int shr2, shr1, shr0, rhs2, rhs1 = 0;
1935 int rhs1_change_limit, rhs2_change_limit = 0;
1936 static int rhs1_old = IMX464_RHS1_X3_DEFAULT;
1937 static int rhs2_old = IMX464_RHS2_X3_DEFAULT;
1938 int ret = 0;
1939 u32 gain_switch = 0;
1940 u8 cg_mode = 0;
1941 u32 fsc;
1942 int rhs1_max = 0;
1943 int shr2_min = 0;
1944
1945 if (!IMX464->has_init_exp && !IMX464->streaming) {
1946 IMX464->init_hdrae_exp = *ae;
1947 IMX464->has_init_exp = true;
1948 dev_dbg(&IMX464->client->dev, "IMX464 is not streaming, save hdr ae!\n");
1949 return ret;
1950 }
1951 l_exp_time = ae->long_exp_reg;
1952 m_exp_time = ae->middle_exp_reg;
1953 s_exp_time = ae->short_exp_reg;
1954 l_a_gain = ae->long_gain_reg;
1955 m_a_gain = ae->middle_gain_reg;
1956 s_a_gain = ae->short_gain_reg;
1957
1958 if (IMX464->cur_mode->hdr_mode == HDR_X3) {
1959 //3 stagger
1960 cg_mode = ae->long_cg_mode;
1961 }
1962 if (!IMX464->isHCG && cg_mode == GAIN_MODE_HCG) {
1963 gain_switch = 0x01 | 0x100;
1964 IMX464->isHCG = true;
1965 } else if (IMX464->isHCG && cg_mode == GAIN_MODE_LCG) {
1966 gain_switch = 0x00 | 0x100;
1967 IMX464->isHCG = false;
1968 }
1969
1970 dev_dbg(&client->dev,
1971 "rev exp req: L_exp: 0x%x, 0x%x, M_exp: 0x%x, 0x%x S_exp: 0x%x, 0x%x\n",
1972 l_exp_time, l_a_gain, m_exp_time, m_a_gain, s_exp_time, s_a_gain);
1973
1974 ret = imx464_write_reg(client, IMX464_GROUP_HOLD_REG,
1975 IMX464_REG_VALUE_08BIT, IMX464_GROUP_HOLD_START);
1976 /* gain effect n+1 */
1977 ret |= imx464_write_reg(client, IMX464_LF_GAIN_REG_H,
1978 IMX464_REG_VALUE_08BIT, IMX464_FETCH_GAIN_H(l_a_gain));
1979 ret |= imx464_write_reg(client, IMX464_LF_GAIN_REG_L,
1980 IMX464_REG_VALUE_08BIT, IMX464_FETCH_GAIN_L(l_a_gain));
1981 ret |= imx464_write_reg(client, IMX464_SF1_GAIN_REG_H,
1982 IMX464_REG_VALUE_08BIT, IMX464_FETCH_GAIN_H(m_a_gain));
1983 ret |= imx464_write_reg(client, IMX464_SF1_GAIN_REG_L,
1984 IMX464_REG_VALUE_08BIT, IMX464_FETCH_GAIN_L(m_a_gain));
1985 ret |= imx464_write_reg(client, IMX464_SF2_GAIN_REG_H,
1986 IMX464_REG_VALUE_08BIT, IMX464_FETCH_GAIN_H(s_a_gain));
1987 ret |= imx464_write_reg(client, IMX464_SF2_GAIN_REG_L,
1988 IMX464_REG_VALUE_08BIT, IMX464_FETCH_GAIN_L(s_a_gain));
1989 if (gain_switch & 0x100)
1990 ret |= imx464_write_reg(client,
1991 IMX464_GAIN_SWITCH_REG,
1992 IMX464_REG_VALUE_08BIT,
1993 gain_switch & 0xff);
1994
1995 /* Restrictions
1996 * FSC = 4 * VMAX and FSC should be 6n;
1997 * exp_l = FSC - SHR0 + Toffset;
1998 *
1999 * SHR0 = FSC - exp_l + Toffset;
2000 * SHR0 <= (FSC -3);
2001 * SHR0 >= RHS2 + 13;
2002 * SHR0 should be 3n;
2003 *
2004 * exp_m = RHS1 - SHR1 + Toffset;
2005 *
2006 * RHS1 < BRL * 3;
2007 * RHS1 <= SHR2 - 13;
2008 * RHS1 >= SHR1 + 3;
2009 * SHR1 >= 13;
2010 * SHR1 <= RHS1 - 3;
2011 * RHS1(n+1) >= RHS1(n) + BRL * 3 -FSC + 3;
2012 *
2013 * SHR1 should be 3n+1 and RHS1 should be 6n+1;
2014 *
2015 * exp_s = RHS2 - SHR2 + Toffset;
2016 *
2017 * RHS2 < BRL * 3 + RHS1;
2018 * RHS2 <= SHR0 - 13;
2019 * RHS2 >= SHR2 + 3;
2020 * SHR2 >= RHS1 + 13;
2021 * SHR2 <= RHS2 - 3;
2022 * RHS1(n+1) >= RHS1(n) + BRL * 3 -FSC + 3;
2023 *
2024 * SHR2 should be 3n+2 and RHS2 should be 6n+2;
2025 */
2026
2027 /* The HDR mode vts is double by default to workaround T-line */
2028 fsc = IMX464->cur_vts;
2029 shr0 = fsc - l_exp_time;
2030 dev_dbg(&client->dev,
2031 "line(%d) shr0 %d, l_exp_time %d, fsc %d\n",
2032 __LINE__, shr0, l_exp_time, fsc);
2033
2034 rhs1 = (SHR1_MIN_X3 + m_exp_time + 5) / 6 * 6 + 1;
2035 rhs1_max = RHS1_MAX_X3;
2036 if (rhs1 < SHR1_MIN_X3 + 3)
2037 rhs1 = SHR1_MIN_X3 + 3;
2038 else if (rhs1 > rhs1_max)
2039 rhs1 = rhs1_max;
2040
2041 dev_dbg(&client->dev,
2042 "line(%d) rhs1 %d, m_exp_time %d rhs1_old %d\n",
2043 __LINE__, rhs1, m_exp_time, rhs1_old);
2044
2045 //Dynamic adjustment rhs2 must meet the following conditions
2046
2047 rhs1_change_limit = rhs1_old + 3 * BRL - fsc + 3;
2048 rhs1_change_limit = (rhs1_change_limit < 16) ? 16 : rhs1_change_limit;
2049 rhs1_change_limit = (rhs1_change_limit + 5) / 6 * 6 + 1;
2050 if (rhs1_max < rhs1_change_limit) {
2051 dev_err(&client->dev,
2052 "The total exposure limit makes rhs1 max is %d,but old rhs1 limit makes rhs1 min is %d\n",
2053 rhs1_max, rhs1_change_limit);
2054 return -EINVAL;
2055 }
2056 if (rhs1 < rhs1_change_limit)
2057 rhs1 = rhs1_change_limit;
2058
2059 dev_dbg(&client->dev,
2060 "line(%d) m_exp_time %d rhs1_old %d, rhs1_new %d\n",
2061 __LINE__, m_exp_time, rhs1_old, rhs1);
2062
2063 rhs1_old = rhs1;
2064
2065 /* shr1 = rhs1 - s_exp_time */
2066 if (rhs1 - m_exp_time <= SHR1_MIN_X3) {
2067 shr1 = SHR1_MIN_X3;
2068 m_exp_time = rhs1 - shr1;
2069 } else {
2070 shr1 = rhs1 - m_exp_time;
2071 }
2072
2073 shr2_min = rhs1 + 13;
2074 rhs2 = (shr2_min + s_exp_time + 5) / 6 * 6 + 2;
2075 if (rhs2 > (shr0 - 13))
2076 rhs2 = shr0 - 13;
2077 else if (rhs2 < 32)//16+13 +3
2078 rhs2 = 32;
2079
2080 dev_err(&client->dev,
2081 "line(%d) rhs2 %d, s_exp_time %d, rhs2_old %d\n",
2082 __LINE__, rhs2, s_exp_time, rhs2_old);
2083
2084 //Dynamic adjustment rhs2 must meet the following conditions
2085 //RHS2(N+1) > (RHS2(N) + BRL �� 3) �C VMAX �� 4) + 3
2086 rhs2_change_limit = rhs2_old + 3 * BRL - fsc + 3;
2087 rhs2_change_limit = (rhs2_change_limit < 32) ? 32 : rhs2_change_limit;
2088 rhs2_change_limit = (rhs2_change_limit + 5) / 6 * 6 + 2;
2089 if ((shr0 - 13) < rhs2_change_limit) {
2090 dev_err(&client->dev,
2091 "The total exposure limit makes rhs2 max is %d,but old rhs1 limit makes rhs2 min is %d\n",
2092 shr0 - 13, rhs2_change_limit);
2093 return -EINVAL;
2094 }
2095 if (rhs2 < rhs2_change_limit)
2096 rhs2 = rhs2_change_limit;
2097
2098 rhs2_old = rhs2;
2099
2100 /* shr2 = rhs2 - s_exp_time */
2101 if (rhs2 - s_exp_time <= shr2_min) {
2102 shr2 = shr2_min;
2103 s_exp_time = rhs2 - shr2;
2104 } else {
2105 shr2 = rhs2 - s_exp_time;
2106 }
2107 dev_dbg(&client->dev,
2108 "line(%d) rhs2_new %d, s_exp_time %d shr2 %d, rhs2_change_limit %d\n",
2109 __LINE__, rhs2, s_exp_time, shr2, rhs2_change_limit);
2110
2111 if (shr0 < rhs2 + 13)
2112 shr0 = rhs2 + 13;
2113 else if (shr0 > fsc - 3)
2114 shr0 = fsc - 3;
2115
2116 dev_dbg(&client->dev,
2117 "long exposure: l_exp_time=%d, fsc=%d, shr0=%d, l_a_gain=%d\n",
2118 l_exp_time, fsc, shr0, l_a_gain);
2119 dev_dbg(&client->dev,
2120 "middle exposure(SEF1): m_exp_time=%d, rhs1=%d, shr1=%d, m_a_gain=%d\n",
2121 m_exp_time, rhs1, shr1, m_a_gain);
2122 dev_dbg(&client->dev,
2123 "short exposure(SEF2): s_exp_time=%d, rhs2=%d, shr2=%d, s_a_gain=%d\n",
2124 s_exp_time, rhs2, shr2, s_a_gain);
2125 /* time effect n+1 */
2126 /* write SEF2 exposure RHS2 regs*/
2127 ret |= imx464_write_reg(client,
2128 IMX464_RHS2_REG_L,
2129 IMX464_REG_VALUE_08BIT,
2130 IMX464_FETCH_RHS1_L(rhs2));
2131 ret |= imx464_write_reg(client,
2132 IMX464_RHS2_REG_M,
2133 IMX464_REG_VALUE_08BIT,
2134 IMX464_FETCH_RHS1_M(rhs2));
2135 ret |= imx464_write_reg(client,
2136 IMX464_RHS2_REG_H,
2137 IMX464_REG_VALUE_08BIT,
2138 IMX464_FETCH_RHS1_H(rhs2));
2139 /* write SEF2 exposure SHR2 regs*/
2140 ret |= imx464_write_reg(client,
2141 IMX464_SF2_EXPO_REG_L,
2142 IMX464_REG_VALUE_08BIT,
2143 IMX464_FETCH_EXP_L(shr2));
2144 ret |= imx464_write_reg(client,
2145 IMX464_SF2_EXPO_REG_M,
2146 IMX464_REG_VALUE_08BIT,
2147 IMX464_FETCH_EXP_M(shr2));
2148 ret |= imx464_write_reg(client,
2149 IMX464_SF2_EXPO_REG_H,
2150 IMX464_REG_VALUE_08BIT,
2151 IMX464_FETCH_EXP_H(shr2));
2152 /* write SEF1 exposure RHS1 regs*/
2153 ret |= imx464_write_reg(client,
2154 IMX464_RHS1_REG_L,
2155 IMX464_REG_VALUE_08BIT,
2156 IMX464_FETCH_RHS1_L(rhs1));
2157 ret |= imx464_write_reg(client,
2158 IMX464_RHS1_REG_M,
2159 IMX464_REG_VALUE_08BIT,
2160 IMX464_FETCH_RHS1_M(rhs1));
2161 ret |= imx464_write_reg(client,
2162 IMX464_RHS1_REG_H,
2163 IMX464_REG_VALUE_08BIT,
2164 IMX464_FETCH_RHS1_H(rhs1));
2165 /* write SEF1 exposure SHR1 regs*/
2166 ret |= imx464_write_reg(client,
2167 IMX464_SF1_EXPO_REG_L,
2168 IMX464_REG_VALUE_08BIT,
2169 IMX464_FETCH_EXP_L(shr1));
2170 ret |= imx464_write_reg(client,
2171 IMX464_SF1_EXPO_REG_M,
2172 IMX464_REG_VALUE_08BIT,
2173 IMX464_FETCH_EXP_M(shr1));
2174 ret |= imx464_write_reg(client,
2175 IMX464_SF1_EXPO_REG_H,
2176 IMX464_REG_VALUE_08BIT,
2177 IMX464_FETCH_EXP_H(shr1));
2178 /* write LF exposure SHR0 regs*/
2179 ret |= imx464_write_reg(client,
2180 IMX464_LF_EXPO_REG_L,
2181 IMX464_REG_VALUE_08BIT,
2182 IMX464_FETCH_EXP_L(shr0));
2183 ret |= imx464_write_reg(client,
2184 IMX464_LF_EXPO_REG_M,
2185 IMX464_REG_VALUE_08BIT,
2186 IMX464_FETCH_EXP_M(shr0));
2187 ret |= imx464_write_reg(client,
2188 IMX464_LF_EXPO_REG_H,
2189 IMX464_REG_VALUE_08BIT,
2190 IMX464_FETCH_EXP_H(shr0));
2191
2192 ret |= imx464_write_reg(client, IMX464_GROUP_HOLD_REG,
2193 IMX464_REG_VALUE_08BIT, IMX464_GROUP_HOLD_END);
2194 return ret;
2195 }
2196
IMX464_set_conversion_gain(struct IMX464 * IMX464,u32 * cg)2197 static int IMX464_set_conversion_gain(struct IMX464 *IMX464, u32 *cg)
2198 {
2199 int ret = 0;
2200 struct i2c_client *client = IMX464->client;
2201 int cur_cg = *cg;
2202 u32 gain_switch = 0;
2203
2204 if (IMX464->isHCG && cur_cg == GAIN_MODE_LCG) {
2205 gain_switch = 0x00 | 0x100;
2206 IMX464->isHCG = false;
2207 } else if (!IMX464->isHCG && cur_cg == GAIN_MODE_HCG) {
2208 gain_switch = 0x01 | 0x100;
2209 IMX464->isHCG = true;
2210 }
2211 ret = imx464_write_reg(client,
2212 IMX464_GROUP_HOLD_REG,
2213 IMX464_REG_VALUE_08BIT,
2214 IMX464_GROUP_HOLD_START);
2215 if (gain_switch & 0x100)
2216 ret |= imx464_write_reg(client,
2217 IMX464_GAIN_SWITCH_REG,
2218 IMX464_REG_VALUE_08BIT,
2219 gain_switch & 0xff);
2220 ret |= imx464_write_reg(client,
2221 IMX464_GROUP_HOLD_REG,
2222 IMX464_REG_VALUE_08BIT,
2223 IMX464_GROUP_HOLD_END);
2224 return ret;
2225 }
2226
2227 #ifdef USED_SYS_DEBUG
2228 //ag: echo 0 > /sys/devices/platform/ff510000.i2c/i2c-1/1-0037/cam_s_cg
set_conversion_gain_status(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2229 static ssize_t set_conversion_gain_status(struct device *dev,
2230 struct device_attribute *attr,
2231 const char *buf,
2232 size_t count)
2233 {
2234 struct i2c_client *client = to_i2c_client(dev);
2235 struct v4l2_subdev *sd = i2c_get_clientdata(client);
2236 struct IMX464 *IMX464 = to_IMX464(sd);
2237 int status = 0;
2238 int ret = 0;
2239
2240 ret = kstrtoint(buf, 0, &status);
2241 if (!ret && status >= 0 && status < 2)
2242 IMX464_set_conversion_gain(IMX464, &status);
2243 else
2244 dev_err(dev, "input 0 for LCG, 1 for HCG, cur %d\n", status);
2245 return count;
2246 }
2247
2248 static struct device_attribute attributes[] = {
2249 __ATTR(cam_s_cg, S_IWUSR, NULL, set_conversion_gain_status),
2250 };
2251
add_sysfs_interfaces(struct device * dev)2252 static int add_sysfs_interfaces(struct device *dev)
2253 {
2254 int i;
2255
2256 for (i = 0; i < ARRAY_SIZE(attributes); i++)
2257 if (device_create_file(dev, attributes + i))
2258 goto undo;
2259 return 0;
2260 undo:
2261 for (i--; i >= 0 ; i--)
2262 device_remove_file(dev, attributes + i);
2263 dev_err(dev, "%s: failed to create sysfs interface\n", __func__);
2264 return -ENODEV;
2265 }
2266
remove_sysfs_interfaces(struct device * dev)2267 static int remove_sysfs_interfaces(struct device *dev)
2268 {
2269 int i;
2270
2271 for (i = 0; i < ARRAY_SIZE(attributes); i++)
2272 device_remove_file(dev, attributes + i);
2273 return 0;
2274 }
2275 #endif
2276
IMX464_get_channel_info(struct IMX464 * IMX464,struct rkmodule_channel_info * ch_info)2277 static int IMX464_get_channel_info(struct IMX464 *IMX464, struct rkmodule_channel_info *ch_info)
2278 {
2279 if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX)
2280 return -EINVAL;
2281 ch_info->vc = IMX464->cur_mode->vc[ch_info->index];
2282 ch_info->width = IMX464->cur_mode->width;
2283 ch_info->height = IMX464->cur_mode->height;
2284 ch_info->bus_fmt = IMX464->cur_mode->bus_fmt;
2285 return 0;
2286 }
2287
IMX464_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)2288 static long IMX464_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
2289 {
2290 struct IMX464 *IMX464 = to_IMX464(sd);
2291 struct rkmodule_hdr_cfg *hdr;
2292 struct rkmodule_channel_info *ch_info;
2293 u32 i, h, w, stream;
2294 long ret = 0;
2295 u64 pixel_rate = 0;
2296 u32 *sync_mode = NULL;
2297
2298 switch (cmd) {
2299 case PREISP_CMD_SET_HDRAE_EXP:
2300 if (IMX464->cur_mode->hdr_mode == HDR_X2)
2301 ret = IMX464_set_hdrae(IMX464, arg);
2302 else if (IMX464->cur_mode->hdr_mode == HDR_X3)
2303 ret = IMX464_set_hdrae_3frame(IMX464, arg);
2304 break;
2305 case RKMODULE_GET_MODULE_INFO:
2306 IMX464_get_module_inf(IMX464, (struct rkmodule_inf *)arg);
2307 break;
2308 case RKMODULE_GET_HDR_CFG:
2309 hdr = (struct rkmodule_hdr_cfg *)arg;
2310 hdr->esp.mode = HDR_NORMAL_VC;
2311 hdr->hdr_mode = IMX464->cur_mode->hdr_mode;
2312 break;
2313 case RKMODULE_SET_HDR_CFG:
2314 hdr = (struct rkmodule_hdr_cfg *)arg;
2315 w = IMX464->cur_mode->width;
2316 h = IMX464->cur_mode->height;
2317 for (i = 0; i < IMX464->cfg_num; i++) {
2318 if (w == IMX464->support_modes[i].width &&
2319 h == IMX464->support_modes[i].height &&
2320 IMX464->support_modes[i].hdr_mode == hdr->hdr_mode) {
2321 IMX464->cur_mode = &IMX464->support_modes[i];
2322 break;
2323 }
2324 }
2325 if (i == IMX464->cfg_num) {
2326 dev_err(&IMX464->client->dev,
2327 "not find hdr mode:%d %dx%d config\n",
2328 hdr->hdr_mode, w, h);
2329 ret = -EINVAL;
2330 } else {
2331 w = IMX464->cur_mode->hts_def - IMX464->cur_mode->width;
2332 h = IMX464->cur_mode->vts_def - IMX464->cur_mode->height;
2333 __v4l2_ctrl_modify_range(IMX464->hblank, w, w, 1, w);
2334 __v4l2_ctrl_modify_range(IMX464->vblank, h,
2335 IMX464_VTS_MAX - IMX464->cur_mode->height,
2336 1, h);
2337 IMX464->cur_vts = IMX464->cur_mode->vts_def;
2338 pixel_rate = (u32)link_freq_menu_items[IMX464->cur_mode->mipi_freq_idx] / IMX464->cur_mode->bpp * 2 *
2339 IMX464->bus_cfg.bus.mipi_csi2.num_data_lanes;
2340 __v4l2_ctrl_s_ctrl_int64(IMX464->pixel_rate,
2341 pixel_rate);
2342 __v4l2_ctrl_s_ctrl(IMX464->link_freq,
2343 IMX464->cur_mode->mipi_freq_idx);
2344 }
2345 break;
2346 case RKMODULE_SET_CONVERSION_GAIN:
2347 ret = IMX464_set_conversion_gain(IMX464, (u32 *)arg);
2348 break;
2349 case RKMODULE_SET_QUICK_STREAM:
2350
2351 stream = *((u32 *)arg);
2352
2353 if (stream)
2354 ret = imx464_write_reg(IMX464->client, IMX464_REG_CTRL_MODE,
2355 IMX464_REG_VALUE_08BIT, IMX464_MODE_STREAMING);
2356 else
2357 ret = imx464_write_reg(IMX464->client, IMX464_REG_CTRL_MODE,
2358 IMX464_REG_VALUE_08BIT, IMX464_MODE_SW_STANDBY);
2359
2360 break;
2361 case RKMODULE_GET_CHANNEL_INFO:
2362 ch_info = (struct rkmodule_channel_info *)arg;
2363 ret = IMX464_get_channel_info(IMX464, ch_info);
2364 break;
2365 case RKMODULE_GET_SYNC_MODE:
2366 sync_mode = (u32 *)arg;
2367 *sync_mode = IMX464->sync_mode;
2368 break;
2369 case RKMODULE_SET_SYNC_MODE:
2370 sync_mode = (u32 *)arg;
2371 IMX464->sync_mode = *sync_mode;
2372 break;
2373 default:
2374 ret = -ENOIOCTLCMD;
2375 break;
2376 }
2377
2378 return ret;
2379 }
2380
2381 #ifdef CONFIG_COMPAT
IMX464_compat_ioctl32(struct v4l2_subdev * sd,unsigned int cmd,unsigned long arg)2382 static long IMX464_compat_ioctl32(struct v4l2_subdev *sd,
2383 unsigned int cmd, unsigned long arg)
2384 {
2385 void __user *up = compat_ptr(arg);
2386 struct rkmodule_inf *inf;
2387 struct rkmodule_awb_cfg *cfg;
2388 struct rkmodule_hdr_cfg *hdr;
2389 struct preisp_hdrae_exp_s *hdrae;
2390 struct rkmodule_channel_info *ch_info;
2391 long ret;
2392 u32 cg = 0;
2393 u32 stream;
2394 u32 sync_mode;
2395
2396 switch (cmd) {
2397 case RKMODULE_GET_MODULE_INFO:
2398 inf = kzalloc(sizeof(*inf), GFP_KERNEL);
2399 if (!inf) {
2400 ret = -ENOMEM;
2401 return ret;
2402 }
2403
2404 ret = IMX464_ioctl(sd, cmd, inf);
2405 if (!ret) {
2406 ret = copy_to_user(up, inf, sizeof(*inf));
2407 if (ret)
2408 ret = -EFAULT;
2409 }
2410 kfree(inf);
2411 break;
2412 case RKMODULE_AWB_CFG:
2413 cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
2414 if (!cfg) {
2415 ret = -ENOMEM;
2416 return ret;
2417 }
2418
2419 ret = copy_from_user(cfg, up, sizeof(*cfg));
2420 if (!ret)
2421 ret = IMX464_ioctl(sd, cmd, cfg);
2422 else
2423 ret = -EFAULT;
2424 kfree(cfg);
2425 break;
2426 case RKMODULE_GET_HDR_CFG:
2427 hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
2428 if (!hdr) {
2429 ret = -ENOMEM;
2430 return ret;
2431 }
2432
2433 ret = IMX464_ioctl(sd, cmd, hdr);
2434 if (!ret) {
2435 ret = copy_to_user(up, hdr, sizeof(*hdr));
2436 if (ret)
2437 ret = -EFAULT;
2438 }
2439 kfree(hdr);
2440 break;
2441 case RKMODULE_SET_HDR_CFG:
2442 hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
2443 if (!hdr) {
2444 ret = -ENOMEM;
2445 return ret;
2446 }
2447
2448 ret = copy_from_user(hdr, up, sizeof(*hdr));
2449 if (!ret)
2450 ret = IMX464_ioctl(sd, cmd, hdr);
2451 else
2452 ret = -EFAULT;
2453 kfree(hdr);
2454 break;
2455 case PREISP_CMD_SET_HDRAE_EXP:
2456 hdrae = kzalloc(sizeof(*hdrae), GFP_KERNEL);
2457 if (!hdrae) {
2458 ret = -ENOMEM;
2459 return ret;
2460 }
2461
2462 ret = copy_from_user(hdrae, up, sizeof(*hdrae));
2463 if (!ret)
2464 ret = IMX464_ioctl(sd, cmd, hdrae);
2465 else
2466 ret = -EFAULT;
2467 kfree(hdrae);
2468 break;
2469 case RKMODULE_SET_CONVERSION_GAIN:
2470 ret = copy_from_user(&cg, up, sizeof(cg));
2471 if (!ret)
2472 ret = IMX464_ioctl(sd, cmd, &cg);
2473 else
2474 ret = -EFAULT;
2475 break;
2476 case RKMODULE_SET_QUICK_STREAM:
2477 ret = copy_from_user(&stream, up, sizeof(u32));
2478 if (!ret)
2479 ret = IMX464_ioctl(sd, cmd, &stream);
2480 else
2481 ret = -EFAULT;
2482
2483 break;
2484 case RKMODULE_GET_CHANNEL_INFO:
2485 ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
2486 if (!ch_info) {
2487 ret = -ENOMEM;
2488 return ret;
2489 }
2490
2491 ret = IMX464_ioctl(sd, cmd, ch_info);
2492 if (!ret) {
2493 ret = copy_to_user(up, ch_info, sizeof(*ch_info));
2494 if (ret)
2495 ret = -EFAULT;
2496 }
2497 kfree(ch_info);
2498 break;
2499 case RKMODULE_GET_SYNC_MODE:
2500 ret = IMX464_ioctl(sd, cmd, &sync_mode);
2501 if (!ret) {
2502 ret = copy_to_user(up, &sync_mode, sizeof(u32));
2503 if (ret)
2504 ret = -EFAULT;
2505 }
2506 break;
2507 case RKMODULE_SET_SYNC_MODE:
2508 ret = copy_from_user(&sync_mode, up, sizeof(u32));
2509 if (!ret)
2510 ret = IMX464_ioctl(sd, cmd, &sync_mode);
2511 else
2512 ret = -EFAULT;
2513 break;
2514 default:
2515 ret = -ENOIOCTLCMD;
2516 break;
2517 }
2518
2519 return ret;
2520 }
2521 #endif
2522
IMX464_init_conversion_gain(struct IMX464 * IMX464,bool isHCG)2523 static int IMX464_init_conversion_gain(struct IMX464 *IMX464, bool isHCG)
2524 {
2525 struct i2c_client *client = IMX464->client;
2526 int ret = 0;
2527 u32 val = 0;
2528
2529 if (isHCG)
2530 val = 0x01;
2531 else
2532 val = 0;
2533 ret = imx464_write_reg(client,
2534 IMX464_GAIN_SWITCH_REG,
2535 IMX464_REG_VALUE_08BIT,
2536 val);
2537 return ret;
2538 }
2539
__IMX464_start_stream(struct IMX464 * IMX464)2540 static int __IMX464_start_stream(struct IMX464 *IMX464)
2541 {
2542 int ret;
2543
2544 ret = IMX464_write_array(IMX464->client, IMX464->cur_mode->reg_list);
2545 if (ret)
2546 return ret;
2547 ret = IMX464_init_conversion_gain(IMX464, IMX464->isHCG);
2548 if (ret)
2549 return ret;
2550 /* In case these controls are set before streaming */
2551 ret = __v4l2_ctrl_handler_setup(&IMX464->ctrl_handler);
2552 if (ret)
2553 return ret;
2554 if (IMX464->has_init_exp && IMX464->cur_mode->hdr_mode != NO_HDR) {
2555 ret = IMX464_ioctl(&IMX464->subdev, PREISP_CMD_SET_HDRAE_EXP,
2556 &IMX464->init_hdrae_exp);
2557 if (ret) {
2558 dev_err(&IMX464->client->dev,
2559 "init exp fail in hdr mode\n");
2560 return ret;
2561 }
2562 }
2563
2564 if (IMX464->sync_mode == EXTERNAL_MASTER_MODE) {
2565 ret |= IMX464_write_array(IMX464->client, IMX464_external_sync_master_start_regs);
2566 v4l2_err(&IMX464->subdev, "cur externam master mode\n");
2567 } else if (IMX464->sync_mode == INTERNAL_MASTER_MODE) {
2568 ret |= IMX464_write_array(IMX464->client, IMX464_interal_sync_master_start_regs);
2569 v4l2_err(&IMX464->subdev, "cur intertal master\n");
2570 } else if (IMX464->sync_mode == SLAVE_MODE) {
2571 ret |= IMX464_write_array(IMX464->client, IMX464_slave_start_regs);
2572 v4l2_err(&IMX464->subdev, "cur slave mode\n");
2573 }
2574 if (IMX464->sync_mode == NO_SYNC_MODE) {
2575 ret = imx464_write_reg(IMX464->client, IMX464_REG_CTRL_MODE,
2576 IMX464_REG_VALUE_08BIT, IMX464_MODE_STREAMING);
2577 usleep_range(30000, 40000);
2578 ret |= imx464_write_reg(IMX464->client, IMX464_REG_MARSTER_MODE,
2579 IMX464_REG_VALUE_08BIT, 0);
2580 } else {
2581 ret |= imx464_write_reg(IMX464->client, IMX464_REG_MARSTER_MODE,
2582 IMX464_REG_VALUE_08BIT, 0);
2583 }
2584 return ret;
2585 }
2586
__IMX464_stop_stream(struct IMX464 * IMX464)2587 static int __IMX464_stop_stream(struct IMX464 *IMX464)
2588 {
2589 int ret = 0;
2590
2591 IMX464->has_init_exp = false;
2592 ret = imx464_write_reg(IMX464->client, IMX464_REG_CTRL_MODE,
2593 IMX464_REG_VALUE_08BIT, IMX464_MODE_SW_STANDBY);
2594
2595 if (IMX464->sync_mode == EXTERNAL_MASTER_MODE)
2596 ret |= IMX464_write_array(IMX464->client, IMX464_external_sync_master_stop_regs);
2597 else if (IMX464->sync_mode == INTERNAL_MASTER_MODE)
2598 ret |= IMX464_write_array(IMX464->client, IMX464_interal_sync_master_stop_regs);
2599 return ret;
2600 }
2601
IMX464_s_stream(struct v4l2_subdev * sd,int on)2602 static int IMX464_s_stream(struct v4l2_subdev *sd, int on)
2603 {
2604 struct IMX464 *IMX464 = to_IMX464(sd);
2605 struct i2c_client *client = IMX464->client;
2606 int ret = 0;
2607
2608 mutex_lock(&IMX464->mutex);
2609 on = !!on;
2610 if (on == IMX464->streaming)
2611 goto unlock_and_return;
2612
2613 if (on) {
2614 ret = pm_runtime_get_sync(&client->dev);
2615 if (ret < 0) {
2616 pm_runtime_put_noidle(&client->dev);
2617 goto unlock_and_return;
2618 }
2619
2620 ret = __IMX464_start_stream(IMX464);
2621 if (ret) {
2622 v4l2_err(sd, "start stream failed while write regs\n");
2623 pm_runtime_put(&client->dev);
2624 goto unlock_and_return;
2625 }
2626 } else {
2627 __IMX464_stop_stream(IMX464);
2628 pm_runtime_put(&client->dev);
2629 }
2630
2631 IMX464->streaming = on;
2632
2633 unlock_and_return:
2634 mutex_unlock(&IMX464->mutex);
2635
2636 return ret;
2637 }
2638
IMX464_s_power(struct v4l2_subdev * sd,int on)2639 static int IMX464_s_power(struct v4l2_subdev *sd, int on)
2640 {
2641 struct IMX464 *IMX464 = to_IMX464(sd);
2642 struct i2c_client *client = IMX464->client;
2643 int ret = 0;
2644
2645 mutex_lock(&IMX464->mutex);
2646
2647 /* If the power state is not modified - no work to do. */
2648 if (IMX464->power_on == !!on)
2649 goto unlock_and_return;
2650
2651 if (on) {
2652 ret = pm_runtime_get_sync(&client->dev);
2653 if (ret < 0) {
2654 pm_runtime_put_noidle(&client->dev);
2655 goto unlock_and_return;
2656 }
2657
2658 ret = IMX464_write_array(IMX464->client, IMX464_global_regs);
2659 if (ret) {
2660 v4l2_err(sd, "could not set init registers\n");
2661 pm_runtime_put_noidle(&client->dev);
2662 goto unlock_and_return;
2663 }
2664
2665 IMX464->power_on = true;
2666 } else {
2667 pm_runtime_put(&client->dev);
2668 IMX464->power_on = false;
2669 }
2670
2671 unlock_and_return:
2672 mutex_unlock(&IMX464->mutex);
2673
2674 return ret;
2675 }
2676
2677 /* Calculate the delay in us by clock rate and clock cycles */
IMX464_cal_delay(u32 cycles)2678 static inline u32 IMX464_cal_delay(u32 cycles)
2679 {
2680 return DIV_ROUND_UP(cycles, IMX464_XVCLK_FREQ_37M / 1000 / 1000);
2681 }
2682
__IMX464_power_on(struct IMX464 * IMX464)2683 static int __IMX464_power_on(struct IMX464 *IMX464)
2684 {
2685 int ret;
2686 u32 delay_us;
2687 struct device *dev = &IMX464->client->dev;
2688
2689 if (!IS_ERR_OR_NULL(IMX464->pins_default)) {
2690 ret = pinctrl_select_state(IMX464->pinctrl,
2691 IMX464->pins_default);
2692 if (ret < 0)
2693 dev_err(dev, "could not set pins\n");
2694 }
2695
2696 ret = clk_set_rate(IMX464->xvclk, IMX464->cur_mode->mclk);
2697 if (ret < 0)
2698 dev_warn(dev, "Failed to set xvclk rate\n");
2699 if (clk_get_rate(IMX464->xvclk) != IMX464->cur_mode->mclk)
2700 dev_warn(dev, "xvclk mismatched, %lu\n", clk_get_rate(IMX464->xvclk));
2701 else
2702 IMX464->cur_mclk = IMX464->cur_mode->mclk;
2703 ret = clk_prepare_enable(IMX464->xvclk);
2704 if (ret < 0) {
2705 dev_err(dev, "Failed to enable xvclk\n");
2706 return ret;
2707 }
2708 if (!IS_ERR(IMX464->reset_gpio))
2709 gpiod_set_value_cansleep(IMX464->reset_gpio, 0);
2710
2711 ret = regulator_bulk_enable(IMX464_NUM_SUPPLIES, IMX464->supplies);
2712 if (ret < 0) {
2713 dev_err(dev, "Failed to enable regulators\n");
2714 goto disable_clk;
2715 }
2716 usleep_range(15000, 16000);
2717 if (!IS_ERR(IMX464->reset_gpio))
2718 gpiod_set_value_cansleep(IMX464->reset_gpio, 1);
2719
2720 usleep_range(500, 1000);
2721 if (!IS_ERR(IMX464->pwdn_gpio))
2722 gpiod_set_value_cansleep(IMX464->pwdn_gpio, 1);
2723
2724 /* 8192 cycles prior to first SCCB transaction */
2725 delay_us = IMX464_cal_delay(8192);
2726 usleep_range(delay_us, delay_us * 2);
2727
2728 return 0;
2729
2730 disable_clk:
2731 clk_disable_unprepare(IMX464->xvclk);
2732
2733 return ret;
2734 }
2735
__IMX464_power_off(struct IMX464 * IMX464)2736 static void __IMX464_power_off(struct IMX464 *IMX464)
2737 {
2738 int ret;
2739 struct device *dev = &IMX464->client->dev;
2740
2741 if (!IS_ERR(IMX464->pwdn_gpio))
2742 gpiod_set_value_cansleep(IMX464->pwdn_gpio, 0);
2743 clk_disable_unprepare(IMX464->xvclk);
2744 if (!IS_ERR(IMX464->reset_gpio))
2745 gpiod_set_value_cansleep(IMX464->reset_gpio, 0);
2746 if (!IS_ERR_OR_NULL(IMX464->pins_sleep)) {
2747 ret = pinctrl_select_state(IMX464->pinctrl,
2748 IMX464->pins_sleep);
2749 if (ret < 0)
2750 dev_err(dev, "could not set pins\n");
2751 }
2752 regulator_bulk_disable(IMX464_NUM_SUPPLIES, IMX464->supplies);
2753 usleep_range(15000, 16000);
2754 }
2755
IMX464_runtime_resume(struct device * dev)2756 static int IMX464_runtime_resume(struct device *dev)
2757 {
2758 struct i2c_client *client = to_i2c_client(dev);
2759 struct v4l2_subdev *sd = i2c_get_clientdata(client);
2760 struct IMX464 *IMX464 = to_IMX464(sd);
2761
2762 return __IMX464_power_on(IMX464);
2763 }
2764
IMX464_runtime_suspend(struct device * dev)2765 static int IMX464_runtime_suspend(struct device *dev)
2766 {
2767 struct i2c_client *client = to_i2c_client(dev);
2768 struct v4l2_subdev *sd = i2c_get_clientdata(client);
2769 struct IMX464 *IMX464 = to_IMX464(sd);
2770
2771 __IMX464_power_off(IMX464);
2772
2773 return 0;
2774 }
2775
2776 #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
IMX464_open(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)2777 static int IMX464_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
2778 {
2779 struct IMX464 *IMX464 = to_IMX464(sd);
2780 struct v4l2_mbus_framefmt *try_fmt =
2781 v4l2_subdev_get_try_format(sd, fh->pad, 0);
2782 const struct IMX464_mode *def_mode = &IMX464->support_modes[0];
2783
2784 mutex_lock(&IMX464->mutex);
2785 /* Initialize try_fmt */
2786 try_fmt->width = def_mode->width;
2787 try_fmt->height = def_mode->height;
2788 try_fmt->code = def_mode->bus_fmt;
2789 try_fmt->field = V4L2_FIELD_NONE;
2790
2791 mutex_unlock(&IMX464->mutex);
2792 /* No crop or compose */
2793
2794 return 0;
2795 }
2796 #endif
2797
IMX464_enum_frame_interval(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_frame_interval_enum * fie)2798 static int IMX464_enum_frame_interval(struct v4l2_subdev *sd,
2799 struct v4l2_subdev_pad_config *cfg,
2800 struct v4l2_subdev_frame_interval_enum *fie)
2801 {
2802 struct IMX464 *IMX464 = to_IMX464(sd);
2803
2804 if (fie->index >= IMX464->cfg_num)
2805 return -EINVAL;
2806
2807 fie->code = IMX464->support_modes[fie->index].bus_fmt;
2808 fie->width = IMX464->support_modes[fie->index].width;
2809 fie->height = IMX464->support_modes[fie->index].height;
2810 fie->interval = IMX464->support_modes[fie->index].max_fps;
2811 fie->reserved[0] = IMX464->support_modes[fie->index].hdr_mode;
2812 return 0;
2813 }
2814
2815 #define CROP_START(SRC, DST) (((SRC) - (DST)) / 2 / 4 * 4)
2816 #define DST_WIDTH 2560
2817 #define DST_HEIGHT 1520
2818
2819 /*
2820 * The resolution of the driver configuration needs to be exactly
2821 * the same as the current output resolution of the sensor,
2822 * the input width of the isp needs to be 16 aligned,
2823 * the input height of the isp needs to be 8 aligned.
2824 * Can be cropped to standard resolution by this function,
2825 * otherwise it will crop out strange resolution according
2826 * to the alignment rules.
2827 */
IMX464_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_selection * sel)2828 static int IMX464_get_selection(struct v4l2_subdev *sd,
2829 struct v4l2_subdev_pad_config *cfg,
2830 struct v4l2_subdev_selection *sel)
2831 {
2832 struct IMX464 *IMX464 = to_IMX464(sd);
2833
2834 if (sel->target == V4L2_SEL_TGT_CROP_BOUNDS) {
2835 sel->r.left = CROP_START(IMX464->cur_mode->width, DST_WIDTH);
2836 sel->r.width = DST_WIDTH;
2837 sel->r.top = CROP_START(IMX464->cur_mode->height, DST_HEIGHT);
2838 sel->r.height = DST_HEIGHT;
2839 return 0;
2840 }
2841 return -EINVAL;
2842 }
2843
2844 static const struct dev_pm_ops IMX464_pm_ops = {
2845 SET_RUNTIME_PM_OPS(IMX464_runtime_suspend,
2846 IMX464_runtime_resume, NULL)
2847 };
2848
2849 #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
2850 static const struct v4l2_subdev_internal_ops IMX464_internal_ops = {
2851 .open = IMX464_open,
2852 };
2853 #endif
2854
2855 static const struct v4l2_subdev_core_ops IMX464_core_ops = {
2856 .s_power = IMX464_s_power,
2857 .ioctl = IMX464_ioctl,
2858 #ifdef CONFIG_COMPAT
2859 .compat_ioctl32 = IMX464_compat_ioctl32,
2860 #endif
2861 };
2862
2863 static const struct v4l2_subdev_video_ops IMX464_video_ops = {
2864 .s_stream = IMX464_s_stream,
2865 .g_frame_interval = IMX464_g_frame_interval,
2866 };
2867
2868 static const struct v4l2_subdev_pad_ops IMX464_pad_ops = {
2869 .enum_mbus_code = IMX464_enum_mbus_code,
2870 .enum_frame_size = IMX464_enum_frame_sizes,
2871 .enum_frame_interval = IMX464_enum_frame_interval,
2872 .get_fmt = IMX464_get_fmt,
2873 .set_fmt = IMX464_set_fmt,
2874 .get_selection = IMX464_get_selection,
2875 .get_mbus_config = IMX464_g_mbus_config,
2876 };
2877
2878 static const struct v4l2_subdev_ops IMX464_subdev_ops = {
2879 .core = &IMX464_core_ops,
2880 .video = &IMX464_video_ops,
2881 .pad = &IMX464_pad_ops,
2882 };
2883
IMX464_set_ctrl(struct v4l2_ctrl * ctrl)2884 static int IMX464_set_ctrl(struct v4l2_ctrl *ctrl)
2885 {
2886 struct IMX464 *IMX464 = container_of(ctrl->handler,
2887 struct IMX464, ctrl_handler);
2888 struct i2c_client *client = IMX464->client;
2889 const struct IMX464_mode *mode = IMX464->cur_mode;
2890 s64 max;
2891 u32 vts = 0;
2892 int ret = 0;
2893 u32 shr0 = 0;
2894 u32 flip = 0;
2895
2896 /* Propagate change of current control to all related controls */
2897 switch (ctrl->id) {
2898 case V4L2_CID_VBLANK:
2899 /* Update max exposure while meeting expected vblanking */
2900 if (mode->hdr_mode == NO_HDR) {
2901 max = IMX464->cur_mode->height + ctrl->val - 3;
2902 __v4l2_ctrl_modify_range(IMX464->exposure,
2903 IMX464->exposure->minimum, max,
2904 IMX464->exposure->step,
2905 IMX464->exposure->default_value);
2906 }
2907 break;
2908 }
2909
2910 if (!pm_runtime_get_if_in_use(&client->dev))
2911 return 0;
2912
2913 switch (ctrl->id) {
2914 case V4L2_CID_EXPOSURE:
2915 if (mode->hdr_mode == NO_HDR) {
2916 shr0 = IMX464->cur_vts - ctrl->val;
2917 ret = imx464_write_reg(IMX464->client, IMX464_LF_EXPO_REG_L,
2918 IMX464_REG_VALUE_08BIT,
2919 IMX464_FETCH_EXP_L(shr0));
2920 ret |= imx464_write_reg(IMX464->client, IMX464_LF_EXPO_REG_M,
2921 IMX464_REG_VALUE_08BIT,
2922 IMX464_FETCH_EXP_M(shr0));
2923 ret |= imx464_write_reg(IMX464->client, IMX464_LF_EXPO_REG_H,
2924 IMX464_REG_VALUE_08BIT,
2925 IMX464_FETCH_EXP_H(shr0));
2926 dev_err(&client->dev, "set exposure 0x%x\n",
2927 ctrl->val);
2928 }
2929 break;
2930 case V4L2_CID_ANALOGUE_GAIN:
2931 if (mode->hdr_mode == NO_HDR) {
2932 ret = imx464_write_reg(IMX464->client, IMX464_LF_GAIN_REG_H,
2933 IMX464_REG_VALUE_08BIT,
2934 IMX464_FETCH_GAIN_H(ctrl->val));
2935 ret |= imx464_write_reg(IMX464->client, IMX464_LF_GAIN_REG_L,
2936 IMX464_REG_VALUE_08BIT,
2937 IMX464_FETCH_GAIN_L(ctrl->val));
2938 dev_err(&client->dev, "set analog gain 0x%x\n",
2939 ctrl->val);
2940 }
2941 break;
2942 case V4L2_CID_VBLANK:
2943 vts = ctrl->val + IMX464->cur_mode->height;
2944
2945 if (mode->hdr_mode == HDR_X2) {
2946 vts = (vts + 3) / 4 * 4;
2947 IMX464->cur_vts = vts;
2948 vts /= 2;
2949 } else if (mode->hdr_mode == HDR_X3) {
2950 vts = (vts + 5) / 6 * 6;
2951 IMX464->cur_vts = vts;
2952 vts /= 4;
2953 } else {
2954 IMX464->cur_vts = vts;
2955 }
2956 ret = imx464_write_reg(IMX464->client, IMX464_VTS_REG_L,
2957 IMX464_REG_VALUE_08BIT,
2958 IMX464_FETCH_VTS_L(vts));
2959 ret |= imx464_write_reg(IMX464->client, IMX464_VTS_REG_M,
2960 IMX464_REG_VALUE_08BIT,
2961 IMX464_FETCH_VTS_M(vts));
2962 ret |= imx464_write_reg(IMX464->client, IMX464_VTS_REG_H,
2963 IMX464_REG_VALUE_08BIT,
2964 IMX464_FETCH_VTS_H(vts));
2965
2966 dev_err(&client->dev, "set vts 0x%x\n",
2967 vts);
2968 break;
2969 case V4L2_CID_HFLIP:
2970 ret = imx464_write_reg(client,
2971 IMX464_GROUP_HOLD_REG,
2972 IMX464_REG_VALUE_08BIT,
2973 IMX464_GROUP_HOLD_START);
2974 ret |= imx464_write_reg(IMX464->client, IMX464_HREVERSE_REG,
2975 IMX464_REG_VALUE_08BIT, !!ctrl->val);
2976 ret |= imx464_write_reg(client,
2977 IMX464_GROUP_HOLD_REG,
2978 IMX464_REG_VALUE_08BIT,
2979 IMX464_GROUP_HOLD_END);
2980 break;
2981 case V4L2_CID_VFLIP:
2982 flip = ctrl->val;
2983 ret = imx464_write_reg(client,
2984 IMX464_GROUP_HOLD_REG,
2985 IMX464_REG_VALUE_08BIT,
2986 IMX464_GROUP_HOLD_START);
2987 ret |= imx464_write_reg(IMX464->client, IMX464_VREVERSE_REG,
2988 IMX464_REG_VALUE_08BIT, !!flip);
2989 if (flip) {
2990 ret |= imx464_write_reg(IMX464->client, 0x3074,
2991 IMX464_REG_VALUE_08BIT, 0x40);
2992 ret |= imx464_write_reg(IMX464->client, 0x3075,
2993 IMX464_REG_VALUE_08BIT, 0x06);
2994 ret |= imx464_write_reg(IMX464->client, 0x3080,
2995 IMX464_REG_VALUE_08BIT, 0xff);
2996 ret |= imx464_write_reg(IMX464->client, 0x30ad,
2997 IMX464_REG_VALUE_08BIT, 0x7e);
2998 ret |= imx464_write_reg(IMX464->client, 0x30b6,
2999 IMX464_REG_VALUE_08BIT, 0xff);
3000 ret |= imx464_write_reg(IMX464->client, 0x30b7,
3001 IMX464_REG_VALUE_08BIT, 0x01);
3002 ret |= imx464_write_reg(IMX464->client, 0x30d8,
3003 IMX464_REG_VALUE_08BIT, 0x45);
3004 ret |= imx464_write_reg(IMX464->client, 0x3114,
3005 IMX464_REG_VALUE_08BIT, 0x01);
3006 } else {
3007 ret |= imx464_write_reg(IMX464->client, 0x3074,
3008 IMX464_REG_VALUE_08BIT, 0x3c);
3009 ret |= imx464_write_reg(IMX464->client, 0x3075,
3010 IMX464_REG_VALUE_08BIT, 0x00);
3011 ret |= imx464_write_reg(IMX464->client, 0x3080,
3012 IMX464_REG_VALUE_08BIT, 0x01);
3013 ret |= imx464_write_reg(IMX464->client, 0x30ad,
3014 IMX464_REG_VALUE_08BIT, 0x02);
3015 ret |= imx464_write_reg(IMX464->client, 0x30b6,
3016 IMX464_REG_VALUE_08BIT, 0x00);
3017 ret |= imx464_write_reg(IMX464->client, 0x30b7,
3018 IMX464_REG_VALUE_08BIT, 0x00);
3019 ret |= imx464_write_reg(IMX464->client, 0x30d8,
3020 IMX464_REG_VALUE_08BIT, 0x44);
3021 ret |= imx464_write_reg(IMX464->client, 0x3114,
3022 IMX464_REG_VALUE_08BIT, 0x02);
3023 }
3024 ret |= imx464_write_reg(client,
3025 IMX464_GROUP_HOLD_REG,
3026 IMX464_REG_VALUE_08BIT,
3027 IMX464_GROUP_HOLD_END);
3028 break;
3029 default:
3030 dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
3031 __func__, ctrl->id, ctrl->val);
3032 break;
3033 }
3034
3035 pm_runtime_put(&client->dev);
3036
3037 return ret;
3038 }
3039
3040 static const struct v4l2_ctrl_ops IMX464_ctrl_ops = {
3041 .s_ctrl = IMX464_set_ctrl,
3042 };
3043
IMX464_initialize_controls(struct IMX464 * IMX464)3044 static int IMX464_initialize_controls(struct IMX464 *IMX464)
3045 {
3046 const struct IMX464_mode *mode;
3047 struct v4l2_ctrl_handler *handler;
3048 s64 exposure_max, vblank_def;
3049 u32 h_blank;
3050 u64 pixel_rate = 0;
3051 int ret;
3052
3053 handler = &IMX464->ctrl_handler;
3054 mode = IMX464->cur_mode;
3055 ret = v4l2_ctrl_handler_init(handler, 8);
3056 if (ret)
3057 return ret;
3058 handler->lock = &IMX464->mutex;
3059
3060 IMX464->link_freq = v4l2_ctrl_new_int_menu(handler,
3061 NULL, V4L2_CID_LINK_FREQ,
3062 1, 0, link_freq_menu_items);
3063 __v4l2_ctrl_s_ctrl(IMX464->link_freq,
3064 IMX464->cur_mode->mipi_freq_idx);
3065 pixel_rate = (u32)link_freq_menu_items[mode->mipi_freq_idx] / mode->bpp * 2 *
3066 IMX464->bus_cfg.bus.mipi_csi2.num_data_lanes;
3067 IMX464->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
3068 V4L2_CID_PIXEL_RATE, 0, IMX464_10BIT_HDR2_PIXEL_RATE,
3069 1, pixel_rate);
3070
3071 h_blank = mode->hts_def - mode->width;
3072 IMX464->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
3073 h_blank, h_blank, 1, h_blank);
3074 if (IMX464->hblank)
3075 IMX464->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
3076
3077 vblank_def = mode->vts_def - mode->height;
3078 IMX464->vblank = v4l2_ctrl_new_std(handler, &IMX464_ctrl_ops,
3079 V4L2_CID_VBLANK, vblank_def,
3080 IMX464_VTS_MAX - mode->height,
3081 1, vblank_def);
3082 IMX464->cur_vts = mode->vts_def;
3083
3084 exposure_max = mode->vts_def - 3;
3085 IMX464->exposure = v4l2_ctrl_new_std(handler, &IMX464_ctrl_ops,
3086 V4L2_CID_EXPOSURE, IMX464_EXPOSURE_MIN,
3087 exposure_max, IMX464_EXPOSURE_STEP,
3088 mode->exp_def);
3089
3090 IMX464->anal_a_gain = v4l2_ctrl_new_std(handler, &IMX464_ctrl_ops,
3091 V4L2_CID_ANALOGUE_GAIN, IMX464_GAIN_MIN,
3092 IMX464_GAIN_MAX, IMX464_GAIN_STEP,
3093 IMX464_GAIN_DEFAULT);
3094 v4l2_ctrl_new_std(handler, &IMX464_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
3095 v4l2_ctrl_new_std(handler, &IMX464_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
3096
3097 if (handler->error) {
3098 ret = handler->error;
3099 dev_err(&IMX464->client->dev,
3100 "Failed to init controls(%d)\n", ret);
3101 goto err_free_handler;
3102 }
3103
3104 IMX464->subdev.ctrl_handler = handler;
3105 IMX464->has_init_exp = false;
3106 IMX464->isHCG = false;
3107
3108 return 0;
3109
3110 err_free_handler:
3111 v4l2_ctrl_handler_free(handler);
3112
3113 return ret;
3114 }
3115
IMX464_check_sensor_id(struct IMX464 * IMX464,struct i2c_client * client)3116 static int IMX464_check_sensor_id(struct IMX464 *IMX464,
3117 struct i2c_client *client)
3118 {
3119 struct device *dev = &IMX464->client->dev;
3120 u32 id = 0;
3121 int ret;
3122
3123 ret = IMX464_read_reg(client, IMX464_REG_CHIP_ID,
3124 IMX464_REG_VALUE_08BIT, &id);
3125 if (id != CHIP_ID) {
3126 dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret);
3127 return -ENODEV;
3128 }
3129
3130 dev_info(dev, "Detected IMX464 id %06x\n", CHIP_ID);
3131
3132 return 0;
3133 }
3134
IMX464_configure_regulators(struct IMX464 * IMX464)3135 static int IMX464_configure_regulators(struct IMX464 *IMX464)
3136 {
3137 unsigned int i;
3138
3139 for (i = 0; i < IMX464_NUM_SUPPLIES; i++)
3140 IMX464->supplies[i].supply = IMX464_supply_names[i];
3141
3142 return devm_regulator_bulk_get(&IMX464->client->dev,
3143 IMX464_NUM_SUPPLIES,
3144 IMX464->supplies);
3145 }
3146
IMX464_probe(struct i2c_client * client,const struct i2c_device_id * id)3147 static int IMX464_probe(struct i2c_client *client,
3148 const struct i2c_device_id *id)
3149 {
3150 struct device *dev = &client->dev;
3151 struct device_node *node = dev->of_node;
3152 struct IMX464 *IMX464;
3153 struct v4l2_subdev *sd;
3154 struct device_node *endpoint;
3155 char facing[2];
3156 int ret;
3157 u32 i, hdr_mode = 0;
3158 const char *sync_mode_name = NULL;
3159
3160
3161 dev_info(dev, "driver version: %02x.%02x.%02x",
3162 DRIVER_VERSION >> 16,
3163 (DRIVER_VERSION & 0xff00) >> 8,
3164 DRIVER_VERSION & 0x00ff);
3165
3166 IMX464 = devm_kzalloc(dev, sizeof(*IMX464), GFP_KERNEL);
3167 if (!IMX464)
3168 return -ENOMEM;
3169
3170 ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
3171 &IMX464->module_index);
3172 ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
3173 &IMX464->module_facing);
3174 ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME,
3175 &IMX464->module_name);
3176 ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME,
3177 &IMX464->len_name);
3178 if (ret) {
3179 dev_err(dev, "could not get module information!\n");
3180 return -EINVAL;
3181 }
3182
3183 ret = of_property_read_string(node, RKMODULE_CAMERA_SYNC_MODE,
3184 &sync_mode_name);
3185 if (ret) {
3186 IMX464->sync_mode = NO_SYNC_MODE;
3187 dev_err(dev, "could not get sync mode!\n");
3188 } else {
3189 if (strcmp(sync_mode_name, RKMODULE_EXTERNAL_MASTER_MODE) == 0)
3190 IMX464->sync_mode = EXTERNAL_MASTER_MODE;
3191 else if (strcmp(sync_mode_name, RKMODULE_INTERNAL_MASTER_MODE) == 0)
3192 IMX464->sync_mode = INTERNAL_MASTER_MODE;
3193 else if (strcmp(sync_mode_name, RKMODULE_SLAVE_MODE) == 0)
3194 IMX464->sync_mode = SLAVE_MODE;
3195 }
3196
3197 ret = of_property_read_u32(node, OF_CAMERA_HDR_MODE,
3198 &hdr_mode);
3199 if (ret) {
3200 hdr_mode = NO_HDR;
3201 dev_warn(dev, " Get hdr mode failed! no hdr default\n");
3202 }
3203 IMX464->client = client;
3204 endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
3205 if (!endpoint) {
3206 dev_err(dev, "Failed to get endpoint\n");
3207 return -EINVAL;
3208 }
3209 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
3210 &IMX464->bus_cfg);
3211 if (ret) {
3212 dev_err(dev, "Failed to get bus cfg\n");
3213 return ret;
3214 }
3215 if (IMX464->bus_cfg.bus.mipi_csi2.num_data_lanes == 4) {
3216 IMX464->support_modes = supported_modes;
3217 IMX464->cfg_num = ARRAY_SIZE(supported_modes);
3218 } else {
3219 IMX464->support_modes = supported_modes_2lane;
3220 IMX464->cfg_num = ARRAY_SIZE(supported_modes_2lane);
3221 }
3222
3223 for (i = 0; i < IMX464->cfg_num; i++) {
3224 if (hdr_mode == IMX464->support_modes[i].hdr_mode) {
3225 IMX464->cur_mode = &IMX464->support_modes[i];
3226 break;
3227 }
3228 }
3229 IMX464->cur_mode = &IMX464->support_modes[0];
3230 IMX464->xvclk = devm_clk_get(dev, "xvclk");
3231 if (IS_ERR(IMX464->xvclk)) {
3232 dev_err(dev, "Failed to get xvclk\n");
3233 return -EINVAL;
3234 }
3235
3236 IMX464->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
3237 if (IS_ERR(IMX464->reset_gpio))
3238 dev_warn(dev, "Failed to get reset-gpios\n");
3239
3240 IMX464->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
3241 if (IS_ERR(IMX464->pwdn_gpio))
3242 dev_warn(dev, "Failed to get pwdn-gpios\n");
3243
3244 IMX464->pinctrl = devm_pinctrl_get(dev);
3245 if (!IS_ERR(IMX464->pinctrl)) {
3246 IMX464->pins_default =
3247 pinctrl_lookup_state(IMX464->pinctrl,
3248 OF_CAMERA_PINCTRL_STATE_DEFAULT);
3249 if (IS_ERR(IMX464->pins_default))
3250 dev_err(dev, "could not get default pinstate\n");
3251
3252 IMX464->pins_sleep =
3253 pinctrl_lookup_state(IMX464->pinctrl,
3254 OF_CAMERA_PINCTRL_STATE_SLEEP);
3255 if (IS_ERR(IMX464->pins_sleep))
3256 dev_err(dev, "could not get sleep pinstate\n");
3257 } else {
3258 dev_err(dev, "no pinctrl\n");
3259 }
3260
3261 ret = IMX464_configure_regulators(IMX464);
3262 if (ret) {
3263 dev_err(dev, "Failed to get power regulators\n");
3264 return ret;
3265 }
3266
3267 mutex_init(&IMX464->mutex);
3268
3269 sd = &IMX464->subdev;
3270 v4l2_i2c_subdev_init(sd, client, &IMX464_subdev_ops);
3271 ret = IMX464_initialize_controls(IMX464);
3272 if (ret)
3273 goto err_destroy_mutex;
3274
3275 ret = __IMX464_power_on(IMX464);
3276 if (ret)
3277 goto err_free_handler;
3278
3279 ret = IMX464_check_sensor_id(IMX464, client);
3280 if (ret)
3281 goto err_power_off;
3282
3283 #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
3284 sd->internal_ops = &IMX464_internal_ops;
3285 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
3286 V4L2_SUBDEV_FL_HAS_EVENTS;
3287 #endif
3288 #if defined(CONFIG_MEDIA_CONTROLLER)
3289 IMX464->pad.flags = MEDIA_PAD_FL_SOURCE;
3290 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
3291 ret = media_entity_pads_init(&sd->entity, 1, &IMX464->pad);
3292 if (ret < 0)
3293 goto err_power_off;
3294 #endif
3295
3296 memset(facing, 0, sizeof(facing));
3297 if (strcmp(IMX464->module_facing, "back") == 0)
3298 facing[0] = 'b';
3299 else
3300 facing[0] = 'f';
3301
3302 snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s",
3303 IMX464->module_index, facing,
3304 IMX464_NAME, dev_name(sd->dev));
3305 ret = v4l2_async_register_subdev_sensor_common(sd);
3306 if (ret) {
3307 dev_err(dev, "v4l2 async register subdev failed\n");
3308 goto err_clean_entity;
3309 }
3310
3311 pm_runtime_set_active(dev);
3312 pm_runtime_enable(dev);
3313 pm_runtime_idle(dev);
3314
3315 #ifdef USED_SYS_DEBUG
3316 add_sysfs_interfaces(dev);
3317 #endif
3318 return 0;
3319
3320 err_clean_entity:
3321 #if defined(CONFIG_MEDIA_CONTROLLER)
3322 media_entity_cleanup(&sd->entity);
3323 #endif
3324 err_power_off:
3325 __IMX464_power_off(IMX464);
3326 err_free_handler:
3327 v4l2_ctrl_handler_free(&IMX464->ctrl_handler);
3328 err_destroy_mutex:
3329 mutex_destroy(&IMX464->mutex);
3330
3331 return ret;
3332 }
3333
IMX464_remove(struct i2c_client * client)3334 static int IMX464_remove(struct i2c_client *client)
3335 {
3336 struct v4l2_subdev *sd = i2c_get_clientdata(client);
3337 struct IMX464 *IMX464 = to_IMX464(sd);
3338
3339 v4l2_async_unregister_subdev(sd);
3340 #if defined(CONFIG_MEDIA_CONTROLLER)
3341 media_entity_cleanup(&sd->entity);
3342 #endif
3343 v4l2_ctrl_handler_free(&IMX464->ctrl_handler);
3344 mutex_destroy(&IMX464->mutex);
3345
3346 pm_runtime_disable(&client->dev);
3347 if (!pm_runtime_status_suspended(&client->dev))
3348 __IMX464_power_off(IMX464);
3349 pm_runtime_set_suspended(&client->dev);
3350 #ifdef USED_SYS_DEBUG
3351 remove_sysfs_interfaces(&client->dev);
3352 #endif
3353 return 0;
3354 }
3355
3356 #if IS_ENABLED(CONFIG_OF)
3357 static const struct of_device_id IMX464_of_match[] = {
3358 { .compatible = "sony,imx464" },
3359 {},
3360 };
3361 MODULE_DEVICE_TABLE(of, IMX464_of_match);
3362 #endif
3363
3364 static const struct i2c_device_id IMX464_match_id[] = {
3365 { "sony,imx464", 0 },
3366 { },
3367 };
3368
3369 static struct i2c_driver IMX464_i2c_driver = {
3370 .driver = {
3371 .name = IMX464_NAME,
3372 .pm = &IMX464_pm_ops,
3373 .of_match_table = of_match_ptr(IMX464_of_match),
3374 },
3375 .probe = &IMX464_probe,
3376 .remove = &IMX464_remove,
3377 .id_table = IMX464_match_id,
3378 };
3379
sensor_mod_init(void)3380 static int __init sensor_mod_init(void)
3381 {
3382 return i2c_add_driver(&IMX464_i2c_driver);
3383 }
3384
sensor_mod_exit(void)3385 static void __exit sensor_mod_exit(void)
3386 {
3387 i2c_del_driver(&IMX464_i2c_driver);
3388 }
3389
3390 device_initcall_sync(sensor_mod_init);
3391 module_exit(sensor_mod_exit);
3392
3393 MODULE_DESCRIPTION("Sony IMX464 sensor driver");
3394 MODULE_LICENSE("GPL v2");
3395