1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * sc4210 driver
4 *
5 * Copyright (C) 2022 Rockchip Electronics Co., Ltd.
6 *
7 * V0.0X01.0X00 first version.
8 */
9
10 //#define DEBUG
11 #include <linux/clk.h>
12 #include <linux/device.h>
13 #include <linux/delay.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/i2c.h>
16 #include <linux/module.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/of.h>
19 #include <linux/of_graph.h>
20 #include <linux/regulator/consumer.h>
21 #include <linux/sysfs.h>
22 #include <linux/pinctrl/consumer.h>
23 #include <linux/slab.h>
24 #include <linux/version.h>
25 #include <linux/rk-camera-module.h>
26 #include <linux/rk-preisp.h>
27 #include <media/media-entity.h>
28 #include <media/v4l2-common.h>
29 #include <media/v4l2-async.h>
30 #include <media/v4l2-device.h>
31 #include <media/v4l2-event.h>
32 #include <media/v4l2-fwnode.h>
33 #include <media/v4l2-ctrls.h>
34 #include <media/v4l2-subdev.h>
35 #include <media/v4l2-image-sizes.h>
36 #include <media/v4l2-mediabus.h>
37 #include <media/v4l2-subdev.h>
38 #include <linux/pinctrl/consumer.h>
39 #include <stdarg.h>
40 #include <linux/linkage.h>
41 #include <linux/types.h>
42 #include <linux/printk.h>
43
44 #include <linux/rk-camera-module.h>
45 #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x00)
46
47 #ifndef V4L2_CID_DIGITAL_GAIN
48 #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
49 #endif
50
51 #define SC4210_LINK_FREQ_2LANE_LINEAR 303000000 // 607.5Mbps
52 #define SC4210_LINK_FREQ_2LANE_HDR2 540000000 // 1080Mbps
53 #define SC4210_LINK_FREQ_4LANE_LINEAR 202500000 // 405Mbps
54 #define SC4210_LINK_FREQ_4LANE_HDR2 364500000 // 729Mbps
55
56 #define SC4210_PIXEL_RATES_2LANE_LINEAR (SC4210_LINK_FREQ_2LANE_LINEAR / 10 * 2 * 2)
57 #define SC4210_PIXEL_RATES_2LANE_HDR2 (SC4210_LINK_FREQ_2LANE_HDR2 / 10 * 2 * 2)
58 #define SC4210_PIXEL_RATES_4LANE_LINEAR (SC4210_LINK_FREQ_4LANE_LINEAR / 10 * 4 * 2)
59 #define SC4210_PIXEL_RATES_4LANE_HDR2 (SC4210_LINK_FREQ_4LANE_HDR2 / 10 * 4 * 2)
60 #define SC4210_MAX_PIXEL_RATE (SC4210_LINK_FREQ_4LANE_HDR2 / 10 * 4 * 2)
61
62 #define SC4210_XVCLK_FREQ 27000000
63
64 #define SC4210_CHIP_ID 0x4210
65 #define SC4210_REG_CHIP_ID 0x3107
66
67 #define SC4210_REG_CTRL_MODE 0x0100
68 #define SC4210_MODE_SW_STANDBY 0x0
69 #define SC4210_MODE_STREAMING BIT(0)
70
71 #define SC4210_REG_EXPOSURE_H 0x3e00
72 #define SC4210_REG_EXPOSURE_M 0x3e01
73 #define SC4210_REG_EXPOSURE_L 0x3e02
74 #define SC4210_EXPOSURE_MIN 2
75 #define SC4210_EXPOSURE_STEP 1
76
77 #define SC4210_REG_DIG_GAIN 0x3e06
78 #define SC4210_REG_DIG_FINE_GAIN 0x3e07
79 #define SC4210_REG_ANA_GAIN 0x3e08
80 #define SC4210_REG_ANA_FINE_GAIN 0x3e09
81 #define SC4210_GAIN_MIN 1000
82 #define SC4210_GAIN_MAX (43.65 * 32 * 1000)
83 #define SC4210_GAIN_STEP 1
84 #define SC4210_GAIN_DEFAULT 1000
85
86 #define SC4210_REG_VTS_H 0x320e
87 #define SC4210_REG_VTS_L 0x320f
88 #define SC4210_VTS_MAX 0x7fff
89
90 #define SC4210_SOFTWARE_RESET_REG 0x0103
91
92 // short frame exposure
93 #define SC4210_REG_SHORT_EXPOSURE_H 0x3e22
94 #define SC4210_REG_SHORT_EXPOSURE_M 0x3e04
95 #define SC4210_REG_SHORT_EXPOSURE_L 0x3e05
96 #define SC4210_REG_MAX_SHORT_EXP_H 0x3e23
97 #define SC4210_REG_MAX_SHORT_EXP_L 0x3e24
98 #define SC4210_HDR_EXPOSURE_MIN 5
99 #define SC4210_HDR_EXPOSURE_STEP 4
100 #define SC4210_MAX_SHORT_EXPOSURE 608
101
102 // short frame gain
103 #define SC4210_REG_SDIG_GAIN 0x3e10
104 #define SC4210_REG_SDIG_FINE_GAIN 0x3e11
105 #define SC4210_REG_SANA_GAIN 0x3e12
106 #define SC4210_REG_SANA_FINE_GAIN 0x3e13
107
108 //group hold
109 #define SC4210_GROUP_UPDATE_ADDRESS 0x3800
110 #define SC4210_GROUP_UPDATE_START_DATA 0x00
111 #define SC4210_GROUP_UPDATE_END_DATA 0x10
112 #define SC4210_GROUP_UPDATE_LAUNCH 0x40
113
114 #define SC4210_FLIP_MIRROR_REG 0x3221
115 #define SC4210_FLIP_MASK 0x60
116 #define SC4210_MIRROR_MASK 0x06
117
118 #define REG_NULL 0xFFFF
119
120 #define SC4210_REG_VALUE_08BIT 1
121 #define SC4210_REG_VALUE_16BIT 2
122 #define SC4210_REG_VALUE_24BIT 3
123
124 #define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default"
125 #define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep"
126 #define OF_CAMERA_HDR_MODE "rockchip,camera-hdr-mode"
127
128 #define SC4210_NAME "sc4210"
129
130 #define SC4210_FETCH_EXP_H(VAL) (((VAL) >> 12) & 0xF)
131 #define SC4210_FETCH_EXP_M(VAL) (((VAL) >> 4) & 0xFF)
132 #define SC4210_FETCH_EXP_L(VAL) (((VAL) & 0xF) << 4)
133
134 static const char * const sc4210_supply_names[] = {
135 "avdd", /* Analog power */
136 "dovdd", /* Digital I/O power */
137 "dvdd", /* Digital core power */
138 };
139
140 #define sc4210_NUM_SUPPLIES ARRAY_SIZE(sc4210_supply_names)
141 struct regval {
142 u16 addr;
143 u8 val;
144 };
145
146 struct sc4210_mode {
147 u32 bus_fmt;
148 u32 width;
149 u32 height;
150 struct v4l2_fract max_fps;
151 u32 hts_def;
152 u32 vts_def;
153 u32 exp_def;
154 u32 mipi_freq_idx;
155 u32 bpp;
156 const struct regval *reg_list;
157 u32 hdr_mode;
158 u32 vc[PAD_MAX];
159 };
160
161 struct sc4210 {
162 struct i2c_client *client;
163 struct clk *xvclk;
164 struct gpio_desc *reset_gpio;
165 struct gpio_desc *pwdn_gpio;
166 struct regulator_bulk_data supplies[sc4210_NUM_SUPPLIES];
167 struct pinctrl *pinctrl;
168 struct pinctrl_state *pins_default;
169 struct pinctrl_state *pins_sleep;
170
171 struct v4l2_subdev subdev;
172 struct media_pad pad;
173 struct v4l2_ctrl_handler ctrl_handler;
174 struct v4l2_ctrl *exposure;
175 struct v4l2_ctrl *anal_gain;
176 struct v4l2_ctrl *digi_gain;
177 struct v4l2_ctrl *hblank;
178 struct v4l2_ctrl *vblank;
179 struct v4l2_ctrl *pixel_rate;
180 struct v4l2_ctrl *link_freq;
181 struct mutex mutex;
182 bool streaming;
183 bool power_on;
184 const struct sc4210_mode *support_modes;
185 const struct sc4210_mode *cur_mode;
186 struct v4l2_fract cur_fps;
187 u32 support_modes_num;
188 unsigned int lane_num;
189 u32 module_index;
190 const char *module_facing;
191 const char *module_name;
192 const char *len_name;
193 bool has_init_exp;
194 struct preisp_hdrae_exp_s init_hdrae_exp;
195 u32 cur_vts;
196 };
197
198 #define to_sc4210(sd) container_of(sd, struct sc4210, subdev)
199
200 /*
201 * sc4210 27Mhz
202 * max_framerate 30fps
203 * mipi_datarate per lane 405Mbps, 4lane
204 */
205 static const struct regval sc4210_linear_10_30fps_2560x1440_4lane_regs[] = {
206 {0x0103, 0x01},
207 {0x0100, 0x00},
208 {0x36e9, 0x80},
209 {0x36f9, 0x80},
210 {0x3001, 0x07},
211 {0x3002, 0xc0},
212 {0x300a, 0x2c},
213 {0x300f, 0x00},
214 {0x3018, 0x73},
215 {0x301f, 0x3b},
216 {0x3031, 0x0a},
217 {0x3038, 0x22},
218 {0x320c, 0x05},
219 {0x320d, 0x46},
220 {0x3220, 0x10},
221 {0x3225, 0x01},
222 {0x3227, 0x03},
223 {0x3229, 0x08},
224 {0x3231, 0x01},
225 {0x3241, 0x02},
226 {0x3243, 0x03},
227 {0x3249, 0x17},
228 {0x3251, 0x08},
229 {0x3253, 0x08},
230 {0x325e, 0x00},
231 {0x325f, 0x00},
232 {0x3273, 0x01},
233 {0x3301, 0x28},
234 {0x3302, 0x18},
235 {0x3000, 0x00},
236 {0x3304, 0x20},
237 {0x3305, 0x00},
238 {0x3306, 0x74},
239 {0x3308, 0x10},
240 {0x3309, 0x40},
241 {0x330a, 0x00},
242 {0x330b, 0xe8},
243 {0x330e, 0x18},
244 {0x3312, 0x02},
245 {0x3314, 0x84},
246 {0x331e, 0x19},
247 {0x331f, 0x39},
248 {0x3320, 0x05},
249 {0x3338, 0x10},
250 {0x334c, 0x10},
251 {0x335d, 0x20},
252 {0x3366, 0x92},
253 {0x3367, 0x08},
254 {0x3368, 0x05},
255 {0x3369, 0xdc},
256 {0x336a, 0x0b},
257 {0x336b, 0xb8},
258 {0x336c, 0xc2},
259 {0x337a, 0x08},
260 {0x337b, 0x10},
261 {0x337e, 0x40},
262 {0x33a3, 0x0c},
263 {0x33e0, 0xa0},
264 {0x33e1, 0x08},
265 {0x33e2, 0x00},
266 {0x33e3, 0x10},
267 {0x33e4, 0x10},
268 {0x33e5, 0x00},
269 {0x33e6, 0x10},
270 {0x33e7, 0x10},
271 {0x33e8, 0x00},
272 {0x33e9, 0x10},
273 {0x33ea, 0x16},
274 {0x33eb, 0x00},
275 {0x33ec, 0x10},
276 {0x33ed, 0x18},
277 {0x33ee, 0xa0},
278 {0x33ef, 0x08},
279 {0x33f4, 0x00},
280 {0x33f5, 0x10},
281 {0x33f6, 0x10},
282 {0x33f7, 0x00},
283 {0x33f8, 0x10},
284 {0x33f9, 0x10},
285 {0x33fa, 0x00},
286 {0x33fb, 0x10},
287 {0x33fc, 0x16},
288 {0x33fd, 0x00},
289 {0x33fe, 0x10},
290 {0x33ff, 0x18},
291 {0x360f, 0x05},
292 {0x3622, 0xff},
293 {0x3624, 0x07},
294 {0x3625, 0x02},
295 {0x3630, 0xc4},
296 {0x3631, 0x80},
297 {0x3632, 0x88},
298 {0x3633, 0x22},
299 {0x3634, 0x64},
300 {0x3635, 0x40},
301 {0x3636, 0x20},
302 {0x3638, 0x28},
303 {0x363b, 0x03},
304 {0x363c, 0x08},
305 {0x363d, 0x08},
306 {0x366e, 0x04},
307 {0x3670, 0x48},
308 {0x3671, 0xff},
309 {0x3672, 0x1f},
310 {0x3673, 0x1f},
311 {0x367a, 0x40},
312 {0x367b, 0x40},
313 {0x3690, 0x42},
314 {0x3691, 0x44},
315 {0x3692, 0x44},
316 {0x3699, 0x80},
317 {0x369a, 0x9f},
318 {0x369b, 0x9f},
319 {0x369c, 0x40},
320 {0x369d, 0x40},
321 {0x36a2, 0x40},
322 {0x36a3, 0x40},
323 {0x36cc, 0x2c},
324 {0x36cd, 0x30},
325 {0x36ce, 0x30},
326 {0x36d0, 0x20},
327 {0x36d1, 0x40},
328 {0x36d2, 0x40},
329 {0x36ea, 0x36},
330 {0x36eb, 0x16},
331 {0x36ec, 0x03},
332 {0x36ed, 0x0c},
333 {0x36fa, 0x37},
334 {0x36fb, 0x14},
335 {0x36fc, 0x00},
336 {0x36fd, 0x2c},
337 {0x3817, 0x20},
338 {0x3905, 0xd8},
339 {0x3908, 0x11},
340 {0x391b, 0x80},
341 {0x391c, 0x0f},
342 {0x391d, 0x21},
343 {0x3933, 0x27},
344 {0x3934, 0xf5},
345 {0x3935, 0x80},
346 {0x3936, 0x1f},
347 {0x3940, 0x6e},
348 {0x3942, 0x07},
349 {0x3943, 0xf6},
350 {0x3980, 0x00},
351 {0x3981, 0x12},
352 {0x3982, 0x00},
353 {0x3983, 0x07},
354 {0x3984, 0x00},
355 {0x3985, 0x03},
356 {0x3986, 0x00},
357 {0x3987, 0x04},
358 {0x3988, 0x00},
359 {0x3989, 0x01},
360 {0x398a, 0x00},
361 {0x398b, 0x03},
362 {0x398c, 0x00},
363 {0x398d, 0x06},
364 {0x398e, 0x00},
365 {0x398f, 0x0d},
366 {0x3990, 0x00},
367 {0x3991, 0x12},
368 {0x3992, 0x00},
369 {0x3993, 0x09},
370 {0x3994, 0x00},
371 {0x3995, 0x02},
372 {0x3996, 0x00},
373 {0x3997, 0x04},
374 {0x3998, 0x00},
375 {0x3999, 0x0a},
376 {0x399a, 0x00},
377 {0x399b, 0x10},
378 {0x399c, 0x00},
379 {0x399d, 0x16},
380 {0x399e, 0x00},
381 {0x399f, 0x1f},
382 {0x39a0, 0x02},
383 {0x39a1, 0x04},
384 {0x39a2, 0x10},
385 {0x39a3, 0x13},
386 {0x39a4, 0x97},
387 {0x39a5, 0x43},
388 {0x39a6, 0x20},
389 {0x39a7, 0x05},
390 {0x39a8, 0x23},
391 {0x39a9, 0x43},
392 {0x39aa, 0x85},
393 {0x39ab, 0x95},
394 {0x39ac, 0x24},
395 {0x39ad, 0x18},
396 {0x39ae, 0x11},
397 {0x39af, 0x04},
398 {0x39b9, 0x00},
399 {0x39ba, 0x19},
400 {0x39bb, 0xba},
401 {0x39bc, 0x00},
402 {0x39bd, 0x05},
403 {0x39be, 0x99},
404 {0x39bf, 0x00},
405 {0x39c0, 0x00},
406 {0x39c5, 0x71},
407 {0x3e00, 0x00},
408 {0x3e01, 0xbb},
409 {0x3e02, 0x40},
410 {0x3e03, 0x0b},
411 {0x3e06, 0x00},
412 {0x3e07, 0x80},
413 {0x3e08, 0x03},
414 {0x3e09, 0x40},
415 {0x3e0e, 0x6a},
416 {0x3e26, 0x40},
417 {0x4407, 0xb0},
418 {0x4418, 0x0b},
419 {0x4501, 0xb4},
420 {0x4509, 0x20},
421 {0x4603, 0x00},
422 {0x4800, 0x24},
423 {0x4837, 0x28},
424 {0x5000, 0x0e},
425 {0x550f, 0x20},
426 {0x5784, 0x10},
427 {0x5785, 0x08},
428 {0x5787, 0x06},
429 {0x5788, 0x06},
430 {0x5789, 0x00},
431 {0x578a, 0x06},
432 {0x578b, 0x06},
433 {0x578c, 0x00},
434 {0x5790, 0x10},
435 {0x5791, 0x10},
436 {0x5792, 0x00},
437 {0x5793, 0x10},
438 {0x5794, 0x10},
439 {0x5795, 0x00},
440 {0x57c4, 0x10},
441 {0x57c5, 0x08},
442 {0x57c7, 0x06},
443 {0x57c8, 0x06},
444 {0x57c9, 0x00},
445 {0x57ca, 0x06},
446 {0x57cb, 0x06},
447 {0x57cc, 0x00},
448 {0x57d0, 0x10},
449 {0x57d1, 0x10},
450 {0x57d2, 0x00},
451 {0x57d3, 0x10},
452 {0x57d4, 0x10},
453 {0x57d5, 0x00},
454 {0x36e9, 0x27},
455 {0x36f9, 0x20},
456 //{0x0100, 0x01},
457 {REG_NULL, 0x0},
458 };
459
460 /*
461 * sc4210 27Mhz
462 * max_framerate 30fps
463 * mipi_datarate per lane 729Mbps, 4lane
464 */
465 static const struct regval sc4210_hdr_10_30fps_2560x1440_4lane_regs[] = {
466 {0x0103, 0x01},
467 {0x0100, 0x00},
468 {0x36e9, 0x80},
469 {0x36f9, 0x80},
470 {0x3001, 0x07},
471 {0x3002, 0xc0},
472 {0x300a, 0x2c},
473 {0x300f, 0x00},
474 {0x3018, 0x73},
475 {0x301f, 0x3e},
476 {0x3031, 0x0a},
477 {0x3038, 0x22},
478 {0x3207, 0xa7},
479 {0x320c, 0x05},
480 {0x320d, 0x58},
481 {0x320e, 0x0b},
482 {0x320f, 0x90},
483 {0x3213, 0x04},
484 {0x3220, 0x50},
485 {0x3225, 0x01},
486 {0x3227, 0x03},
487 {0x3229, 0x08},
488 {0x3231, 0x01},
489 {0x3241, 0x02},
490 {0x3243, 0x03},
491 {0x3249, 0x17},
492 {0x3250, 0x3f},
493 {0x3251, 0x08},
494 {0x3253, 0x10},
495 {0x325e, 0x00},
496 {0x3000, 0x00},
497 {0x325f, 0x00},
498 {0x3273, 0x01},
499 {0x3301, 0x15},
500 {0x3302, 0x18},
501 {0x3304, 0x20},
502 {0x3305, 0x00},
503 {0x3306, 0x78},
504 {0x3308, 0x10},
505 {0x3309, 0x50},
506 {0x330a, 0x00},
507 {0x330b, 0xe8},
508 {0x330e, 0x20},
509 {0x3312, 0x02},
510 {0x3314, 0x84},
511 {0x331e, 0x19},
512 {0x331f, 0x49},
513 {0x3320, 0x05},
514 {0x3338, 0x10},
515 {0x334c, 0x10},
516 {0x335d, 0x20},
517 {0x335e, 0x02},
518 {0x335f, 0x04},
519 {0x3360, 0x20},
520 {0x3362, 0x72},
521 {0x3364, 0x1e},
522 {0x3366, 0x92},
523 {0x3367, 0x08},
524 {0x3368, 0x0a},
525 {0x3369, 0xd4},
526 {0x336a, 0x15},
527 {0x336b, 0xa8},
528 {0x336c, 0xc2},
529 {0x337a, 0x08},
530 {0x337b, 0x10},
531 {0x337c, 0x06},
532 {0x337d, 0x0a},
533 {0x337e, 0x40},
534 {0x3390, 0x08},
535 {0x3391, 0x18},
536 {0x3392, 0x38},
537 {0x3393, 0x13},
538 {0x3394, 0x24},
539 {0x3395, 0x24},
540 {0x3396, 0x08},
541 {0x3397, 0x18},
542 {0x3398, 0x38},
543 {0x3399, 0x11},
544 {0x339a, 0x14},
545 {0x339b, 0x24},
546 {0x339c, 0x24},
547 {0x33a2, 0x08},
548 {0x33a3, 0x0c},
549 {0x33e0, 0xa0},
550 {0x33e1, 0x08},
551 {0x33e2, 0x00},
552 {0x33e3, 0x10},
553 {0x33e4, 0x10},
554 {0x33e5, 0x00},
555 {0x33e6, 0x10},
556 {0x33e7, 0x10},
557 {0x33e8, 0x00},
558 {0x33e9, 0x10},
559 {0x33ea, 0x16},
560 {0x33eb, 0x00},
561 {0x33ec, 0x10},
562 {0x33ed, 0x18},
563 {0x33ee, 0xa0},
564 {0x33ef, 0x08},
565 {0x33f4, 0x00},
566 {0x33f5, 0x10},
567 {0x33f6, 0x10},
568 {0x33f7, 0x00},
569 {0x33f8, 0x10},
570 {0x33f9, 0x10},
571 {0x33fa, 0x00},
572 {0x33fb, 0x10},
573 {0x33fc, 0x16},
574 {0x33fd, 0x00},
575 {0x33fe, 0x10},
576 {0x33ff, 0x18},
577 {0x360f, 0x05},
578 {0x3622, 0xff},
579 {0x3624, 0x07},
580 {0x3625, 0x0a},
581 {0x3630, 0xc4},
582 {0x3631, 0x80},
583 {0x3632, 0x88},
584 {0x3633, 0x42},
585 {0x3634, 0x64},
586 {0x3635, 0x20},
587 {0x3636, 0x20},
588 {0x3638, 0x28},
589 {0x363b, 0x03},
590 {0x363c, 0x06},
591 {0x363d, 0x06},
592 {0x366e, 0x04},
593 {0x3670, 0x4a},
594 {0x3671, 0xff},
595 {0x3672, 0x9f},
596 {0x3673, 0x9f},
597 {0x3674, 0xc4},
598 {0x3675, 0xc4},
599 {0x3676, 0xb8},
600 {0x367a, 0x40},
601 {0x367b, 0x48},
602 {0x367c, 0x40},
603 {0x367d, 0x48},
604 {0x3690, 0x43},
605 {0x3691, 0x55},
606 {0x3692, 0x66},
607 {0x3699, 0x8c},
608 {0x369a, 0x96},
609 {0x369b, 0x9f},
610 {0x369c, 0x40},
611 {0x369d, 0x48},
612 {0x36a2, 0x40},
613 {0x36a3, 0x48},
614 {0x36cc, 0x2c},
615 {0x36cd, 0x30},
616 {0x36ce, 0x30},
617 {0x36d0, 0x20},
618 {0x36d1, 0x40},
619 {0x36d2, 0x40},
620 {0x36ea, 0x37},
621 {0x36eb, 0x06},
622 {0x36ec, 0x03},
623 {0x36ed, 0x0c},
624 {0x36fa, 0x37},
625 {0x36fb, 0x04},
626 {0x36fc, 0x00},
627 {0x36fd, 0x2c},
628 {0x3817, 0x20},
629 {0x3905, 0x98},
630 {0x3908, 0x11},
631 {0x391b, 0x80},
632 {0x391c, 0x0f},
633 {0x391d, 0x21},
634 {0x3933, 0x1f},
635 {0x3934, 0xff},
636 {0x3935, 0x80},
637 {0x3936, 0x1f},
638 {0x393e, 0x01},
639 {0x3940, 0x60},
640 {0x3942, 0x04},
641 {0x3943, 0xd0},
642 {0x3980, 0x00},
643 {0x3981, 0x30},
644 {0x3982, 0x00},
645 {0x3983, 0x2c},
646 {0x3984, 0x00},
647 {0x3985, 0x15},
648 {0x3986, 0x00},
649 {0x3987, 0x10},
650 {0x3988, 0x00},
651 {0x3989, 0x30},
652 {0x398a, 0x00},
653 {0x398b, 0x28},
654 {0x398c, 0x00},
655 {0x398d, 0x30},
656 {0x398e, 0x00},
657 {0x398f, 0x70},
658 {0x3990, 0x0a},
659 {0x3991, 0x00},
660 {0x3992, 0x00},
661 {0x3993, 0x60},
662 {0x3994, 0x00},
663 {0x3995, 0x30},
664 {0x3996, 0x00},
665 {0x3997, 0x10},
666 {0x3998, 0x00},
667 {0x3999, 0x1c},
668 {0x399a, 0x00},
669 {0x399b, 0x48},
670 {0x399c, 0x00},
671 {0x399d, 0x90},
672 {0x399e, 0x00},
673 {0x399f, 0xc0},
674 {0x39a0, 0x14},
675 {0x39a1, 0x28},
676 {0x39a2, 0x48},
677 {0x39a3, 0x70},
678 {0x39a4, 0x18},
679 {0x39a5, 0x04},
680 {0x39a6, 0x08},
681 {0x39a7, 0x04},
682 {0x39a8, 0x01},
683 {0x39a9, 0x14},
684 {0x39aa, 0x28},
685 {0x39ab, 0x50},
686 {0x39ac, 0x30},
687 {0x39ad, 0x20},
688 {0x39ae, 0x10},
689 {0x39af, 0x08},
690 {0x39b9, 0x00},
691 {0x39ba, 0x00},
692 {0x39bb, 0x00},
693 {0x39bc, 0x00},
694 {0x39bd, 0x58},
695 {0x39be, 0xc0},
696 {0x39bf, 0x00},
697 {0x39c0, 0x00},
698 {0x39c5, 0x41},
699 {0x3c09, 0x4a},
700 {0x3c10, 0x04},
701 {0x3c11, 0x20},
702 {0x3c12, 0x04},
703 {0x3c13, 0x20},
704 {0x3c14, 0x0f},
705 {0x3e00, 0x01},
706 {0x3e01, 0x5a},
707 {0x3e02, 0x00},
708 {0x3e03, 0x0b},
709 {0x3e04, 0x15},
710 {0x3e05, 0xa0},
711 {0x3e06, 0x00},
712 {0x3e07, 0x80},
713 {0x3e08, 0x03},
714 {0x3e09, 0x40},
715 {0x3e0e, 0x6a},
716 {0x3e10, 0x00},
717 {0x3e11, 0x80},
718 {0x3e12, 0x03},
719 {0x3e13, 0x40},
720 {0x3e23, 0x00},
721 {0x3e24, 0xbc},
722 {0x3e26, 0x40},
723 {0x4401, 0x0b},
724 {0x4407, 0xb0},
725 {0x4418, 0x16},
726 {0x4501, 0xa4},
727 {0x4509, 0x08},
728 {0x4603, 0x00},
729 {0x4800, 0x24},
730 {0x4816, 0x11},
731 {0x4819, 0x40},
732 {0x4829, 0x01},
733 {0x4837, 0x16},
734 {0x5000, 0x0e},
735 {0x550f, 0x20},
736 {0x5784, 0x10},
737 {0x5785, 0x08},
738 {0x5787, 0x06},
739 {0x5788, 0x06},
740 {0x5789, 0x00},
741 {0x578a, 0x06},
742 {0x578b, 0x06},
743 {0x578c, 0x00},
744 {0x5790, 0x10},
745 {0x5791, 0x10},
746 {0x5792, 0x00},
747 {0x5793, 0x10},
748 {0x5794, 0x10},
749 {0x5795, 0x00},
750 {0x57c4, 0x10},
751 {0x57c5, 0x08},
752 {0x57c7, 0x06},
753 {0x57c8, 0x06},
754 {0x57c9, 0x00},
755 {0x57ca, 0x06},
756 {0x57cb, 0x06},
757 {0x57cc, 0x00},
758 {0x57d0, 0x10},
759 {0x57d1, 0x10},
760 {0x57d2, 0x00},
761 {0x57d3, 0x10},
762 {0x57d4, 0x10},
763 {0x57d5, 0x00},
764 {0x36e9, 0x27},
765 {0x36f9, 0x20},
766 //{0x0100, 0x01},
767 {REG_NULL, 0x00},
768 };
769
770 /*
771 * Xclk 27Mhz
772 * max_framerate 30fps
773 * mipi_datarate per lane 607.5Mbps, 2lane
774 */
775 static const struct regval sc4210_liner_10_30fps_2560x1440_2lane_regs[] = {
776 {0x0103, 0x01},
777 {0x0100, 0x00},
778 {0x36e9, 0xd1},
779 {0x36f9, 0xd1},
780 {0x3001, 0x07},
781 {0x3002, 0xc0},
782 {0x300a, 0x2c},
783 {0x300f, 0x00},
784 {0x3018, 0x33},
785 {0x301f, 0x21},
786 {0x3031, 0x0a},
787 {0x3038, 0x22},
788 {0x320c, 0x05},
789 {0x320d, 0x46},
790 {0x3220, 0x10},
791 {0x3225, 0x01},
792 {0x3227, 0x03},
793 {0x3229, 0x08},
794 {0x3231, 0x01},
795 {0x3241, 0x02},
796 {0x3243, 0x03},
797 {0x3249, 0x17},
798 {0x3251, 0x08},
799 {0x3253, 0x08},
800 {0x325e, 0x00},
801 {0x325f, 0x00},
802 {0x3273, 0x01},
803 {0x3301, 0x28},
804 {0x3302, 0x18},
805 {0x3304, 0x20},
806 {0x3000, 0x00},
807 {0x3305, 0x00},
808 {0x3306, 0x74},
809 {0x3308, 0x10},
810 {0x3309, 0x40},
811 {0x330a, 0x00},
812 {0x330b, 0xe8},
813 {0x330e, 0x18},
814 {0x3312, 0x02},
815 {0x3314, 0x84},
816 {0x331e, 0x19},
817 {0x331f, 0x39},
818 {0x3320, 0x05},
819 {0x3338, 0x10},
820 {0x334c, 0x10},
821 {0x335d, 0x20},
822 {0x3366, 0x92},
823 {0x3367, 0x08},
824 {0x3368, 0x05},
825 {0x3369, 0xdc},
826 {0x336a, 0x0b},
827 {0x336b, 0xb8},
828 {0x336c, 0xc2},
829 {0x337a, 0x08},
830 {0x337b, 0x10},
831 {0x337e, 0x40},
832 {0x33a3, 0x0c},
833 {0x33e0, 0xa0},
834 {0x33e1, 0x08},
835 {0x33e2, 0x00},
836 {0x33e3, 0x10},
837 {0x33e4, 0x10},
838 {0x33e5, 0x00},
839 {0x33e6, 0x10},
840 {0x33e7, 0x10},
841 {0x33e8, 0x00},
842 {0x33e9, 0x10},
843 {0x33ea, 0x16},
844 {0x33eb, 0x00},
845 {0x33ec, 0x10},
846 {0x33ed, 0x18},
847 {0x33ee, 0xa0},
848 {0x33ef, 0x08},
849 {0x33f4, 0x00},
850 {0x33f5, 0x10},
851 {0x33f6, 0x10},
852 {0x33f7, 0x00},
853 {0x33f8, 0x10},
854 {0x33f9, 0x10},
855 {0x33fa, 0x00},
856 {0x33fb, 0x10},
857 {0x33fc, 0x16},
858 {0x33fd, 0x00},
859 {0x33fe, 0x10},
860 {0x33ff, 0x18},
861 {0x360f, 0x05},
862 {0x3622, 0xff},
863 {0x3624, 0x07},
864 {0x3625, 0x02},
865 {0x3630, 0xc4},
866 {0x3631, 0x80},
867 {0x3632, 0x88},
868 {0x3633, 0x22},
869 {0x3634, 0x64},
870 {0x3635, 0x20},
871 {0x3636, 0x20},
872 {0x3638, 0x28},
873 {0x363b, 0x03},
874 {0x363c, 0x06},
875 {0x363d, 0x06},
876 {0x366e, 0x04},
877 {0x3670, 0x48},
878 {0x3671, 0xff},
879 {0x3672, 0x1f},
880 {0x3673, 0x1f},
881 {0x367a, 0x40},
882 {0x367b, 0x40},
883 {0x3690, 0x42},
884 {0x3691, 0x44},
885 {0x3692, 0x44},
886 {0x3699, 0x80},
887 {0x369a, 0x9f},
888 {0x369b, 0x9f},
889 {0x369c, 0x40},
890 {0x369d, 0x40},
891 {0x36a2, 0x40},
892 {0x36a3, 0x40},
893 {0x36cc, 0x2c},
894 {0x36cd, 0x30},
895 {0x36ce, 0x30},
896 {0x36d0, 0x20},
897 {0x36d1, 0x40},
898 {0x36d2, 0x40},
899 {0x36ea, 0xa8},
900 {0x36eb, 0x04},
901 {0x36ec, 0x03},
902 {0x36ed, 0x0c},
903 {0x36fa, 0x78},
904 {0x36fb, 0x14},
905 {0x36fc, 0x00},
906 {0x36fd, 0x2c},
907 {0x3817, 0x20},
908 {0x3905, 0xd8},
909 {0x3908, 0x11},
910 {0x391b, 0x80},
911 {0x391c, 0x0f},
912 {0x391d, 0x21},
913 {0x3933, 0x24},
914 {0x3934, 0xb0},
915 {0x3935, 0x80},
916 {0x3936, 0x1f},
917 {0x3940, 0x68},
918 {0x3942, 0x04},
919 {0x3943, 0xc0},
920 {0x3980, 0x00},
921 {0x3981, 0x50},
922 {0x3982, 0x00},
923 {0x3983, 0x40},
924 {0x3984, 0x00},
925 {0x3985, 0x20},
926 {0x3986, 0x00},
927 {0x3987, 0x10},
928 {0x3988, 0x00},
929 {0x3989, 0x20},
930 {0x398a, 0x00},
931 {0x398b, 0x30},
932 {0x398c, 0x00},
933 {0x398d, 0x50},
934 {0x398e, 0x00},
935 {0x398f, 0x60},
936 {0x3990, 0x00},
937 {0x3991, 0x70},
938 {0x3992, 0x00},
939 {0x3993, 0x36},
940 {0x3994, 0x00},
941 {0x3995, 0x20},
942 {0x3996, 0x00},
943 {0x3997, 0x14},
944 {0x3998, 0x00},
945 {0x3999, 0x20},
946 {0x399a, 0x00},
947 {0x399b, 0x50},
948 {0x399c, 0x00},
949 {0x399d, 0x90},
950 {0x399e, 0x00},
951 {0x399f, 0xf0},
952 {0x39a0, 0x08},
953 {0x39a1, 0x10},
954 {0x39a2, 0x20},
955 {0x39a3, 0x40},
956 {0x39a4, 0x20},
957 {0x39a5, 0x10},
958 {0x39a6, 0x08},
959 {0x39a7, 0x04},
960 {0x39a8, 0x18},
961 {0x39a9, 0x30},
962 {0x39aa, 0x40},
963 {0x39ab, 0x60},
964 {0x39ac, 0x38},
965 {0x39ad, 0x20},
966 {0x39ae, 0x10},
967 {0x39af, 0x08},
968 {0x39b9, 0x00},
969 {0x39ba, 0xa0},
970 {0x39bb, 0x80},
971 {0x39bc, 0x00},
972 {0x39bd, 0x44},
973 {0x39be, 0x00},
974 {0x39bf, 0x00},
975 {0x39c0, 0x00},
976 {0x39c5, 0x41},
977 {0x3e00, 0x00},
978 {0x3e01, 0xbb},
979 {0x3e02, 0x40},
980 {0x3e03, 0x0b},
981 {0x3e06, 0x00},
982 {0x3e07, 0x80},
983 {0x3e08, 0x03},
984 {0x3e09, 0x40},
985 {0x3e0e, 0x6a},
986 {0x3e26, 0x40},
987 {0x4401, 0x0b},
988 {0x4407, 0xb0},
989 {0x4418, 0x0b},
990 {0x4501, 0xb4},
991 {0x4509, 0x10},
992 {0x4603, 0x00},
993 {0x4837, 0x15},
994 {0x5000, 0x0e},
995 {0x550f, 0x20},
996 {0x5784, 0x10},
997 {0x5785, 0x08},
998 {0x5787, 0x06},
999 {0x5788, 0x06},
1000 {0x5789, 0x00},
1001 {0x578a, 0x06},
1002 {0x578b, 0x06},
1003 {0x578c, 0x00},
1004 {0x5790, 0x10},
1005 {0x5791, 0x10},
1006 {0x5792, 0x00},
1007 {0x5793, 0x10},
1008 {0x5794, 0x10},
1009 {0x5795, 0x00},
1010 {0x57c4, 0x10},
1011 {0x57c5, 0x08},
1012 {0x57c7, 0x06},
1013 {0x57c8, 0x06},
1014 {0x57c9, 0x00},
1015 {0x57ca, 0x06},
1016 {0x57cb, 0x06},
1017 {0x57cc, 0x00},
1018 {0x57d0, 0x10},
1019 {0x57d1, 0x10},
1020 {0x57d2, 0x00},
1021 {0x57d3, 0x10},
1022 {0x57d4, 0x10},
1023 {0x57d5, 0x00},
1024 {0x36e9, 0x51},
1025 {0x36f9, 0x51},
1026 //{0x0100, 0x01},
1027 {REG_NULL, 0x00},
1028 };
1029
1030
1031 /*
1032 * Xclk 27Mhz
1033 * max_framerate 25fps
1034 * mipi_datarate per lane 1080Mbps, 2lane
1035 */
1036 static const struct regval sc4210_hdr_10_25fps_2560x1440_2lane_regs[] = {
1037 {0x0103, 0x01},
1038 {0x0100, 0x00},
1039 {0x36e9, 0x80},
1040 {0x36f9, 0x80},
1041 {0x3001, 0x07},
1042 {0x3002, 0xc0},
1043 {0x300a, 0x2c},
1044 {0x300f, 0x00},
1045 {0x3018, 0x33},
1046 {0x3019, 0x0c},
1047 {0x301f, 0x45},
1048 {0x3031, 0x0a},
1049 {0x3038, 0x22},
1050 {0x3207, 0xa7},
1051 {0x320c, 0x06},
1052 {0x320d, 0x68},
1053 {0x320e, 0x0b},
1054 {0x320f, 0x90},
1055 {0x3213, 0x04},
1056 {0x3220, 0x50},
1057 {0x3225, 0x01},
1058 {0x3227, 0x03},
1059 {0x3229, 0x08},
1060 {0x3231, 0x01},
1061 {0x3241, 0x02},
1062 {0x3243, 0x03},
1063 {0x3249, 0x17},
1064 {0x3250, 0x3f},
1065 {0x3251, 0x08},
1066 {0x3000, 0x00},
1067 {0x3253, 0x10},
1068 {0x325e, 0x00},
1069 {0x325f, 0x00},
1070 {0x3273, 0x01},
1071 {0x3301, 0x15},
1072 {0x3302, 0x18},
1073 {0x3304, 0x20},
1074 {0x3305, 0x00},
1075 {0x3306, 0x78},
1076 {0x3308, 0x10},
1077 {0x3309, 0x50},
1078 {0x330a, 0x00},
1079 {0x330b, 0xe8},
1080 {0x330e, 0x20},
1081 {0x3312, 0x02},
1082 {0x3314, 0x84},
1083 {0x331e, 0x19},
1084 {0x331f, 0x49},
1085 {0x3320, 0x05},
1086 {0x3338, 0x10},
1087 {0x334c, 0x10},
1088 {0x335d, 0x20},
1089 {0x335e, 0x02},
1090 {0x335f, 0x04},
1091 {0x3360, 0x20},
1092 {0x3362, 0x72},
1093 {0x3364, 0x1e},
1094 {0x3366, 0x92},
1095 {0x3367, 0x08},
1096 {0x3368, 0x0a},
1097 {0x3369, 0xd4},
1098 {0x336a, 0x15},
1099 {0x336b, 0xa8},
1100 {0x336c, 0xc2},
1101 {0x337a, 0x08},
1102 {0x337b, 0x10},
1103 {0x337c, 0x06},
1104 {0x337d, 0x0a},
1105 {0x337e, 0x40},
1106 {0x3390, 0x08},
1107 {0x3391, 0x18},
1108 {0x3392, 0x38},
1109 {0x3393, 0x13},
1110 {0x3394, 0x24},
1111 {0x3395, 0x24},
1112 {0x3396, 0x08},
1113 {0x3397, 0x18},
1114 {0x3398, 0x38},
1115 {0x3399, 0x11},
1116 {0x339a, 0x14},
1117 {0x339b, 0x24},
1118 {0x339c, 0x24},
1119 {0x33a2, 0x08},
1120 {0x33a3, 0x0c},
1121 {0x33e0, 0xa0},
1122 {0x33e1, 0x08},
1123 {0x33e2, 0x00},
1124 {0x33e3, 0x10},
1125 {0x33e4, 0x10},
1126 {0x33e5, 0x00},
1127 {0x33e6, 0x10},
1128 {0x33e7, 0x10},
1129 {0x33e8, 0x00},
1130 {0x33e9, 0x10},
1131 {0x33ea, 0x16},
1132 {0x33eb, 0x00},
1133 {0x33ec, 0x10},
1134 {0x33ed, 0x18},
1135 {0x33ee, 0xa0},
1136 {0x33ef, 0x08},
1137 {0x33f4, 0x00},
1138 {0x33f5, 0x10},
1139 {0x33f6, 0x10},
1140 {0x33f7, 0x00},
1141 {0x33f8, 0x10},
1142 {0x33f9, 0x10},
1143 {0x33fa, 0x00},
1144 {0x33fb, 0x10},
1145 {0x33fc, 0x16},
1146 {0x33fd, 0x00},
1147 {0x33fe, 0x10},
1148 {0x33ff, 0x18},
1149 {0x360f, 0x05},
1150 {0x3622, 0xff},
1151 {0x3624, 0x07},
1152 {0x3625, 0x0a},
1153 {0x3630, 0xc4},
1154 {0x3631, 0x80},
1155 {0x3632, 0x88},
1156 {0x3633, 0x42},
1157 {0x3634, 0x64},
1158 {0x3635, 0x20},
1159 {0x3636, 0x20},
1160 {0x3638, 0x28},
1161 {0x363b, 0x03},
1162 {0x363c, 0x06},
1163 {0x363d, 0x06},
1164 {0x366e, 0x04},
1165 {0x3670, 0x4a},
1166 {0x3671, 0xff},
1167 {0x3672, 0x9f},
1168 {0x3673, 0x9f},
1169 {0x3674, 0xc4},
1170 {0x3675, 0xc4},
1171 {0x3676, 0xb8},
1172 {0x367a, 0x40},
1173 {0x367b, 0x48},
1174 {0x367c, 0x40},
1175 {0x367d, 0x48},
1176 {0x3690, 0x43},
1177 {0x3691, 0x55},
1178 {0x3692, 0x66},
1179 {0x3699, 0x8c},
1180 {0x369a, 0x96},
1181 {0x369b, 0x9f},
1182 {0x369c, 0x40},
1183 {0x369d, 0x48},
1184 {0x36a2, 0x40},
1185 {0x36a3, 0x48},
1186 {0x36cc, 0x2c},
1187 {0x36cd, 0x30},
1188 {0x36ce, 0x30},
1189 {0x36d0, 0x20},
1190 {0x36d1, 0x40},
1191 {0x36d2, 0x40},
1192 {0x36ea, 0x34},
1193 {0x36eb, 0x06},
1194 {0x36ec, 0x03},
1195 {0x36ed, 0x2c},
1196 {0x36fa, 0x37},
1197 {0x36fb, 0x04},
1198 {0x36fc, 0x00},
1199 {0x36fd, 0x2c},
1200 {0x3817, 0x20},
1201 {0x3905, 0x98},
1202 {0x3908, 0x11},
1203 {0x391b, 0x80},
1204 {0x391c, 0x0f},
1205 {0x391d, 0x21},
1206 {0x3933, 0x1f},
1207 {0x3934, 0xff},
1208 {0x3935, 0x80},
1209 {0x3936, 0x1f},
1210 {0x393e, 0x01},
1211 {0x3940, 0x60},
1212 {0x3942, 0x04},
1213 {0x3943, 0xd0},
1214 {0x3980, 0x00},
1215 {0x3981, 0x30},
1216 {0x3982, 0x00},
1217 {0x3983, 0x2c},
1218 {0x3984, 0x00},
1219 {0x3985, 0x15},
1220 {0x3986, 0x00},
1221 {0x3987, 0x10},
1222 {0x3988, 0x00},
1223 {0x3989, 0x30},
1224 {0x398a, 0x00},
1225 {0x398b, 0x28},
1226 {0x398c, 0x00},
1227 {0x398d, 0x30},
1228 {0x398e, 0x00},
1229 {0x398f, 0x70},
1230 {0x3990, 0x0a},
1231 {0x3991, 0x00},
1232 {0x3992, 0x00},
1233 {0x3993, 0x60},
1234 {0x3994, 0x00},
1235 {0x3995, 0x30},
1236 {0x3996, 0x00},
1237 {0x3997, 0x10},
1238 {0x3998, 0x00},
1239 {0x3999, 0x1c},
1240 {0x399a, 0x00},
1241 {0x399b, 0x48},
1242 {0x399c, 0x00},
1243 {0x399d, 0x90},
1244 {0x399e, 0x00},
1245 {0x399f, 0xc0},
1246 {0x39a0, 0x14},
1247 {0x39a1, 0x28},
1248 {0x39a2, 0x48},
1249 {0x39a3, 0x70},
1250 {0x39a4, 0x18},
1251 {0x39a5, 0x04},
1252 {0x39a6, 0x08},
1253 {0x39a7, 0x04},
1254 {0x39a8, 0x01},
1255 {0x39a9, 0x14},
1256 {0x39aa, 0x28},
1257 {0x39ab, 0x50},
1258 {0x39ac, 0x30},
1259 {0x39ad, 0x20},
1260 {0x39ae, 0x10},
1261 {0x39af, 0x08},
1262 {0x39b9, 0x00},
1263 {0x39ba, 0x00},
1264 {0x39bb, 0x00},
1265 {0x39bc, 0x00},
1266 {0x39bd, 0x58},
1267 {0x39be, 0xc0},
1268 {0x39bf, 0x00},
1269 {0x39c0, 0x00},
1270 {0x39c5, 0x41},
1271 {0x3c09, 0x4a},
1272 {0x3c10, 0x07},
1273 {0x3c11, 0x20},
1274 {0x3c12, 0x07},
1275 {0x3c13, 0x20},
1276 {0x3c14, 0x0f},
1277 {0x3e00, 0x01},
1278 {0x3e01, 0x5a},
1279 {0x3e02, 0x00},
1280 {0x3e03, 0x0b},
1281 {0x3e04, 0x15},
1282 {0x3e05, 0xa0},
1283 {0x3e06, 0x00},
1284 {0x3e07, 0x80},
1285 {0x3e08, 0x03},
1286 {0x3e09, 0x40},
1287 {0x3e0e, 0x6a},
1288 {0x3e10, 0x00},
1289 {0x3e11, 0x80},
1290 {0x3e12, 0x03},
1291 {0x3e13, 0x40},
1292 {0x3e23, 0x00},
1293 {0x3e24, 0xbc},
1294 {0x3e26, 0x40},
1295 {0x4401, 0x0b},
1296 {0x4407, 0xb0},
1297 {0x4418, 0x16},
1298 {0x4501, 0xa4},
1299 {0x4509, 0x08},
1300 {0x4603, 0x00},
1301 {0x4800, 0x24},
1302 {0x4816, 0x11},
1303 {0x4819, 0x40},
1304 {0x4829, 0x01},
1305 {0x4837, 0x0f},
1306 {0x5000, 0x0e},
1307 {0x550f, 0x20},
1308 {0x5784, 0x10},
1309 {0x5785, 0x08},
1310 {0x5787, 0x06},
1311 {0x5788, 0x06},
1312 {0x5789, 0x00},
1313 {0x578a, 0x06},
1314 {0x578b, 0x06},
1315 {0x578c, 0x00},
1316 {0x5790, 0x10},
1317 {0x5791, 0x10},
1318 {0x5792, 0x00},
1319 {0x5793, 0x10},
1320 {0x5794, 0x10},
1321 {0x5795, 0x00},
1322 {0x57c4, 0x10},
1323 {0x57c5, 0x08},
1324 {0x57c7, 0x06},
1325 {0x57c8, 0x06},
1326 {0x57c9, 0x00},
1327 {0x57ca, 0x06},
1328 {0x57cb, 0x06},
1329 {0x57cc, 0x00},
1330 {0x57d0, 0x10},
1331 {0x57d1, 0x10},
1332 {0x57d2, 0x00},
1333 {0x57d3, 0x10},
1334 {0x57d4, 0x10},
1335 {0x57d5, 0x00},
1336 {0x36e9, 0x44},
1337 {0x36f9, 0x20},
1338 //{0x0100, 0x01},
1339 {REG_NULL, 0x00},
1340 };
1341
1342 static const struct sc4210_mode supported_modes_2lane[] = {
1343 {
1344 .width = 2560,
1345 .height = 1440,
1346 .max_fps = {
1347 .numerator = 10000,
1348 .denominator = 300000,
1349 },
1350 .exp_def = 0x0100,
1351 .hts_def = 0x0546,
1352 .vts_def = 0x05dc,
1353 .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
1354 .reg_list = sc4210_liner_10_30fps_2560x1440_2lane_regs,
1355 .mipi_freq_idx = 0,
1356 .bpp = 10,
1357 .hdr_mode = NO_HDR,
1358 .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
1359 },
1360 {
1361 .width = 2560,
1362 .height = 1440,
1363 .max_fps = {
1364 .numerator = 10000,
1365 .denominator = 250000,
1366 },
1367 .exp_def = 0x015a,
1368 .hts_def = 0x0668,
1369 .vts_def = 0x0b90,
1370 .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
1371 .reg_list = sc4210_hdr_10_25fps_2560x1440_2lane_regs,
1372 .mipi_freq_idx = 1,
1373 .bpp = 10,
1374 .hdr_mode = HDR_X2,
1375 .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1,
1376 .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
1377 .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
1378 .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
1379 },
1380 };
1381
1382 static const struct sc4210_mode supported_modes_4lane[] = {
1383 {
1384 .width = 2560,
1385 .height = 1440,
1386 .max_fps = {
1387 .numerator = 10000,
1388 .denominator = 300000,
1389 },
1390 .exp_def = 0x0100,
1391 .hts_def = 0x0546,
1392 .vts_def = 0x05dc,
1393 .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
1394 .reg_list = sc4210_linear_10_30fps_2560x1440_4lane_regs,
1395 .mipi_freq_idx = 2,
1396 .bpp = 10,
1397 .hdr_mode = NO_HDR,
1398 .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
1399 },
1400 {
1401 .width = 2560,
1402 .height = 1440,
1403 .max_fps = {
1404 .numerator = 10000,
1405 .denominator = 300000,
1406 },
1407 .exp_def = 0x05a1,
1408 .hts_def = 0x0558,
1409 .vts_def = 0x0b90,
1410 .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
1411 .reg_list = sc4210_hdr_10_30fps_2560x1440_4lane_regs,
1412 .mipi_freq_idx = 3,
1413 .bpp = 10,
1414 .hdr_mode = HDR_X2,
1415 .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1,
1416 .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
1417 .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
1418 .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
1419 },
1420 };
1421
1422 static const s64 link_freq_items[] = {
1423 SC4210_LINK_FREQ_2LANE_LINEAR,
1424 SC4210_LINK_FREQ_2LANE_HDR2,
1425 SC4210_LINK_FREQ_4LANE_LINEAR,
1426 SC4210_LINK_FREQ_4LANE_HDR2,
1427 };
1428
1429 /* Write registers up to 4 at a time */
sc4210_write_reg(struct i2c_client * client,u16 reg,u32 len,u32 val)1430 static int sc4210_write_reg(struct i2c_client *client, u16 reg,
1431 u32 len, u32 val)
1432 {
1433 u32 buf_i, val_i;
1434 u8 buf[6];
1435 u8 *val_p;
1436 __be32 val_be;
1437
1438 if (len > 4)
1439 return -EINVAL;
1440
1441 buf[0] = reg >> 8;
1442 buf[1] = reg & 0xff;
1443
1444 val_be = cpu_to_be32(val);
1445 val_p = (u8 *)&val_be;
1446 buf_i = 2;
1447 val_i = 4 - len;
1448
1449 while (val_i < 4)
1450 buf[buf_i++] = val_p[val_i++];
1451
1452 if (i2c_master_send(client, buf, len + 2) != len + 2)
1453 return -EIO;
1454
1455 return 0;
1456 }
1457
sc4210_write_array(struct i2c_client * client,const struct regval * regs)1458 static int sc4210_write_array(struct i2c_client *client,
1459 const struct regval *regs)
1460 {
1461 u32 i;
1462 int ret = 0;
1463
1464 for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++)
1465 ret = sc4210_write_reg(client, regs[i].addr,
1466 SC4210_REG_VALUE_08BIT, regs[i].val);
1467
1468 return ret;
1469 }
1470
1471 /* Read registers up to 4 at a time */
sc4210_read_reg(struct i2c_client * client,u16 reg,unsigned int len,u32 * val)1472 static int sc4210_read_reg(struct i2c_client *client,
1473 u16 reg, unsigned int len, u32 *val)
1474 {
1475 struct i2c_msg msgs[2];
1476 u8 *data_be_p;
1477 __be32 data_be = 0;
1478 __be16 reg_addr_be = cpu_to_be16(reg);
1479 int ret;
1480
1481 if (len > 4 || !len)
1482 return -EINVAL;
1483
1484 data_be_p = (u8 *)&data_be;
1485 /* Write register address */
1486 msgs[0].addr = client->addr;
1487 msgs[0].flags = 0;
1488 msgs[0].len = 2;
1489 msgs[0].buf = (u8 *)®_addr_be;
1490
1491 /* Read data from register */
1492 msgs[1].addr = client->addr;
1493 msgs[1].flags = I2C_M_RD;
1494 msgs[1].len = len;
1495 msgs[1].buf = &data_be_p[4 - len];
1496
1497 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
1498 if (ret != ARRAY_SIZE(msgs))
1499 return -EIO;
1500
1501 *val = be32_to_cpu(data_be);
1502
1503 return 0;
1504 }
1505
sc4210_get_reso_dist(const struct sc4210_mode * mode,struct v4l2_mbus_framefmt * framefmt)1506 static int sc4210_get_reso_dist(const struct sc4210_mode *mode,
1507 struct v4l2_mbus_framefmt *framefmt)
1508 {
1509 return abs(mode->width - framefmt->width) +
1510 abs(mode->height - framefmt->height);
1511 }
1512
1513 static const struct sc4210_mode *
sc4210_find_best_fit(struct sc4210 * sc4210,struct v4l2_subdev_format * fmt)1514 sc4210_find_best_fit(struct sc4210 *sc4210, struct v4l2_subdev_format *fmt)
1515 {
1516 struct v4l2_mbus_framefmt *framefmt = &fmt->format;
1517 int dist;
1518 int cur_best_fit = 0;
1519 int cur_best_fit_dist = -1;
1520 unsigned int i;
1521
1522 for (i = 0; i < sc4210->support_modes_num; i++) {
1523 dist = sc4210_get_reso_dist(&sc4210->support_modes[i], framefmt);
1524 if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
1525 cur_best_fit_dist = dist;
1526 cur_best_fit = i;
1527 }
1528 }
1529
1530 return &sc4210->support_modes[cur_best_fit];
1531 }
1532
sc4210_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)1533 static int sc4210_set_fmt(struct v4l2_subdev *sd,
1534 struct v4l2_subdev_pad_config *cfg,
1535 struct v4l2_subdev_format *fmt)
1536 {
1537 struct sc4210 *sc4210 = to_sc4210(sd);
1538 const struct sc4210_mode *mode;
1539 s64 h_blank, vblank_def;
1540 u64 pixel_rate = 0;
1541
1542 mutex_lock(&sc4210->mutex);
1543
1544 mode = sc4210_find_best_fit(sc4210, fmt);
1545 fmt->format.code = mode->bus_fmt;
1546 fmt->format.width = mode->width;
1547 fmt->format.height = mode->height;
1548 fmt->format.field = V4L2_FIELD_NONE;
1549 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1550 #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
1551 *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
1552 #else
1553 mutex_unlock(&sc4210->mutex);
1554 return -ENOTTY;
1555 #endif
1556 } else {
1557 sc4210->cur_mode = mode;
1558
1559 h_blank = mode->hts_def - mode->width;
1560 __v4l2_ctrl_modify_range(sc4210->hblank, h_blank,
1561 h_blank, 1, h_blank);
1562 vblank_def = mode->vts_def - mode->height;
1563 __v4l2_ctrl_modify_range(sc4210->vblank, vblank_def,
1564 SC4210_VTS_MAX - mode->height,
1565 1, vblank_def);
1566
1567 __v4l2_ctrl_s_ctrl(sc4210->link_freq, mode->mipi_freq_idx);
1568 pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] /
1569 mode->bpp * 2 * sc4210->lane_num;
1570 __v4l2_ctrl_s_ctrl_int64(sc4210->pixel_rate, pixel_rate);
1571 sc4210->cur_fps = mode->max_fps;
1572 }
1573
1574 mutex_unlock(&sc4210->mutex);
1575
1576 return 0;
1577 }
1578
sc4210_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)1579 static int sc4210_get_fmt(struct v4l2_subdev *sd,
1580 struct v4l2_subdev_pad_config *cfg,
1581 struct v4l2_subdev_format *fmt)
1582 {
1583 struct sc4210 *sc4210 = to_sc4210(sd);
1584 const struct sc4210_mode *mode = sc4210->cur_mode;
1585
1586 mutex_lock(&sc4210->mutex);
1587 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1588 #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
1589 fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
1590 #else
1591 mutex_unlock(&sc4210->mutex);
1592 return -ENOTTY;
1593 #endif
1594 } else {
1595 fmt->format.width = mode->width;
1596 fmt->format.height = mode->height;
1597 fmt->format.code = mode->bus_fmt;
1598 fmt->format.field = V4L2_FIELD_NONE;
1599 /* format info: width/height/data type/virctual channel */
1600 if (fmt->pad < PAD_MAX && mode->hdr_mode != NO_HDR)
1601 fmt->reserved[0] = mode->vc[fmt->pad];
1602 else
1603 fmt->reserved[0] = mode->vc[PAD0];
1604 }
1605 mutex_unlock(&sc4210->mutex);
1606
1607 return 0;
1608 }
1609
sc4210_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_mbus_code_enum * code)1610 static int sc4210_enum_mbus_code(struct v4l2_subdev *sd,
1611 struct v4l2_subdev_pad_config *cfg,
1612 struct v4l2_subdev_mbus_code_enum *code)
1613 {
1614 struct sc4210 *sc4210 = to_sc4210(sd);
1615
1616 if (code->index != 0)
1617 return -EINVAL;
1618 code->code = sc4210->cur_mode->bus_fmt;
1619
1620 return 0;
1621 }
1622
sc4210_enum_frame_sizes(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_frame_size_enum * fse)1623 static int sc4210_enum_frame_sizes(struct v4l2_subdev *sd,
1624 struct v4l2_subdev_pad_config *cfg,
1625 struct v4l2_subdev_frame_size_enum *fse)
1626 {
1627 struct sc4210 *sc4210 = to_sc4210(sd);
1628
1629 if (fse->index >= sc4210->support_modes_num)
1630 return -EINVAL;
1631
1632 if (fse->code != sc4210->support_modes[fse->index].bus_fmt)
1633 return -EINVAL;
1634
1635 fse->min_width = sc4210->support_modes[fse->index].width;
1636 fse->max_width = sc4210->support_modes[fse->index].width;
1637 fse->max_height = sc4210->support_modes[fse->index].height;
1638 fse->min_height = sc4210->support_modes[fse->index].height;
1639
1640 return 0;
1641 }
1642
sc4210_g_frame_interval(struct v4l2_subdev * sd,struct v4l2_subdev_frame_interval * fi)1643 static int sc4210_g_frame_interval(struct v4l2_subdev *sd,
1644 struct v4l2_subdev_frame_interval *fi)
1645 {
1646 struct sc4210 *sc4210 = to_sc4210(sd);
1647 const struct sc4210_mode *mode = sc4210->cur_mode;
1648
1649 if (sc4210->streaming)
1650 fi->interval = sc4210->cur_fps;
1651 else
1652 fi->interval = mode->max_fps;
1653
1654 return 0;
1655 }
1656
sc4210_g_mbus_config(struct v4l2_subdev * sd,unsigned int pad_id,struct v4l2_mbus_config * config)1657 static int sc4210_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
1658 struct v4l2_mbus_config *config)
1659 {
1660 struct sc4210 *sc4210 = to_sc4210(sd);
1661 const struct sc4210_mode *mode = sc4210->cur_mode;
1662 u32 val = 1 << (sc4210->lane_num - 1) |
1663 V4L2_MBUS_CSI2_CHANNEL_0 |
1664 V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
1665
1666 if (mode->hdr_mode != NO_HDR)
1667 val |= V4L2_MBUS_CSI2_CHANNEL_1;
1668 if (mode->hdr_mode == HDR_X3)
1669 val |= V4L2_MBUS_CSI2_CHANNEL_2;
1670
1671 config->type = V4L2_MBUS_CSI2_DPHY;
1672 config->flags = val;
1673
1674 return 0;
1675 }
1676
sc4210_get_module_inf(struct sc4210 * sc4210,struct rkmodule_inf * inf)1677 static void sc4210_get_module_inf(struct sc4210 *sc4210,
1678 struct rkmodule_inf *inf)
1679 {
1680 memset(inf, 0, sizeof(*inf));
1681 strscpy(inf->base.sensor, SC4210_NAME, sizeof(inf->base.sensor));
1682 strscpy(inf->base.module, sc4210->module_name,
1683 sizeof(inf->base.module));
1684 strscpy(inf->base.lens, sc4210->len_name, sizeof(inf->base.lens));
1685 }
1686
sc4210_get_gain_reg(u32 total_gain,u32 * again,u32 * again_fine,u32 * dgain,u32 * dgain_fine)1687 static void sc4210_get_gain_reg(u32 total_gain, u32 *again, u32 *again_fine,
1688 u32 *dgain, u32 *dgain_fine)
1689 {
1690 u32 dgain_total = 0;
1691
1692 if (total_gain < SC4210_GAIN_MIN)
1693 total_gain = SC4210_GAIN_MIN;
1694 else if (total_gain > SC4210_GAIN_MAX)
1695 total_gain = SC4210_GAIN_MAX;
1696
1697 dgain_total = total_gain * 1000 / 43656;
1698
1699 if (total_gain < 2000) { /* 1 - 2x gain */
1700 *again = 0x03;
1701 *again_fine = total_gain*64/1000;
1702 *dgain = 0x00;
1703 *dgain_fine = 0x80;
1704 } else if (total_gain < 2750) { /* 2x - 2.75x gain */
1705 *again = 0x07;
1706 *again_fine = total_gain*64/2000;
1707 *dgain = 0x00;
1708 *dgain_fine = 0x80;
1709 } else if (total_gain < 2750 * 2) { /* 2.75xx - 5.5x gain */
1710 *again = 0x23;
1711 *again_fine = total_gain*64/2750;
1712 *dgain = 0x00;
1713 *dgain_fine = 0x80;
1714 } else if (total_gain < 2750 * 4) { /* 5.5x - 11.0x gain */
1715 *again = 0x27;
1716 *again_fine = total_gain*64/5500;
1717 *dgain = 0x00;
1718 *dgain_fine = 0x80;
1719 } else if (total_gain < 2750 * 8) { /* 11.0x - 22.0x gain */
1720 *again = 0x2f;
1721 *again_fine = total_gain*64/11000;
1722 *dgain = 0x00;
1723 *dgain_fine = 0x80;
1724 } else if (total_gain < 2750 * 16) { /* 22.0x - 43.656x gain */
1725 *again = 0x3f;
1726 *again_fine = total_gain*64/22000;
1727 *dgain = 0x00;
1728 *dgain_fine = 0x80;
1729 } else if (total_gain < 43656 * 2) { /* 43.656x - 87.312x gain */
1730 *again = 0x3f;
1731 *again_fine = 0x7f;
1732 *dgain = 0x00;
1733 *dgain_fine = dgain_total*128/1000;
1734 } else if (total_gain < 43656 * 4) { /* 87.312x - 174.624x gain */
1735 *again = 0x3f;
1736 *again_fine = 0x7f;
1737 *dgain = 0x01;
1738 *dgain_fine = dgain_total*128/2000;
1739 } else if (total_gain < 43656 * 8) { /* 174.624x - 349.248x gain */
1740 *again = 0x3f;
1741 *again_fine = 0x7f;
1742 *dgain = 0x03;
1743 *dgain_fine = dgain_total*128/4000;
1744 } else if (total_gain < 43656 * 16) { /* 349.248x - 698.496x gain */
1745 *again = 0x3f;
1746 *again_fine = 0x7f;
1747 *dgain = 0x07;
1748 *dgain_fine = dgain_total*128/8000;
1749 } else if (total_gain < 43656 * 32) { /* 698.496x - 1375.164x gain */
1750 *again = 0x3f;
1751 *again_fine = 0x7f;
1752 *dgain = 0x0f;
1753 *dgain_fine = dgain_total*128/16000;
1754 }
1755 }
1756
sc4210_set_hdrae(struct sc4210 * sc4210,struct preisp_hdrae_exp_s * ae)1757 static int sc4210_set_hdrae(struct sc4210 *sc4210,
1758 struct preisp_hdrae_exp_s *ae)
1759 {
1760 int ret = 0;
1761 u32 l_exp_time, m_exp_time, s_exp_time;
1762 u32 l_t_gain, m_t_gain, s_t_gain;
1763 u32 l_again = 0, l_again_fine = 0, l_dgain = 0, l_dgain_fine = 0;
1764 u32 s_again = 0, s_again_fine = 0, s_dgain = 0, s_dgain_fine = 0;
1765
1766 if (!sc4210->has_init_exp && !sc4210->streaming) {
1767 sc4210->init_hdrae_exp = *ae;
1768 sc4210->has_init_exp = true;
1769 dev_dbg(&sc4210->client->dev,
1770 "sc4210 don't stream, record exp for hdr!\n");
1771 return ret;
1772 }
1773
1774 l_exp_time = ae->long_exp_reg;
1775 m_exp_time = ae->middle_exp_reg;
1776 s_exp_time = ae->short_exp_reg;
1777 l_t_gain = ae->long_gain_reg;
1778 m_t_gain = ae->middle_gain_reg;
1779 s_t_gain = ae->short_gain_reg;
1780
1781 if (sc4210->cur_mode->hdr_mode == HDR_X2) {
1782 //2 stagger
1783 l_t_gain = m_t_gain;
1784 l_exp_time = m_exp_time;
1785 }
1786
1787 l_exp_time = l_exp_time << 1;
1788 s_exp_time = s_exp_time << 1;
1789
1790 // set exposure reg
1791 ret |= sc4210_write_reg(sc4210->client,
1792 SC4210_REG_EXPOSURE_H,
1793 SC4210_REG_VALUE_08BIT,
1794 SC4210_FETCH_EXP_H(l_exp_time));
1795 ret |= sc4210_write_reg(sc4210->client,
1796 SC4210_REG_EXPOSURE_M,
1797 SC4210_REG_VALUE_08BIT,
1798 SC4210_FETCH_EXP_M(l_exp_time));
1799 ret |= sc4210_write_reg(sc4210->client,
1800 SC4210_REG_EXPOSURE_L,
1801 SC4210_REG_VALUE_08BIT,
1802 SC4210_FETCH_EXP_L(l_exp_time));
1803 //ret |= sc4210_write_reg(sc4210->client,
1804 // SC4210_REG_SHORT_EXPOSURE_H,
1805 // SC4210_REG_VALUE_08BIT,
1806 // SC4210_FETCH_EXP_H(s_exp_time));
1807 ret |= sc4210_write_reg(sc4210->client,
1808 SC4210_REG_SHORT_EXPOSURE_M,
1809 SC4210_REG_VALUE_08BIT,
1810 SC4210_FETCH_EXP_M(s_exp_time));
1811 ret |= sc4210_write_reg(sc4210->client,
1812 SC4210_REG_SHORT_EXPOSURE_L,
1813 SC4210_REG_VALUE_08BIT,
1814 SC4210_FETCH_EXP_L(s_exp_time));
1815
1816 // set gain reg
1817 sc4210_get_gain_reg(l_t_gain, &l_again, &l_again_fine, &l_dgain, &l_dgain_fine);
1818 sc4210_get_gain_reg(s_t_gain, &s_again, &s_again_fine, &s_dgain, &s_dgain_fine);
1819
1820 ret |= sc4210_write_reg(sc4210->client,
1821 SC4210_REG_DIG_GAIN,
1822 SC4210_REG_VALUE_08BIT,
1823 l_dgain);
1824 ret |= sc4210_write_reg(sc4210->client,
1825 SC4210_REG_DIG_FINE_GAIN,
1826 SC4210_REG_VALUE_08BIT,
1827 l_dgain_fine);
1828 ret |= sc4210_write_reg(sc4210->client,
1829 SC4210_REG_ANA_GAIN,
1830 SC4210_REG_VALUE_08BIT,
1831 l_again);
1832 ret |= sc4210_write_reg(sc4210->client,
1833 SC4210_REG_ANA_FINE_GAIN,
1834 SC4210_REG_VALUE_08BIT,
1835 l_again_fine);
1836
1837 ret |= sc4210_write_reg(sc4210->client,
1838 SC4210_REG_SDIG_GAIN,
1839 SC4210_REG_VALUE_08BIT,
1840 s_dgain);
1841 ret |= sc4210_write_reg(sc4210->client,
1842 SC4210_REG_SDIG_FINE_GAIN,
1843 SC4210_REG_VALUE_08BIT,
1844 s_dgain_fine);
1845 ret |= sc4210_write_reg(sc4210->client,
1846 SC4210_REG_SANA_GAIN,
1847 SC4210_REG_VALUE_08BIT,
1848 s_again);
1849 ret |= sc4210_write_reg(sc4210->client,
1850 SC4210_REG_SANA_FINE_GAIN,
1851 SC4210_REG_VALUE_08BIT,
1852 s_again_fine);
1853 return ret;
1854 }
1855
sc4210_get_channel_info(struct sc4210 * sc4210,struct rkmodule_channel_info * ch_info)1856 static int sc4210_get_channel_info(struct sc4210 *sc4210, struct rkmodule_channel_info *ch_info)
1857 {
1858 if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX)
1859 return -EINVAL;
1860 ch_info->vc = sc4210->cur_mode->vc[ch_info->index];
1861 ch_info->width = sc4210->cur_mode->width;
1862 ch_info->height = sc4210->cur_mode->height;
1863 ch_info->bus_fmt = sc4210->cur_mode->bus_fmt;
1864 return 0;
1865 }
1866
sc4210_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)1867 static long sc4210_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1868 {
1869 struct sc4210 *sc4210 = to_sc4210(sd);
1870 struct rkmodule_hdr_cfg *hdr;
1871 const struct sc4210_mode *mode;
1872 struct rkmodule_channel_info *ch_info;
1873 long ret = 0;
1874 u32 i, h = 0, w;
1875 u32 stream = 0;
1876 int pixel_rate = 0;
1877
1878 switch (cmd) {
1879 case RKMODULE_GET_MODULE_INFO:
1880 sc4210_get_module_inf(sc4210, (struct rkmodule_inf *)arg);
1881 break;
1882 case RKMODULE_GET_HDR_CFG:
1883 hdr = (struct rkmodule_hdr_cfg *)arg;
1884 hdr->esp.mode = HDR_NORMAL_VC;
1885 hdr->hdr_mode = sc4210->cur_mode->hdr_mode;
1886 break;
1887 case RKMODULE_SET_HDR_CFG:
1888 hdr = (struct rkmodule_hdr_cfg *)arg;
1889 w = sc4210->cur_mode->width;
1890 h = sc4210->cur_mode->height;
1891 for (i = 0; i < sc4210->support_modes_num; i++) {
1892 if (w == sc4210->support_modes[i].width &&
1893 h == sc4210->support_modes[i].height &&
1894 sc4210->support_modes[i].hdr_mode == hdr->hdr_mode) {
1895 sc4210->cur_mode = &sc4210->support_modes[i];
1896 break;
1897 }
1898 }
1899 if (i == sc4210->support_modes_num) {
1900 dev_err(&sc4210->client->dev,
1901 "not find hdr mode:%d %dx%d config\n",
1902 hdr->hdr_mode, w, h);
1903 ret = -EINVAL;
1904 } else {
1905 mode = sc4210->cur_mode;
1906 w = sc4210->cur_mode->hts_def -
1907 sc4210->cur_mode->width;
1908 h = sc4210->cur_mode->vts_def -
1909 sc4210->cur_mode->height;
1910 __v4l2_ctrl_modify_range(sc4210->hblank, w, w, 1, w);
1911 __v4l2_ctrl_modify_range(sc4210->vblank, h,
1912 SC4210_VTS_MAX -
1913 sc4210->cur_mode->height,
1914 1, h);
1915
1916 __v4l2_ctrl_s_ctrl(sc4210->link_freq,
1917 mode->mipi_freq_idx);
1918
1919 pixel_rate = (int)link_freq_items[mode->mipi_freq_idx]
1920 / mode->bpp * 2 * sc4210->lane_num;
1921
1922 __v4l2_ctrl_s_ctrl_int64(sc4210->pixel_rate,
1923 pixel_rate);
1924
1925 dev_info(&sc4210->client->dev, "sensor mode: %d\n",
1926 sc4210->cur_mode->hdr_mode);
1927 }
1928 break;
1929 case PREISP_CMD_SET_HDRAE_EXP:
1930 if (sc4210->cur_mode->hdr_mode == HDR_X2)
1931 ret = sc4210_set_hdrae(sc4210, arg);
1932 break;
1933 case RKMODULE_SET_QUICK_STREAM:
1934 stream = *((u32 *)arg);
1935 if (stream)
1936 ret = sc4210_write_reg(sc4210->client,
1937 SC4210_REG_CTRL_MODE,
1938 SC4210_REG_VALUE_08BIT,
1939 SC4210_MODE_STREAMING);
1940 else
1941 ret = sc4210_write_reg(sc4210->client,
1942 SC4210_REG_CTRL_MODE,
1943 SC4210_REG_VALUE_08BIT,
1944 SC4210_MODE_SW_STANDBY);
1945 break;
1946 case RKMODULE_GET_CHANNEL_INFO:
1947 ch_info = (struct rkmodule_channel_info *)arg;
1948 ret = sc4210_get_channel_info(sc4210, ch_info);
1949 break;
1950 default:
1951 ret = -ENOIOCTLCMD;
1952 break;
1953 }
1954
1955 return ret;
1956 }
1957
1958 #ifdef CONFIG_COMPAT
sc4210_compat_ioctl32(struct v4l2_subdev * sd,unsigned int cmd,unsigned long arg)1959 static long sc4210_compat_ioctl32(struct v4l2_subdev *sd,
1960 unsigned int cmd, unsigned long arg)
1961 {
1962 void __user *up = compat_ptr(arg);
1963 struct rkmodule_inf *inf;
1964 struct rkmodule_hdr_cfg *hdr;
1965 struct preisp_hdrae_exp_s *hdrae;
1966 struct rkmodule_channel_info *ch_info;
1967 long ret = 0;
1968 u32 stream = 0;
1969
1970 switch (cmd) {
1971 case RKMODULE_GET_MODULE_INFO:
1972 inf = kzalloc(sizeof(*inf), GFP_KERNEL);
1973 if (!inf) {
1974 ret = -ENOMEM;
1975 return ret;
1976 }
1977
1978 ret = sc4210_ioctl(sd, cmd, inf);
1979 if (!ret) {
1980 ret = copy_to_user(up, inf, sizeof(*inf));
1981 if (ret)
1982 return -EFAULT;
1983 }
1984 kfree(inf);
1985 break;
1986 case RKMODULE_GET_HDR_CFG:
1987 hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
1988 if (!hdr) {
1989 ret = -ENOMEM;
1990 return ret;
1991 }
1992
1993 ret = sc4210_ioctl(sd, cmd, hdr);
1994 if (!ret) {
1995 ret = copy_to_user(up, hdr, sizeof(*hdr));
1996 if (ret)
1997 return -EFAULT;
1998 }
1999 kfree(hdr);
2000 break;
2001 case RKMODULE_SET_HDR_CFG:
2002 hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
2003 if (!hdr) {
2004 ret = -ENOMEM;
2005 return ret;
2006 }
2007
2008 if (copy_from_user(hdr, up, sizeof(*hdr))) {
2009 kfree(hdr);
2010 return -EFAULT;
2011 }
2012
2013 ret = sc4210_ioctl(sd, cmd, hdr);
2014 kfree(hdr);
2015 break;
2016 case PREISP_CMD_SET_HDRAE_EXP:
2017 hdrae = kzalloc(sizeof(*hdrae), GFP_KERNEL);
2018 if (!hdrae) {
2019 ret = -ENOMEM;
2020 return ret;
2021 }
2022
2023 if (copy_from_user(hdrae, up, sizeof(*hdrae))) {
2024 kfree(hdrae);
2025 return -EFAULT;
2026 }
2027
2028 ret = sc4210_ioctl(sd, cmd, hdrae);
2029 kfree(hdrae);
2030 break;
2031 case RKMODULE_SET_QUICK_STREAM:
2032 if (copy_from_user(&stream, up, sizeof(u32)))
2033 return -EFAULT;
2034
2035 ret = sc4210_ioctl(sd, cmd, &stream);
2036 break;
2037 case RKMODULE_GET_CHANNEL_INFO:
2038 ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
2039 if (!ch_info) {
2040 ret = -ENOMEM;
2041 return ret;
2042 }
2043
2044 ret = sc4210_ioctl(sd, cmd, ch_info);
2045 if (!ret) {
2046 ret = copy_to_user(up, ch_info, sizeof(*ch_info));
2047 if (ret)
2048 ret = -EFAULT;
2049 }
2050 kfree(ch_info);
2051 break;
2052 default:
2053 ret = -ENOIOCTLCMD;
2054 break;
2055 }
2056
2057 return ret;
2058 }
2059 #endif
2060
__sc4210_start_stream(struct sc4210 * sc4210)2061 static int __sc4210_start_stream(struct sc4210 *sc4210)
2062 {
2063 int ret;
2064
2065 ret = sc4210_write_array(sc4210->client, sc4210->cur_mode->reg_list);
2066 if (ret)
2067 return ret;
2068
2069 /* In case these controls are set before streaming */
2070 ret = __v4l2_ctrl_handler_setup(&sc4210->ctrl_handler);
2071 if (ret)
2072 return ret;
2073 if (sc4210->has_init_exp && sc4210->cur_mode->hdr_mode != NO_HDR) {
2074 ret = sc4210_ioctl(&sc4210->subdev, PREISP_CMD_SET_HDRAE_EXP,
2075 &sc4210->init_hdrae_exp);
2076 if (ret) {
2077 dev_err(&sc4210->client->dev,
2078 "init exp fail in hdr mode\n");
2079 return ret;
2080 }
2081 }
2082 return sc4210_write_reg(sc4210->client, SC4210_REG_CTRL_MODE,
2083 SC4210_REG_VALUE_08BIT,
2084 SC4210_MODE_STREAMING);
2085 }
2086
__sc4210_stop_stream(struct sc4210 * sc4210)2087 static int __sc4210_stop_stream(struct sc4210 *sc4210)
2088 {
2089 sc4210->has_init_exp = false;
2090 return sc4210_write_reg(sc4210->client, SC4210_REG_CTRL_MODE,
2091 SC4210_REG_VALUE_08BIT,
2092 SC4210_MODE_SW_STANDBY);
2093 }
2094
sc4210_s_stream(struct v4l2_subdev * sd,int on)2095 static int sc4210_s_stream(struct v4l2_subdev *sd, int on)
2096 {
2097 struct sc4210 *sc4210 = to_sc4210(sd);
2098 struct i2c_client *client = sc4210->client;
2099 int ret = 0;
2100
2101 mutex_lock(&sc4210->mutex);
2102 on = !!on;
2103 if (on == sc4210->streaming)
2104 goto unlock_and_return;
2105 if (on) {
2106 ret = pm_runtime_get_sync(&client->dev);
2107 if (ret < 0) {
2108 pm_runtime_put_noidle(&client->dev);
2109 goto unlock_and_return;
2110 }
2111 ret = __sc4210_start_stream(sc4210);
2112 if (ret) {
2113 v4l2_err(sd, "start stream failed while write regs\n");
2114 pm_runtime_put(&client->dev);
2115 goto unlock_and_return;
2116 }
2117 } else {
2118 __sc4210_stop_stream(sc4210);
2119 pm_runtime_put(&client->dev);
2120 }
2121
2122 sc4210->streaming = on;
2123
2124 unlock_and_return:
2125 mutex_unlock(&sc4210->mutex);
2126
2127 return ret;
2128 }
2129
sc4210_s_power(struct v4l2_subdev * sd,int on)2130 static int sc4210_s_power(struct v4l2_subdev *sd, int on)
2131 {
2132 struct sc4210 *sc4210 = to_sc4210(sd);
2133 struct i2c_client *client = sc4210->client;
2134 int ret = 0;
2135
2136 mutex_lock(&sc4210->mutex);
2137
2138 /* If the power state is not modified - no work to do. */
2139 if (sc4210->power_on == !!on)
2140 goto unlock_and_return;
2141
2142 if (on) {
2143 ret = pm_runtime_get_sync(&client->dev);
2144 if (ret < 0) {
2145 pm_runtime_put_noidle(&client->dev);
2146 goto unlock_and_return;
2147 }
2148
2149 sc4210->power_on = true;
2150 } else {
2151 pm_runtime_put(&client->dev);
2152 sc4210->power_on = false;
2153 }
2154
2155 unlock_and_return:
2156 mutex_unlock(&sc4210->mutex);
2157
2158 return ret;
2159 }
2160
__sc4210_power_on(struct sc4210 * sc4210)2161 static int __sc4210_power_on(struct sc4210 *sc4210)
2162 {
2163 int ret;
2164 struct device *dev = &sc4210->client->dev;
2165
2166 if (!IS_ERR_OR_NULL(sc4210->pins_default)) {
2167 ret = pinctrl_select_state(sc4210->pinctrl,
2168 sc4210->pins_default);
2169 if (ret < 0)
2170 dev_err(dev, "could not set pins\n");
2171 }
2172 ret = clk_set_rate(sc4210->xvclk, SC4210_XVCLK_FREQ);
2173 if (ret < 0)
2174 dev_warn(dev, "Failed to set xvclk rate (27MHz)\n");
2175 if (clk_get_rate(sc4210->xvclk) != SC4210_XVCLK_FREQ)
2176 dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
2177 ret = clk_prepare_enable(sc4210->xvclk);
2178 if (ret < 0) {
2179 dev_err(dev, "Failed to enable xvclk\n");
2180 return ret;
2181 }
2182 if (!IS_ERR(sc4210->reset_gpio))
2183 gpiod_set_value_cansleep(sc4210->reset_gpio, 0);
2184
2185 ret = regulator_bulk_enable(sc4210_NUM_SUPPLIES, sc4210->supplies);
2186 if (ret < 0) {
2187 dev_err(dev, "Failed to enable regulators\n");
2188 goto disable_clk;
2189 }
2190
2191 if (!IS_ERR(sc4210->reset_gpio))
2192 gpiod_set_value_cansleep(sc4210->reset_gpio, 1);
2193
2194 usleep_range(500, 1000);
2195 if (!IS_ERR(sc4210->pwdn_gpio))
2196 gpiod_set_value_cansleep(sc4210->pwdn_gpio, 1);
2197
2198 usleep_range(4000, 5000);
2199 return 0;
2200
2201 disable_clk:
2202 clk_disable_unprepare(sc4210->xvclk);
2203
2204 return ret;
2205 }
2206
__sc4210_power_off(struct sc4210 * sc4210)2207 static void __sc4210_power_off(struct sc4210 *sc4210)
2208 {
2209 int ret;
2210 struct device *dev = &sc4210->client->dev;
2211
2212 if (!IS_ERR(sc4210->pwdn_gpio))
2213 gpiod_set_value_cansleep(sc4210->pwdn_gpio, 0);
2214 clk_disable_unprepare(sc4210->xvclk);
2215 if (!IS_ERR(sc4210->reset_gpio))
2216 gpiod_set_value_cansleep(sc4210->reset_gpio, 0);
2217 if (!IS_ERR_OR_NULL(sc4210->pins_sleep)) {
2218 ret = pinctrl_select_state(sc4210->pinctrl,
2219 sc4210->pins_sleep);
2220 if (ret < 0)
2221 dev_dbg(dev, "could not set pins\n");
2222 }
2223 regulator_bulk_disable(sc4210_NUM_SUPPLIES, sc4210->supplies);
2224 }
2225
sc4210_runtime_resume(struct device * dev)2226 static int sc4210_runtime_resume(struct device *dev)
2227 {
2228 struct i2c_client *client = to_i2c_client(dev);
2229 struct v4l2_subdev *sd = i2c_get_clientdata(client);
2230 struct sc4210 *sc4210 = to_sc4210(sd);
2231
2232 return __sc4210_power_on(sc4210);
2233 }
2234
sc4210_runtime_suspend(struct device * dev)2235 static int sc4210_runtime_suspend(struct device *dev)
2236 {
2237 struct i2c_client *client = to_i2c_client(dev);
2238 struct v4l2_subdev *sd = i2c_get_clientdata(client);
2239 struct sc4210 *sc4210 = to_sc4210(sd);
2240
2241 __sc4210_power_off(sc4210);
2242
2243 return 0;
2244 }
2245
2246 #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
sc4210_open(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)2247 static int sc4210_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
2248 {
2249 struct sc4210 *sc4210 = to_sc4210(sd);
2250 struct v4l2_mbus_framefmt *try_fmt =
2251 v4l2_subdev_get_try_format(sd, fh->pad, 0);
2252 const struct sc4210_mode *def_mode = &sc4210->support_modes[0];
2253
2254 mutex_lock(&sc4210->mutex);
2255 /* Initialize try_fmt */
2256 try_fmt->width = def_mode->width;
2257 try_fmt->height = def_mode->height;
2258 try_fmt->code = def_mode->bus_fmt;
2259 try_fmt->field = V4L2_FIELD_NONE;
2260
2261 mutex_unlock(&sc4210->mutex);
2262 /* No crop or compose */
2263
2264 return 0;
2265 }
2266 #endif
2267
sc4210_enum_frame_interval(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_frame_interval_enum * fie)2268 static int sc4210_enum_frame_interval(struct v4l2_subdev *sd,
2269 struct v4l2_subdev_pad_config *cfg,
2270 struct v4l2_subdev_frame_interval_enum *fie)
2271 {
2272 struct sc4210 *sc4210 = to_sc4210(sd);
2273
2274 if (fie->index >= sc4210->support_modes_num)
2275 return -EINVAL;
2276
2277 fie->code = sc4210->support_modes[fie->index].bus_fmt;
2278 fie->width = sc4210->support_modes[fie->index].width;
2279 fie->height = sc4210->support_modes[fie->index].height;
2280 fie->interval = sc4210->support_modes[fie->index].max_fps;
2281 fie->reserved[0] = sc4210->support_modes[fie->index].hdr_mode;
2282 return 0;
2283 }
2284
2285 static const struct dev_pm_ops sc4210_pm_ops = {
2286 SET_RUNTIME_PM_OPS(sc4210_runtime_suspend,
2287 sc4210_runtime_resume, NULL)
2288 };
2289
2290 #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
2291 static const struct v4l2_subdev_internal_ops sc4210_internal_ops = {
2292 .open = sc4210_open,
2293 };
2294 #endif
2295
2296 static const struct v4l2_subdev_core_ops sc4210_core_ops = {
2297 .s_power = sc4210_s_power,
2298 .ioctl = sc4210_ioctl,
2299 #ifdef CONFIG_COMPAT
2300 .compat_ioctl32 = sc4210_compat_ioctl32,
2301 #endif
2302 };
2303
2304 static const struct v4l2_subdev_video_ops sc4210_video_ops = {
2305 .s_stream = sc4210_s_stream,
2306 .g_frame_interval = sc4210_g_frame_interval,
2307 };
2308
2309 static const struct v4l2_subdev_pad_ops sc4210_pad_ops = {
2310 .enum_mbus_code = sc4210_enum_mbus_code,
2311 .enum_frame_size = sc4210_enum_frame_sizes,
2312 .enum_frame_interval = sc4210_enum_frame_interval,
2313 .get_fmt = sc4210_get_fmt,
2314 .set_fmt = sc4210_set_fmt,
2315 .get_mbus_config = sc4210_g_mbus_config,
2316 };
2317
2318 static const struct v4l2_subdev_ops sc4210_subdev_ops = {
2319 .core = &sc4210_core_ops,
2320 .video = &sc4210_video_ops,
2321 .pad = &sc4210_pad_ops,
2322 };
2323
sc4210_modify_fps_info(struct sc4210 * sc4210)2324 static void sc4210_modify_fps_info(struct sc4210 *sc4210)
2325 {
2326 const struct sc4210_mode *mode = sc4210->cur_mode;
2327
2328 sc4210->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def /
2329 sc4210->cur_vts;
2330 }
2331
sc4210_set_ctrl(struct v4l2_ctrl * ctrl)2332 static int sc4210_set_ctrl(struct v4l2_ctrl *ctrl)
2333 {
2334 struct sc4210 *sc4210 = container_of(ctrl->handler,
2335 struct sc4210, ctrl_handler);
2336 struct i2c_client *client = sc4210->client;
2337 s64 max;
2338 u32 again = 0, again_fine = 0, dgain = 0, dgain_fine = 0;
2339 int ret = 0;
2340 u32 val = 0, vts = 0;
2341
2342 /* Propagate change of current control to all related controls */
2343 switch (ctrl->id) {
2344 case V4L2_CID_VBLANK:
2345 /* Update max exposure while meeting expected vblanking */
2346 max = sc4210->cur_mode->height + ctrl->val - 2;
2347 __v4l2_ctrl_modify_range(sc4210->exposure,
2348 sc4210->exposure->minimum, max,
2349 sc4210->exposure->step,
2350 sc4210->exposure->default_value);
2351 break;
2352 }
2353
2354 if (!pm_runtime_get_if_in_use(&client->dev))
2355 return 0;
2356
2357 switch (ctrl->id) {
2358 case V4L2_CID_EXPOSURE:
2359 if (sc4210->cur_mode->hdr_mode != NO_HDR)
2360 goto ctrl_end;
2361 val = ctrl->val << 1;
2362 ret = sc4210_write_reg(sc4210->client,
2363 SC4210_REG_EXPOSURE_H,
2364 SC4210_REG_VALUE_08BIT,
2365 SC4210_FETCH_EXP_H(val));
2366 ret |= sc4210_write_reg(sc4210->client,
2367 SC4210_REG_EXPOSURE_M,
2368 SC4210_REG_VALUE_08BIT,
2369 SC4210_FETCH_EXP_M(val));
2370 ret |= sc4210_write_reg(sc4210->client,
2371 SC4210_REG_EXPOSURE_L,
2372 SC4210_REG_VALUE_08BIT,
2373 SC4210_FETCH_EXP_L(val));
2374
2375 dev_dbg(&client->dev, "set exposure 0x%x\n", val);
2376 break;
2377 case V4L2_CID_ANALOGUE_GAIN:
2378 if (sc4210->cur_mode->hdr_mode != NO_HDR)
2379 goto ctrl_end;
2380
2381 sc4210_get_gain_reg(ctrl->val, &again, &again_fine, &dgain, &dgain_fine);
2382 ret = sc4210_write_reg(sc4210->client,
2383 SC4210_REG_DIG_GAIN,
2384 SC4210_REG_VALUE_08BIT,
2385 dgain);
2386 ret |= sc4210_write_reg(sc4210->client,
2387 SC4210_REG_DIG_FINE_GAIN,
2388 SC4210_REG_VALUE_08BIT,
2389 dgain_fine);
2390 ret |= sc4210_write_reg(sc4210->client,
2391 SC4210_REG_ANA_GAIN,
2392 SC4210_REG_VALUE_08BIT,
2393 again);
2394 ret |= sc4210_write_reg(sc4210->client,
2395 SC4210_REG_ANA_FINE_GAIN,
2396 SC4210_REG_VALUE_08BIT,
2397 again_fine);
2398 dev_dbg(&client->dev, "set gain 0x%x\n", ctrl->val);
2399 break;
2400 case V4L2_CID_VBLANK:
2401 vts = ctrl->val + sc4210->cur_mode->height;
2402 ret = sc4210_write_reg(sc4210->client,
2403 SC4210_REG_VTS_H,
2404 SC4210_REG_VALUE_08BIT,
2405 (vts >> 8) & 0x7f);
2406 ret |= sc4210_write_reg(sc4210->client,
2407 SC4210_REG_VTS_L,
2408 SC4210_REG_VALUE_08BIT,
2409 vts & 0xff);
2410 sc4210->cur_vts = ctrl->val + sc4210->cur_mode->height;
2411 sc4210_modify_fps_info(sc4210);
2412 dev_dbg(&client->dev, "set vblank 0x%x\n", ctrl->val);
2413 break;
2414 case V4L2_CID_HFLIP:
2415 ret = sc4210_read_reg(sc4210->client, SC4210_FLIP_MIRROR_REG,
2416 SC4210_REG_VALUE_08BIT, &val);
2417 if (ret)
2418 break;
2419
2420 if (ctrl->val)
2421 val |= SC4210_MIRROR_MASK;
2422 else
2423 val &= ~SC4210_MIRROR_MASK;
2424 ret |= sc4210_write_reg(sc4210->client,
2425 SC4210_FLIP_MIRROR_REG,
2426 SC4210_REG_VALUE_08BIT, val);
2427 break;
2428 case V4L2_CID_VFLIP:
2429 ret = sc4210_read_reg(sc4210->client,
2430 SC4210_FLIP_MIRROR_REG,
2431 SC4210_REG_VALUE_08BIT, &val);
2432 if (ret)
2433 break;
2434
2435 if (ctrl->val)
2436 val |= SC4210_FLIP_MASK;
2437 else
2438 val &= ~SC4210_FLIP_MASK;
2439 ret |= sc4210_write_reg(sc4210->client,
2440 SC4210_FLIP_MIRROR_REG,
2441 SC4210_REG_VALUE_08BIT,
2442 val);
2443 break;
2444 default:
2445 dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
2446 __func__, ctrl->id, ctrl->val);
2447 break;
2448 }
2449
2450 ctrl_end:
2451 pm_runtime_put(&client->dev);
2452
2453 return ret;
2454 }
2455
2456 static const struct v4l2_ctrl_ops sc4210_ctrl_ops = {
2457 .s_ctrl = sc4210_set_ctrl,
2458 };
2459
sc4210_parse_of(struct sc4210 * sc4210)2460 static int sc4210_parse_of(struct sc4210 *sc4210)
2461 {
2462 struct device *dev = &sc4210->client->dev;
2463 struct device_node *endpoint;
2464 struct fwnode_handle *fwnode;
2465 int rval;
2466
2467 endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
2468 if (!endpoint) {
2469 dev_err(dev, "Failed to get endpoint\n");
2470 return -EINVAL;
2471 }
2472 fwnode = of_fwnode_handle(endpoint);
2473 rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0);
2474 if (rval <= 0) {
2475 dev_err(dev, " Get mipi lane num failed!\n");
2476 return -EINVAL;
2477 }
2478
2479 sc4210->lane_num = rval;
2480 dev_info(dev, "lane_num = %d\n", sc4210->lane_num);
2481
2482 if (sc4210->lane_num == 2) {
2483 sc4210->support_modes = supported_modes_2lane;
2484 sc4210->support_modes_num = ARRAY_SIZE(supported_modes_2lane);
2485 } else if (sc4210->lane_num == 4) {
2486 sc4210->support_modes = supported_modes_4lane;
2487 sc4210->support_modes_num = ARRAY_SIZE(supported_modes_4lane);
2488 }
2489
2490 sc4210->cur_mode = &sc4210->support_modes[0];
2491
2492 return 0;
2493 }
2494
sc4210_initialize_controls(struct sc4210 * sc4210)2495 static int sc4210_initialize_controls(struct sc4210 *sc4210)
2496 {
2497 const struct sc4210_mode *mode;
2498 struct v4l2_ctrl_handler *handler;
2499 s64 exposure_max, vblank_def;
2500 u64 dst_pixel_rate = 0;
2501 u32 h_blank;
2502 int ret;
2503
2504 handler = &sc4210->ctrl_handler;
2505 mode = sc4210->cur_mode;
2506 ret = v4l2_ctrl_handler_init(handler, 8);
2507 if (ret)
2508 return ret;
2509 handler->lock = &sc4210->mutex;
2510
2511 sc4210->link_freq = v4l2_ctrl_new_int_menu(handler, NULL,
2512 V4L2_CID_LINK_FREQ,
2513 ARRAY_SIZE(link_freq_items) - 1, 0,
2514 link_freq_items);
2515 __v4l2_ctrl_s_ctrl(sc4210->link_freq, mode->mipi_freq_idx);
2516
2517 if (mode->mipi_freq_idx == 0)
2518 dst_pixel_rate = SC4210_PIXEL_RATES_2LANE_LINEAR;
2519 else if (mode->mipi_freq_idx == 1)
2520 dst_pixel_rate = SC4210_PIXEL_RATES_2LANE_HDR2;
2521 else if (mode->mipi_freq_idx == 2)
2522 dst_pixel_rate = SC4210_PIXEL_RATES_4LANE_LINEAR;
2523 else if (mode->mipi_freq_idx == 2)
2524 dst_pixel_rate = SC4210_PIXEL_RATES_4LANE_HDR2;
2525
2526 sc4210->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
2527 V4L2_CID_PIXEL_RATE, 0,
2528 SC4210_MAX_PIXEL_RATE,
2529 1, dst_pixel_rate);
2530
2531 h_blank = mode->hts_def - mode->width;
2532 sc4210->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
2533 h_blank, h_blank, 1, h_blank);
2534 if (sc4210->hblank)
2535 sc4210->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
2536
2537 vblank_def = mode->vts_def - mode->height;
2538 sc4210->vblank = v4l2_ctrl_new_std(handler, &sc4210_ctrl_ops,
2539 V4L2_CID_VBLANK, vblank_def,
2540 SC4210_VTS_MAX - mode->height,
2541 1, vblank_def);
2542 sc4210->cur_fps = mode->max_fps;
2543 exposure_max = (mode->vts_def << 1) - 2;
2544 sc4210->exposure = v4l2_ctrl_new_std(handler, &sc4210_ctrl_ops,
2545 V4L2_CID_EXPOSURE,
2546 SC4210_EXPOSURE_MIN,
2547 exposure_max,
2548 SC4210_EXPOSURE_STEP,
2549 mode->exp_def);
2550
2551 sc4210->anal_gain = v4l2_ctrl_new_std(handler, &sc4210_ctrl_ops,
2552 V4L2_CID_ANALOGUE_GAIN,
2553 SC4210_GAIN_MIN,
2554 SC4210_GAIN_MAX,
2555 SC4210_GAIN_STEP,
2556 SC4210_GAIN_DEFAULT);
2557
2558 v4l2_ctrl_new_std(handler, &sc4210_ctrl_ops,
2559 V4L2_CID_HFLIP, 0, 1, 1, 0);
2560
2561 v4l2_ctrl_new_std(handler, &sc4210_ctrl_ops,
2562 V4L2_CID_VFLIP, 0, 1, 1, 0);
2563
2564 if (handler->error) {
2565 ret = handler->error;
2566 dev_err(&sc4210->client->dev,
2567 "Failed to init controls(%d)\n", ret);
2568 goto err_free_handler;
2569 }
2570 sc4210->subdev.ctrl_handler = handler;
2571 sc4210->has_init_exp = false;
2572
2573 return 0;
2574
2575 err_free_handler:
2576 v4l2_ctrl_handler_free(handler);
2577 return ret;
2578 }
2579
sc4210_check_sensor_id(struct sc4210 * sc4210,struct i2c_client * client)2580 static int sc4210_check_sensor_id(struct sc4210 *sc4210,
2581 struct i2c_client *client)
2582 {
2583 struct device *dev = &sc4210->client->dev;
2584 u32 id = 0;
2585 int ret;
2586
2587 ret = sc4210_read_reg(client, SC4210_REG_CHIP_ID,
2588 SC4210_REG_VALUE_16BIT, &id);
2589 if (id != SC4210_CHIP_ID) {
2590 dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret);
2591 return -ENODEV;
2592 }
2593
2594 dev_info(dev, "Detected SC%06x sensor\n", SC4210_CHIP_ID);
2595
2596 return 0;
2597 }
2598
sc4210_configure_regulators(struct sc4210 * sc4210)2599 static int sc4210_configure_regulators(struct sc4210 *sc4210)
2600 {
2601 unsigned int i;
2602
2603 for (i = 0; i < sc4210_NUM_SUPPLIES; i++)
2604 sc4210->supplies[i].supply = sc4210_supply_names[i];
2605
2606 return devm_regulator_bulk_get(&sc4210->client->dev,
2607 sc4210_NUM_SUPPLIES,
2608 sc4210->supplies);
2609 }
2610
sc4210_probe(struct i2c_client * client,const struct i2c_device_id * id)2611 static int sc4210_probe(struct i2c_client *client,
2612 const struct i2c_device_id *id)
2613 {
2614 struct device *dev = &client->dev;
2615 struct device_node *node = dev->of_node;
2616 struct sc4210 *sc4210;
2617 struct v4l2_subdev *sd;
2618 char facing[2];
2619 int ret;
2620 u32 hdr_mode = 0;
2621
2622 dev_info(dev, "driver version: %02x.%02x.%02x",
2623 DRIVER_VERSION >> 16,
2624 (DRIVER_VERSION & 0xff00) >> 8,
2625 DRIVER_VERSION & 0x00ff);
2626
2627 sc4210 = devm_kzalloc(dev, sizeof(*sc4210), GFP_KERNEL);
2628 if (!sc4210)
2629 return -ENOMEM;
2630
2631 of_property_read_u32(node, OF_CAMERA_HDR_MODE, &hdr_mode);
2632 ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
2633 &sc4210->module_index);
2634 ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
2635 &sc4210->module_facing);
2636 ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME,
2637 &sc4210->module_name);
2638 ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME,
2639 &sc4210->len_name);
2640 if (ret) {
2641 dev_err(dev, "could not get module information!\n");
2642 return -EINVAL;
2643 }
2644
2645 sc4210->client = client;
2646
2647 ret = sc4210_parse_of(sc4210);
2648 if (ret)
2649 return -EINVAL;
2650
2651 sc4210->xvclk = devm_clk_get(dev, "xvclk");
2652 if (IS_ERR(sc4210->xvclk)) {
2653 dev_err(dev, "Failed to get xvclk\n");
2654 return -EINVAL;
2655 }
2656
2657 sc4210->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
2658 if (IS_ERR(sc4210->reset_gpio))
2659 dev_warn(dev, "Failed to get reset-gpios\n");
2660
2661 sc4210->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
2662 if (IS_ERR(sc4210->pwdn_gpio))
2663 dev_warn(dev, "Failed to get pwdn-gpios\n");
2664
2665 sc4210->pinctrl = devm_pinctrl_get(dev);
2666 if (!IS_ERR(sc4210->pinctrl)) {
2667 sc4210->pins_default =
2668 pinctrl_lookup_state(sc4210->pinctrl,
2669 OF_CAMERA_PINCTRL_STATE_DEFAULT);
2670 if (IS_ERR(sc4210->pins_default))
2671 dev_err(dev, "could not get default pinstate\n");
2672
2673 sc4210->pins_sleep =
2674 pinctrl_lookup_state(sc4210->pinctrl,
2675 OF_CAMERA_PINCTRL_STATE_SLEEP);
2676 if (IS_ERR(sc4210->pins_sleep))
2677 dev_err(dev, "could not get sleep pinstate\n");
2678 } else {
2679 dev_err(dev, "no pinctrl\n");
2680 }
2681
2682 ret = sc4210_configure_regulators(sc4210);
2683 if (ret) {
2684 dev_err(dev, "Failed to get power regulators\n");
2685 return ret;
2686 }
2687
2688 mutex_init(&sc4210->mutex);
2689
2690 sd = &sc4210->subdev;
2691 v4l2_i2c_subdev_init(sd, client, &sc4210_subdev_ops);
2692 ret = sc4210_initialize_controls(sc4210);
2693 if (ret)
2694 goto err_destroy_mutex;
2695
2696 ret = __sc4210_power_on(sc4210);
2697 if (ret)
2698 goto err_free_handler;
2699
2700 ret = sc4210_check_sensor_id(sc4210, client);
2701 if (ret)
2702 goto err_power_off;
2703
2704 #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
2705 sd->internal_ops = &sc4210_internal_ops;
2706 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
2707 V4L2_SUBDEV_FL_HAS_EVENTS;
2708 #endif
2709 #if defined(CONFIG_MEDIA_CONTROLLER)
2710 sc4210->pad.flags = MEDIA_PAD_FL_SOURCE;
2711 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
2712 ret = media_entity_pads_init(&sd->entity, 1, &sc4210->pad);
2713 if (ret < 0)
2714 goto err_power_off;
2715 #endif
2716
2717 memset(facing, 0, sizeof(facing));
2718 if (strcmp(sc4210->module_facing, "back") == 0)
2719 facing[0] = 'b';
2720 else
2721 facing[0] = 'f';
2722
2723 snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s",
2724 sc4210->module_index, facing,
2725 SC4210_NAME, dev_name(sd->dev));
2726 ret = v4l2_async_register_subdev_sensor_common(sd);
2727 if (ret) {
2728 dev_err(&sc4210->client->dev,
2729 "v4l2 async register subdev failed\n");
2730 goto err_clean_entity;
2731 }
2732
2733 pm_runtime_set_active(dev);
2734 pm_runtime_enable(dev);
2735 pm_runtime_idle(dev);
2736
2737 return 0;
2738
2739 err_clean_entity:
2740 #if defined(CONFIG_MEDIA_CONTROLLER)
2741 media_entity_cleanup(&sd->entity);
2742 #endif
2743 err_power_off:
2744 __sc4210_power_off(sc4210);
2745 err_free_handler:
2746 v4l2_ctrl_handler_free(&sc4210->ctrl_handler);
2747 err_destroy_mutex:
2748 mutex_destroy(&sc4210->mutex);
2749
2750 return ret;
2751 }
2752
sc4210_remove(struct i2c_client * client)2753 static int sc4210_remove(struct i2c_client *client)
2754 {
2755 struct v4l2_subdev *sd = i2c_get_clientdata(client);
2756 struct sc4210 *sc4210 = to_sc4210(sd);
2757
2758 v4l2_async_unregister_subdev(sd);
2759 #if defined(CONFIG_MEDIA_CONTROLLER)
2760 media_entity_cleanup(&sd->entity);
2761 #endif
2762 v4l2_ctrl_handler_free(&sc4210->ctrl_handler);
2763 mutex_destroy(&sc4210->mutex);
2764
2765 pm_runtime_disable(&client->dev);
2766 if (!pm_runtime_status_suspended(&client->dev))
2767 __sc4210_power_off(sc4210);
2768 pm_runtime_set_suspended(&client->dev);
2769
2770 return 0;
2771 }
2772
2773 #if IS_ENABLED(CONFIG_OF)
2774 static const struct of_device_id sc4210_of_match[] = {
2775 { .compatible = "smartsens,sc4210" },
2776 { },
2777 };
2778 MODULE_DEVICE_TABLE(of, sc4210_of_match);
2779 #endif
2780
2781 static const struct i2c_device_id sc4210_match_id[] = {
2782 { "smartsens,sc4210", 0 },
2783 { },
2784 };
2785
2786 static struct i2c_driver sc4210_i2c_driver = {
2787 .driver = {
2788 .name = SC4210_NAME,
2789 .pm = &sc4210_pm_ops,
2790 .of_match_table = of_match_ptr(sc4210_of_match),
2791 },
2792 .probe = &sc4210_probe,
2793 .remove = &sc4210_remove,
2794 .id_table = sc4210_match_id,
2795 };
2796
sensor_mod_init(void)2797 static int __init sensor_mod_init(void)
2798 {
2799 return i2c_add_driver(&sc4210_i2c_driver);
2800 }
2801
sensor_mod_exit(void)2802 static void __exit sensor_mod_exit(void)
2803 {
2804 i2c_del_driver(&sc4210_i2c_driver);
2805 }
2806
2807 device_initcall_sync(sensor_mod_init);
2808 module_exit(sensor_mod_exit);
2809
2810 MODULE_DESCRIPTION("smartsens sc4210 sensor driver");
2811 MODULE_LICENSE("GPL");
2812