forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/media/i2c/sc2355.c
....@@ -0,0 +1,1522 @@
1
+// SPDX-License-Identifier: GPL-2.0
2
+/*
3
+ * SC2355 driver
4
+ *
5
+ * Copyright (C) 2023 Rockchip Electronics Co., Ltd.
6
+ * V0.1.0: MIPI is ok.
7
+ */
8
+
9
+#include <linux/clk.h>
10
+#include <linux/device.h>
11
+#include <linux/delay.h>
12
+#include <linux/gpio/consumer.h>
13
+#include <linux/i2c.h>
14
+#include <linux/module.h>
15
+#include <linux/pm_runtime.h>
16
+#include <linux/regulator/consumer.h>
17
+#include <linux/sysfs.h>
18
+#include <linux/slab.h>
19
+#include <linux/version.h>
20
+#include <linux/rk-camera-module.h>
21
+#include <media/media-entity.h>
22
+#include <media/v4l2-async.h>
23
+#include <media/v4l2-ctrls.h>
24
+#include <media/v4l2-subdev.h>
25
+#include <linux/pinctrl/consumer.h>
26
+
27
+#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x00)
28
+#ifndef V4L2_CID_DIGITAL_GAIN
29
+#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
30
+#endif
31
+
32
+#define MIPI_FREQ_180M 180000000
33
+#define MIPI_FREQ_360M 360000000
34
+
35
+#define PIXEL_RATE_WITH_180M (MIPI_FREQ_180M * 2 / 10)
36
+#define PIXEL_RATE_WITH_360M (MIPI_FREQ_360M * 2 / 10)
37
+
38
+#define SC2355_XVCLK_FREQ 24000000
39
+
40
+#define CHIP_ID 0xeb2c
41
+#define SC2355_REG_CHIP_ID 0x3107
42
+
43
+#define SC2355_REG_CTRL_MODE 0x0100
44
+#define SC2355_MODE_SW_STANDBY 0x0
45
+#define SC2355_MODE_STREAMING BIT(0)
46
+
47
+#define SC2355_REG_EXPOSURE 0x3e01
48
+#define SC2355_EXPOSURE_MIN 6
49
+#define SC2355_EXPOSURE_STEP 1
50
+#define SC2355_VTS_MAX 0xffff
51
+
52
+#define SC2355_REG_COARSE_AGAIN 0x3e09
53
+
54
+#define ANALOG_GAIN_MIN 0x01
55
+#define ANALOG_GAIN_MAX 0xF8
56
+#define ANALOG_GAIN_STEP 1
57
+#define ANALOG_GAIN_DEFAULT 0x1f
58
+
59
+#define SC2355_REG_TEST_PATTERN 0x4501
60
+#define SC2355_TEST_PATTERN_ENABLE 0xcc
61
+#define SC2355_TEST_PATTERN_DISABLE 0xc4
62
+
63
+#define SC2355_REG_VTS 0x320e
64
+
65
+#define REG_NULL 0xFFFF
66
+
67
+#define SC2355_REG_VALUE_08BIT 1
68
+#define SC2355_REG_VALUE_16BIT 2
69
+#define SC2355_REG_VALUE_24BIT 3
70
+
71
+#define SC2355_NAME "sc2355"
72
+
73
+#define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default"
74
+#define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep"
75
+
76
+#define SC2355_FETCH_3RD_BYTE_EXP(VAL) (((VAL) >> 16) & 0xF) /* 4 Bits */
77
+#define SC2355_FETCH_2ND_BYTE_EXP(VAL) (((VAL) >> 8) & 0xFF) /* 8 Bits */
78
+#define SC2355_FETCH_1ST_BYTE_EXP(VAL) ((VAL) & 0xFF) /* 4 Bits */
79
+
80
+//fps set
81
+#define SC2355_FPS (20)
82
+
83
+//default exposure
84
+#define EXP_DEFAULT_TIME_US (8000)
85
+
86
+#define SC2355_VTS_30_FPS 0x4e2
87
+
88
+#define TIME_MS 1000
89
+#define SC2355_VTS (SC2355_VTS_30_FPS * 30 / SC2355_FPS)
90
+
91
+#define SC2355_TIME_TO_EXP_LINE_US(time_us) \
92
+ (uint16_t)(time_us/1000*30*SC2355_VTS_30_FPS/TIME_MS)
93
+
94
+#define SC2355_DEFAULT_EXP_REG \
95
+ SC2355_TIME_TO_EXP_LINE_US(EXP_DEFAULT_TIME_US)
96
+
97
+#define SC2355_FSYNC_RISING_MARGIN_TIME (600)//us
98
+#define SC2355_FSYNC_RISING_MARGIN \
99
+ SC2355_TIME_TO_EXP_LINE_US(SC2355_FSYNC_RISING_MARGIN_TIME)
100
+
101
+#define SC2355_EXP_REG_TO_FSYNC_RISING(exp_reg) \
102
+ (exp_reg - 15 + SC2355_FSYNC_RISING_MARGIN)
103
+
104
+#define SC2355_DEFAULT_FSYNC_RISING \
105
+ SC2355_EXP_REG_TO_FSYNC_RISING(SC2355_DEFAULT_EXP_REG)
106
+
107
+#define SC2355_DEFAULT_FSYNC_FALLING (0x4c0)
108
+#define SC2355_DEFAULT_FSYNC_FALLING_BINNING (0x4c0/2 + 2)
109
+#define SC2355_FSYNC_RISING_REG (0x3217)
110
+
111
+#define SLAVE_MODE
112
+//slave mode max exp time (RB_ROW)
113
+#define EXP_MAX_TIME_US (13*1000)
114
+#define SC2355_SLAVE_RB_ROW SC2355_TIME_TO_EXP_LINE_US(EXP_MAX_TIME_US)
115
+
116
+#define BINNING_MODE
117
+
118
+static const char *const SC2355_supply_names[] = {
119
+ "avdd", /* Analog power */
120
+ "dovdd", /* Digital I/O power */
121
+ "dvdd", /* Digital core power */
122
+};
123
+
124
+#define SC2355_NUM_SUPPLIES ARRAY_SIZE(SC2355_supply_names)
125
+
126
+enum {
127
+ LINK_FREQ_180M_INDEX,
128
+ LINK_FREQ_360M_INDEX,
129
+};
130
+
131
+struct regval {
132
+ u16 addr;
133
+ u8 val;
134
+};
135
+
136
+struct SC2355_mode {
137
+ u32 width;
138
+ u32 height;
139
+ struct v4l2_fract max_fps;
140
+ u32 hts_def;
141
+ u32 vts_def;
142
+ u32 exp_def;
143
+ u32 link_freq_index;
144
+ u64 pixel_rate;
145
+ const struct regval *reg_list;
146
+ u32 lanes;
147
+ u32 bus_fmt;
148
+};
149
+
150
+struct SC2355 {
151
+ struct i2c_client *client;
152
+ struct clk *xvclk;
153
+ struct gpio_desc *reset_gpio;
154
+ struct gpio_desc *pwdn_gpio;
155
+ struct regulator_bulk_data supplies[SC2355_NUM_SUPPLIES];
156
+ struct pinctrl *pinctrl;
157
+ struct pinctrl_state *pins_default;
158
+ struct pinctrl_state *pins_sleep;
159
+ struct v4l2_subdev subdev;
160
+ struct media_pad pad;
161
+ struct v4l2_ctrl_handler ctrl_handler;
162
+ struct v4l2_ctrl *exposure;
163
+ struct v4l2_ctrl *anal_gain;
164
+ struct v4l2_ctrl *digi_gain;
165
+ struct v4l2_ctrl *hblank;
166
+ struct v4l2_ctrl *vblank;
167
+ struct v4l2_ctrl *test_pattern;
168
+ struct v4l2_ctrl *pixel_rate;
169
+ struct v4l2_ctrl *link_freq;
170
+ struct mutex mutex;
171
+ struct v4l2_fract cur_fps;
172
+ u32 cur_vts;
173
+ bool streaming;
174
+ bool power_on;
175
+ const struct SC2355_mode *cur_mode;
176
+ u32 module_index;
177
+ const char *module_facing;
178
+ const char *module_name;
179
+ const char *len_name;
180
+};
181
+
182
+#define to_SC2355(sd) container_of(sd, struct SC2355, subdev)
183
+
184
+/*
185
+ * Xclk 24Mhz
186
+ * Pclk 72Mhz
187
+ * linelength ()
188
+ * framelength ()
189
+ * grabwindow_width 800
190
+ * grabwindow_height 600
191
+ * mipi 1 lane
192
+ * max_framerate 30fps
193
+ * mipi_datarate per lane 360Mbps
194
+ */
195
+static const struct regval SC2355_1lane_10bit_360Mbps_800x600_30fps_regs[] = {
196
+ {0x0103,0x01},
197
+ {0x0100,0x00},
198
+ {0x36e9,0x80},
199
+ {0x36ea,0x0f},
200
+ {0x36eb,0x24},
201
+ {0x36ed,0x14},
202
+ {0x36e9,0x01},
203
+ {0x301f,0x0c},
204
+ {0x303f,0x82},
205
+ {0x3208,0x03},
206
+ {0x3209,0x20},
207
+ {0x320a,0x02},
208
+ {0x320b,0x58},
209
+ {0x3211,0x02},
210
+ {0x3213,0x02},
211
+ {0x3215,0x31},
212
+ {0x3220,0x01},
213
+ {0x3248,0x02},
214
+ {0x3253,0x0a},
215
+ {0x3301,0xff},
216
+ {0x3302,0xff},
217
+ {0x3303,0x10},
218
+ {0x3306,0x28},
219
+ {0x3307,0x02},
220
+ {0x330a,0x00},
221
+ {0x330b,0xb0},
222
+ {0x3318,0x02},
223
+ {0x3320,0x06},
224
+ {0x3321,0x02},
225
+ {0x3326,0x12},
226
+ {0x3327,0x0e},
227
+ {0x3328,0x03},
228
+ {0x3329,0x0f},
229
+ {0x3364,0x4f},
230
+ {0x33b3,0x40},
231
+ {0x33f9,0x2c},
232
+ {0x33fb,0x38},
233
+ {0x33fc,0x0f},
234
+ {0x33fd,0x1f},
235
+ {0x349f,0x03},
236
+ {0x34a6,0x01},
237
+ {0x34a7,0x1f},
238
+ {0x34a8,0x40},
239
+ {0x34a9,0x30},
240
+ {0x34ab,0xa6},
241
+ {0x34ad,0xa6},
242
+ {0x3622,0x60},
243
+ {0x3623,0x40},
244
+ {0x3624,0x61},
245
+ {0x3625,0x08},
246
+ {0x3626,0x03},
247
+ {0x3630,0xa8},
248
+ {0x3631,0x84},
249
+ {0x3632,0x90},
250
+ {0x3633,0x43},
251
+ {0x3634,0x09},
252
+ {0x3635,0x82},
253
+ {0x3636,0x48},
254
+ {0x3637,0xe4},
255
+ {0x3641,0x22},
256
+ {0x3670,0x0f},
257
+ {0x3674,0xc0},
258
+ {0x3675,0xc0},
259
+ {0x3676,0xc0},
260
+ {0x3677,0x86},
261
+ {0x3678,0x88},
262
+ {0x3679,0x8c},
263
+ {0x367c,0x01},
264
+ {0x367d,0x0f},
265
+ {0x367e,0x01},
266
+ {0x367f,0x0f},
267
+ {0x3690,0x63},
268
+ {0x3691,0x63},
269
+ {0x3692,0x73},
270
+ {0x369c,0x01},
271
+ {0x369d,0x1f},
272
+ {0x369e,0x8a},
273
+ {0x369f,0x9e},
274
+ {0x36a0,0xda},
275
+ {0x36a1,0x01},
276
+ {0x36a2,0x03},
277
+ {0x3900,0x0d},
278
+ {0x3904,0x04},
279
+ {0x3905,0x98},
280
+ {0x391b,0x81},
281
+ {0x391c,0x10},
282
+ {0x391d,0x19},
283
+ {0x3933,0x01},
284
+ {0x3934,0x82},
285
+ {0x3940,0x5d},
286
+ {0x3942,0x01},
287
+ {0x3943,0x82},
288
+ {0x3949,0xc8},
289
+ {0x394b,0x64},
290
+ {0x3952,0x02},
291
+ {0x3e00,0x00},
292
+ {0x3e01,0x4d},
293
+ {0x3e02,0xe0},
294
+ {0x4502,0x34},
295
+ {0x4509,0x30},
296
+ {0x450a,0x71},
297
+ {0x4819,0x09},
298
+ {0x481b,0x05},
299
+ {0x481d,0x13},
300
+ {0x481f,0x04},
301
+ {0x4821,0x0a},
302
+ {0x4823,0x05},
303
+ {0x4825,0x04},
304
+ {0x4827,0x05},
305
+ {0x4829,0x08},
306
+ {0x5000,0x46},
307
+ {0x5900,0xf1}, //fix noise
308
+ {0x5901,0x04},
309
+
310
+ //vts
311
+ {0x320e,(SC2355_VTS>>8)&0xff},
312
+ {0x320f,SC2355_VTS&0xff},
313
+
314
+ //exp
315
+ {0x3e00,SC2355_FETCH_3RD_BYTE_EXP(SC2355_DEFAULT_EXP_REG)},
316
+ {0x3e01,SC2355_FETCH_2ND_BYTE_EXP(SC2355_DEFAULT_EXP_REG)},
317
+ {0x3e02,SC2355_FETCH_1ST_BYTE_EXP(SC2355_DEFAULT_EXP_REG)},
318
+
319
+ //[flip]
320
+ {0x3221,0x3 << 5},
321
+
322
+ //[gain=1]
323
+ {0x3e09,0x00},
324
+
325
+ //fsync
326
+#ifndef SLAVE_MODE
327
+ {0x300b,0x44},//FSYNC out
328
+ {0x3217,SC2355_DEFAULT_FSYNC_RISING},
329
+ {0x322e,(SC2355_DEFAULT_FSYNC_FALLING_BINNING>>8)&0xff},
330
+ {0x322f,SC2355_DEFAULT_FSYNC_FALLING_BINNING&0xff},
331
+#else
332
+ {0x3222, 0x01 << 1},//slave mode
333
+ {0x300a, 0x00 << 2},//input mode
334
+
335
+ {0x3230, (SC2355_SLAVE_RB_ROW >> 8)&0xff},
336
+ {0x3231, SC2355_SLAVE_RB_ROW & 0xff},
337
+#endif
338
+
339
+ {REG_NULL, 0x00},
340
+};
341
+
342
+
343
+/*
344
+ * Xclk 24Mhz
345
+ * Pclk 72Mhz
346
+ * linelength ()
347
+ * framelength ()
348
+ * grabwindow_width 1600
349
+ * grabwindow_height 1200
350
+ * mipi 1 lane
351
+ * max_framerate 30fps
352
+ */
353
+static const struct regval SC2355_1lane_10bit_1600x1200_30fps_regs[] = {
354
+ {0x0103,0x01},
355
+ {0x0100,0x00},
356
+
357
+ {0x301f,0x01},
358
+ {0x3248,0x02},
359
+ {0x3253,0x0a},
360
+ {0x3301,0xff},
361
+ {0x3302,0xff},
362
+ {0x3303,0x10},
363
+ {0x3306,0x28},
364
+ {0x3307,0x02},
365
+ {0x330a,0x00},
366
+ {0x330b,0xb0},
367
+ {0x3318,0x02},
368
+ {0x3320,0x06},
369
+ {0x3321,0x02},
370
+ {0x3326,0x12},
371
+ {0x3327,0x0e},
372
+ {0x3328,0x03},
373
+ {0x3329,0x0f},
374
+ {0x3364,0x4f},
375
+ {0x33b3,0x40},
376
+ {0x33f9,0x2c},
377
+ {0x33fb,0x38},
378
+ {0x33fc,0x0f},
379
+ {0x33fd,0x1f},
380
+ {0x349f,0x03},
381
+ {0x34a6,0x01},
382
+ {0x34a7,0x1f},
383
+ {0x34a8,0x40},
384
+ {0x34a9,0x30},
385
+ {0x34ab,0xa6},
386
+ {0x34ad,0xa6},
387
+ {0x3622,0x60},
388
+ {0x3623,0x40},
389
+ {0x3624,0x61},
390
+ {0x3625,0x08},
391
+ {0x3626,0x03},
392
+ {0x3630,0xa8},
393
+ {0x3631,0x84},
394
+ {0x3632,0x90},
395
+ {0x3633,0x43},
396
+ {0x3634,0x09},
397
+ {0x3635,0x82},
398
+ {0x3636,0x48},
399
+ {0x3637,0xe4},
400
+ {0x3641,0x22},
401
+ {0x3670,0x0f},
402
+ {0x3674,0xc0},
403
+ {0x3675,0xc0},
404
+ {0x3676,0xc0},
405
+ {0x3677,0x86},
406
+ {0x3678,0x88},
407
+ {0x3679,0x8c},
408
+ {0x367c,0x01},
409
+ {0x367d,0x0f},
410
+ {0x367e,0x01},
411
+ {0x367f,0x0f},
412
+ {0x3690,0x63},
413
+ {0x3691,0x63},
414
+ {0x3692,0x73},
415
+ {0x369c,0x01},
416
+ {0x369d,0x1f},
417
+ {0x369e,0x8a},
418
+ {0x369f,0x9e},
419
+ {0x36a0,0xda},
420
+ {0x36a1,0x01},
421
+ {0x36a2,0x03},
422
+ {0x36e9,0x01},
423
+ {0x36ea,0x0f},
424
+ {0x36eb,0x25},
425
+ {0x36ed,0x04},
426
+ {0x3900,0x0d},
427
+ {0x3904,0x06},
428
+ {0x3905,0x98},
429
+ {0x391b,0x81},
430
+ {0x391c,0x10},
431
+ {0x391d,0x19},
432
+ {0x3933,0x01},
433
+ {0x3934,0x82},
434
+ {0x3940,0x5d},
435
+ {0x3942,0x01},
436
+ {0x3943,0x82},
437
+ {0x3949,0xc8},
438
+ {0x394b,0x64},
439
+ {0x3952,0x02},
440
+
441
+ //vts
442
+ {0x320e,(SC2355_VTS>>8)&0xff},
443
+ {0x320f,SC2355_VTS&0xff},
444
+
445
+ {0x3e00, SC2355_FETCH_3RD_BYTE_EXP(SC2355_DEFAULT_EXP_REG)},
446
+ {0x3e01, SC2355_FETCH_2ND_BYTE_EXP(SC2355_DEFAULT_EXP_REG)},
447
+ {0x3e02, SC2355_FETCH_1ST_BYTE_EXP(SC2355_DEFAULT_EXP_REG)},
448
+ {0x4502,0x34},
449
+ {0x4509,0x30},
450
+ {0x450a,0x71},
451
+
452
+ //[flip]
453
+ {0x3221,0x3 << 5},
454
+ //[gain=2]
455
+ {0x3e09,0x01},
456
+
457
+#ifndef SLAVE_MODE
458
+ {0x300b,0x44},//FSYNC out
459
+ {0x3217,SC2355_DEFAULT_FSYNC_RISING},
460
+ {0x322e,(SC2355_DEFAULT_FSYNC_FALLING>>8)&0xff},
461
+ {0x322f,SC2355_DEFAULT_FSYNC_FALLING&0xff},
462
+#else
463
+ {0x3222, 0x01 << 1},//slave mode
464
+ {0x300a, 0x00 << 2},//input mode
465
+
466
+ {0x3230, (SC2355_SLAVE_RB_ROW >> 8)&0xff},//input mode
467
+ {0x3231, SC2355_SLAVE_RB_ROW & 0xff},//input mode
468
+#endif
469
+};
470
+
471
+static const struct SC2355_mode supported_modes[] = {
472
+#ifdef BINNING_MODE
473
+ {
474
+ .width = 800,
475
+ .height = 600,
476
+ .max_fps = {
477
+ .numerator = 10000,
478
+ .denominator = 300000,
479
+ },
480
+ .exp_def = SC2355_DEFAULT_EXP_REG,
481
+ .hts_def = 0x640,
482
+ .vts_def = SC2355_VTS,
483
+ .link_freq_index = LINK_FREQ_360M_INDEX,
484
+ .pixel_rate = PIXEL_RATE_WITH_360M,
485
+ .reg_list = SC2355_1lane_10bit_360Mbps_800x600_30fps_regs,
486
+ .lanes = 1,
487
+ .bus_fmt = MEDIA_BUS_FMT_Y10_1X10,
488
+ },
489
+#else
490
+ {
491
+ .width = 1600,
492
+ .height = 1200,
493
+ .max_fps = {
494
+ .numerator = 10000,
495
+ .denominator = 300000,
496
+ },
497
+ .exp_def = SC2355_DEFAULT_EXP_REG,
498
+ .hts_def = 0x640,
499
+ .vts_def = SC2355_VTS,
500
+ .link_freq_index = LINK_FREQ_360M_INDEX,
501
+ .pixel_rate = PIXEL_RATE_WITH_360M,
502
+ .reg_list = SC2355_1lane_10bit_1600x1200_30fps_regs,
503
+ .lanes = 1,
504
+ .bus_fmt = MEDIA_BUS_FMT_Y10_1X10,
505
+ },
506
+#endif
507
+};
508
+
509
+static const char *const SC2355_test_pattern_menu[] = {
510
+ "Disabled",
511
+ "Vertical Color Bar Type 1",
512
+ "Vertical Color Bar Type 2",
513
+ "Vertical Color Bar Type 3",
514
+ "Vertical Color Bar Type 4"
515
+};
516
+
517
+static const s64 link_freq_menu_items[] = {
518
+ MIPI_FREQ_180M,
519
+ MIPI_FREQ_360M,
520
+};
521
+
522
+/* Write registers up to 4 at a time */
523
+static int SC2355_write_reg(struct i2c_client *client,
524
+ u16 reg, u32 len, u32 val)
525
+{
526
+ u32 buf_i, val_i;
527
+ u8 buf[6];
528
+ u8 *val_p;
529
+ __be32 val_be;
530
+ u32 ret;
531
+
532
+ if (len > 4)
533
+ return -EINVAL;
534
+
535
+ buf[0] = reg >> 8;
536
+ buf[1] = reg & 0xff;
537
+
538
+ val_be = cpu_to_be32(val);
539
+ val_p = (u8 *)&val_be;
540
+ buf_i = 2;
541
+ val_i = 4 - len;
542
+
543
+ while (val_i < 4)
544
+ buf[buf_i++] = val_p[val_i++];
545
+
546
+ ret = i2c_master_send(client, buf, len + 2);
547
+ if (ret != len + 2)
548
+ return -EIO;
549
+
550
+ return 0;
551
+}
552
+
553
+static int SC2355_write_array(struct i2c_client *client,
554
+ const struct regval *regs)
555
+{
556
+ u32 i;
557
+ int ret = 0;
558
+
559
+ for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) {
560
+ ret = SC2355_write_reg(client, regs[i].addr,
561
+ SC2355_REG_VALUE_08BIT, regs[i].val);
562
+ }
563
+
564
+ return ret;
565
+}
566
+
567
+/* Read registers up to 4 at a time */
568
+static int SC2355_read_reg(struct i2c_client *client,
569
+ u16 reg, unsigned int len, u32 *val)
570
+{
571
+ struct i2c_msg msgs[2];
572
+ u8 *data_be_p;
573
+ __be32 data_be = 0;
574
+ __be16 reg_addr_be = cpu_to_be16(reg);
575
+ int ret;
576
+
577
+ if (len > 4 || !len)
578
+ return -EINVAL;
579
+
580
+ data_be_p = (u8 *)&data_be;
581
+ /* Write register address */
582
+ msgs[0].addr = client->addr;
583
+ msgs[0].flags = 0;
584
+ msgs[0].len = 2;
585
+ msgs[0].buf = (u8 *)&reg_addr_be;
586
+
587
+ /* Read data from register */
588
+ msgs[1].addr = client->addr;
589
+ msgs[1].flags = I2C_M_RD;
590
+ msgs[1].len = len;
591
+ msgs[1].buf = &data_be_p[4 - len];
592
+
593
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
594
+ if (ret != ARRAY_SIZE(msgs))
595
+ return -EIO;
596
+
597
+ *val = be32_to_cpu(data_be);
598
+
599
+ return 0;
600
+}
601
+
602
+static int SC2355_get_reso_dist(const struct SC2355_mode *mode,
603
+ struct v4l2_mbus_framefmt *framefmt)
604
+{
605
+ return abs(mode->width - framefmt->width) +
606
+ abs(mode->height - framefmt->height);
607
+}
608
+
609
+static const struct SC2355_mode *
610
+SC2355_find_best_fit(struct v4l2_subdev_format *fmt)
611
+{
612
+ struct v4l2_mbus_framefmt *framefmt = &fmt->format;
613
+ int dist;
614
+ int cur_best_fit = 0;
615
+ int cur_best_fit_dist = -1;
616
+ unsigned int i;
617
+
618
+ for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
619
+ dist = SC2355_get_reso_dist(&supported_modes[i], framefmt);
620
+ if ((cur_best_fit_dist == -1 || dist < cur_best_fit_dist) &&
621
+ (supported_modes[i].bus_fmt == framefmt->code)) {
622
+ cur_best_fit_dist = dist;
623
+ cur_best_fit = i;
624
+ }
625
+ }
626
+ return &supported_modes[cur_best_fit];
627
+}
628
+
629
+static int SC2355_set_fmt(struct v4l2_subdev *sd,
630
+ struct v4l2_subdev_pad_config *cfg,
631
+ struct v4l2_subdev_format *fmt)
632
+{
633
+ struct SC2355 *SC2355 = to_SC2355(sd);
634
+ const struct SC2355_mode *mode;
635
+ s64 h_blank, vblank_def;
636
+
637
+ mutex_lock(&SC2355->mutex);
638
+
639
+ mode = SC2355_find_best_fit(fmt);
640
+ fmt->format.code = mode->bus_fmt;
641
+ fmt->format.width = mode->width;
642
+ fmt->format.height = mode->height;
643
+ fmt->format.field = V4L2_FIELD_NONE;
644
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
645
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
646
+ *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
647
+#else
648
+ mutex_unlock(&SC2355->mutex);
649
+ return -ENOTTY;
650
+#endif
651
+ } else {
652
+ SC2355->cur_mode = mode;
653
+ h_blank = mode->hts_def - mode->width;
654
+ __v4l2_ctrl_modify_range(SC2355->hblank, h_blank,
655
+ h_blank, 1, h_blank);
656
+ vblank_def = mode->vts_def - mode->height;
657
+ __v4l2_ctrl_modify_range(SC2355->vblank, vblank_def,
658
+ SC2355_VTS_MAX - mode->height,
659
+ 1, vblank_def);
660
+ __v4l2_ctrl_s_ctrl_int64(SC2355->pixel_rate, mode->pixel_rate);
661
+ __v4l2_ctrl_s_ctrl(SC2355->link_freq, mode->link_freq_index);
662
+ SC2355->cur_vts = mode->vts_def;
663
+ SC2355->cur_fps = mode->max_fps;
664
+ }
665
+
666
+ mutex_unlock(&SC2355->mutex);
667
+
668
+ return 0;
669
+}
670
+
671
+static int SC2355_get_fmt(struct v4l2_subdev *sd,
672
+ struct v4l2_subdev_pad_config *cfg,
673
+ struct v4l2_subdev_format *fmt)
674
+{
675
+ struct SC2355 *SC2355 = to_SC2355(sd);
676
+ const struct SC2355_mode *mode = SC2355->cur_mode;
677
+
678
+ mutex_lock(&SC2355->mutex);
679
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
680
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
681
+ fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
682
+#else
683
+ mutex_unlock(&SC2355->mutex);
684
+ return -ENOTTY;
685
+#endif
686
+ } else {
687
+ fmt->format.width = mode->width;
688
+ fmt->format.height = mode->height;
689
+ fmt->format.code = mode->bus_fmt;
690
+ fmt->format.field = V4L2_FIELD_NONE;
691
+ }
692
+ mutex_unlock(&SC2355->mutex);
693
+
694
+ return 0;
695
+}
696
+
697
+static int SC2355_enum_mbus_code(struct v4l2_subdev *sd,
698
+ struct v4l2_subdev_pad_config *cfg,
699
+ struct v4l2_subdev_mbus_code_enum *code)
700
+{
701
+ struct SC2355 *SC2355 = to_SC2355(sd);
702
+
703
+ if (code->index != 0)
704
+ return -EINVAL;
705
+ code->code = SC2355->cur_mode->bus_fmt;
706
+
707
+ return 0;
708
+}
709
+
710
+static int SC2355_enum_frame_sizes(struct v4l2_subdev *sd,
711
+ struct v4l2_subdev_pad_config *cfg,
712
+ struct v4l2_subdev_frame_size_enum *fse)
713
+{
714
+ if (fse->index >= ARRAY_SIZE(supported_modes))
715
+ return -EINVAL;
716
+
717
+ if (fse->code != supported_modes[fse->index].bus_fmt)
718
+ return -EINVAL;
719
+
720
+ fse->min_width = supported_modes[fse->index].width;
721
+ fse->max_width = supported_modes[fse->index].width;
722
+ fse->max_height = supported_modes[fse->index].height;
723
+ fse->min_height = supported_modes[fse->index].height;
724
+
725
+ return 0;
726
+}
727
+
728
+static int SC2355_enable_test_pattern(struct SC2355 *SC2355, u32 pattern)
729
+{
730
+ u32 val;
731
+
732
+ if (pattern)
733
+ val = (pattern - 1) | SC2355_TEST_PATTERN_ENABLE;
734
+ else
735
+ val = SC2355_TEST_PATTERN_DISABLE;
736
+
737
+ return SC2355_write_reg(SC2355->client, SC2355_REG_TEST_PATTERN,
738
+ SC2355_REG_VALUE_08BIT, val);
739
+}
740
+
741
+static void SC2355_get_module_inf(struct SC2355 *SC2355,
742
+ struct rkmodule_inf *inf)
743
+{
744
+ memset(inf, 0, sizeof(*inf));
745
+ strscpy(inf->base.sensor, SC2355_NAME, sizeof(inf->base.sensor));
746
+ strscpy(inf->base.module, SC2355->module_name,
747
+ sizeof(inf->base.module));
748
+ strscpy(inf->base.lens, SC2355->len_name, sizeof(inf->base.lens));
749
+}
750
+
751
+static long SC2355_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
752
+{
753
+ struct SC2355 *SC2355 = to_SC2355(sd);
754
+ long ret = 0;
755
+ u32 stream = 0;
756
+
757
+ switch (cmd) {
758
+ case RKMODULE_GET_MODULE_INFO:
759
+ SC2355_get_module_inf(SC2355, (struct rkmodule_inf *)arg);
760
+ break;
761
+ case RKMODULE_SET_QUICK_STREAM:
762
+
763
+ stream = *((u32 *)arg);
764
+
765
+ if (stream)
766
+ ret = SC2355_write_reg(SC2355->client, SC2355_REG_CTRL_MODE,
767
+ SC2355_REG_VALUE_08BIT, SC2355_MODE_STREAMING);
768
+ else
769
+ ret = SC2355_write_reg(SC2355->client, SC2355_REG_CTRL_MODE,
770
+ SC2355_REG_VALUE_08BIT, SC2355_MODE_SW_STANDBY);
771
+ break;
772
+ default:
773
+ ret = -ENOIOCTLCMD;
774
+ break;
775
+ }
776
+
777
+ return ret;
778
+}
779
+
780
+#ifdef CONFIG_COMPAT
781
+static long SC2355_compat_ioctl32(struct v4l2_subdev *sd,
782
+ unsigned int cmd, unsigned long arg)
783
+{
784
+ void __user *up = compat_ptr(arg);
785
+ struct rkmodule_inf *inf;
786
+ long ret = 0;
787
+ u32 stream = 0;
788
+
789
+ switch (cmd) {
790
+ case RKMODULE_GET_MODULE_INFO:
791
+ inf = kzalloc(sizeof(*inf), GFP_KERNEL);
792
+ if (!inf) {
793
+ ret = -ENOMEM;
794
+ return ret;
795
+ }
796
+
797
+ ret = SC2355_ioctl(sd, cmd, inf);
798
+ if (!ret) {
799
+ ret = copy_to_user(up, inf, sizeof(*inf));
800
+ if (ret)
801
+ ret = -EFAULT;
802
+ }
803
+ kfree(inf);
804
+ break;
805
+ case RKMODULE_SET_QUICK_STREAM:
806
+ if (copy_from_user(&stream, up, sizeof(u32)))
807
+ return -EFAULT;
808
+
809
+ ret = SC2355_ioctl(sd, cmd, &stream);
810
+ break;
811
+ default:
812
+ ret = -ENOIOCTLCMD;
813
+ break;
814
+ }
815
+
816
+ return ret;
817
+}
818
+#endif
819
+
820
+static int SC2355_set_ctrl_gain(struct SC2355 *SC2355, u32 a_gain)
821
+{
822
+ int ret = 0;
823
+
824
+ if (a_gain > 1)
825
+ a_gain = ((a_gain + 1) >> 1) << 1;
826
+ a_gain -=1;
827
+
828
+ ret |= SC2355_write_reg(SC2355->client,
829
+ SC2355_REG_COARSE_AGAIN,
830
+ SC2355_REG_VALUE_08BIT,
831
+ a_gain);
832
+
833
+ return ret;
834
+}
835
+
836
+
837
+static int __SC2355_start_stream(struct SC2355 *SC2355)
838
+{
839
+ int ret;
840
+
841
+ ret = SC2355_write_array(SC2355->client, SC2355->cur_mode->reg_list);
842
+ if (ret)
843
+ return ret;
844
+
845
+ /* In case these controls are set before streaming */
846
+ mutex_unlock(&SC2355->mutex);
847
+ ret = v4l2_ctrl_handler_setup(&SC2355->ctrl_handler);
848
+ mutex_lock(&SC2355->mutex);
849
+ if (ret)
850
+ return ret;
851
+
852
+ ret = SC2355_write_reg(SC2355->client, SC2355_REG_CTRL_MODE,
853
+ SC2355_REG_VALUE_08BIT, SC2355_MODE_STREAMING);
854
+
855
+ return ret;
856
+}
857
+
858
+static int __SC2355_stop_stream(struct SC2355 *SC2355)
859
+{
860
+ return SC2355_write_reg(SC2355->client, SC2355_REG_CTRL_MODE,
861
+ SC2355_REG_VALUE_08BIT, SC2355_MODE_SW_STANDBY);
862
+}
863
+
864
+static int SC2355_s_stream(struct v4l2_subdev *sd, int on)
865
+{
866
+ struct SC2355 *SC2355 = to_SC2355(sd);
867
+ struct i2c_client *client = SC2355->client;
868
+ unsigned int fps;
869
+ int ret = 0;
870
+
871
+ mutex_lock(&SC2355->mutex);
872
+ on = !!on;
873
+ if (on == SC2355->streaming)
874
+ goto unlock_and_return;
875
+
876
+ fps = DIV_ROUND_CLOSEST(SC2355->cur_mode->max_fps.denominator,
877
+ SC2355->cur_mode->max_fps.numerator);
878
+
879
+ dev_info(&SC2355->client->dev, "%s: on: %d, %dx%d@%d\n", __func__, on,
880
+ SC2355->cur_mode->width,
881
+ SC2355->cur_mode->height,
882
+ fps);
883
+
884
+ if (on) {
885
+ ret = pm_runtime_get_sync(&client->dev);
886
+ if (ret < 0) {
887
+ pm_runtime_put_noidle(&client->dev);
888
+ goto unlock_and_return;
889
+ }
890
+
891
+ ret = __SC2355_start_stream(SC2355);
892
+ if (ret) {
893
+ v4l2_err(sd, "start stream failed while write regs\n");
894
+ pm_runtime_put(&client->dev);
895
+ goto unlock_and_return;
896
+ }
897
+ } else {
898
+ __SC2355_stop_stream(SC2355);
899
+ pm_runtime_put(&client->dev);
900
+ }
901
+
902
+ SC2355->streaming = on;
903
+
904
+unlock_and_return:
905
+ mutex_unlock(&SC2355->mutex);
906
+
907
+ return ret;
908
+}
909
+
910
+static int SC2355_s_power(struct v4l2_subdev *sd, int on)
911
+{
912
+ struct SC2355 *SC2355 = to_SC2355(sd);
913
+ struct i2c_client *client = SC2355->client;
914
+ int ret = 0;
915
+
916
+ mutex_lock(&SC2355->mutex);
917
+
918
+ /* If the power state is not modified - no work to do. */
919
+ if (SC2355->power_on == !!on)
920
+ goto unlock_and_return;
921
+
922
+ if (on) {
923
+ ret = pm_runtime_get_sync(&client->dev);
924
+ if (ret < 0) {
925
+ pm_runtime_put_noidle(&client->dev);
926
+ goto unlock_and_return;
927
+ }
928
+ SC2355->power_on = true;
929
+ } else {
930
+ pm_runtime_put(&client->dev);
931
+ SC2355->power_on = false;
932
+ }
933
+
934
+unlock_and_return:
935
+ mutex_unlock(&SC2355->mutex);
936
+
937
+ return ret;
938
+}
939
+
940
+static int SC2355_g_frame_interval(struct v4l2_subdev *sd,
941
+ struct v4l2_subdev_frame_interval *fi)
942
+{
943
+ struct SC2355 *SC2355 = to_SC2355(sd);
944
+ const struct SC2355_mode *mode = SC2355->cur_mode;
945
+
946
+ if (SC2355->streaming)
947
+ fi->interval = SC2355->cur_fps;
948
+ else
949
+ fi->interval = mode->max_fps;
950
+
951
+ return 0;
952
+}
953
+
954
+/* Calculate the delay in us by clock rate and clock cycles */
955
+static inline u32 SC2355_cal_delay(u32 cycles)
956
+{
957
+ return DIV_ROUND_UP(cycles, SC2355_XVCLK_FREQ / 1000 / 1000);
958
+}
959
+
960
+static int __SC2355_power_on(struct SC2355 *SC2355)
961
+{
962
+ int ret;
963
+ u32 delay_us;
964
+ struct device *dev = &SC2355->client->dev;
965
+
966
+ if (!IS_ERR_OR_NULL(SC2355->pins_default)) {
967
+ ret = pinctrl_select_state(SC2355->pinctrl,
968
+ SC2355->pins_default);
969
+ if (ret < 0)
970
+ dev_err(dev, "could not set pins\n");
971
+ }
972
+
973
+ ret = clk_set_rate(SC2355->xvclk, SC2355_XVCLK_FREQ);
974
+ if (ret < 0)
975
+ dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
976
+ if (clk_get_rate(SC2355->xvclk) != SC2355_XVCLK_FREQ)
977
+ dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
978
+ ret = clk_prepare_enable(SC2355->xvclk);
979
+ if (ret < 0) {
980
+ dev_err(dev, "Failed to enable xvclk\n");
981
+ return ret;
982
+ }
983
+
984
+ ret = regulator_bulk_enable(SC2355_NUM_SUPPLIES, SC2355->supplies);
985
+ if (ret < 0) {
986
+ dev_err(dev, "Failed to enable regulators\n");
987
+ goto disable_clk;
988
+ }
989
+
990
+ if (!IS_ERR(SC2355->reset_gpio))
991
+ gpiod_set_value_cansleep(SC2355->reset_gpio, 1);
992
+
993
+ usleep_range(1000, 2000);
994
+
995
+ if (!IS_ERR(SC2355->pwdn_gpio))
996
+ gpiod_set_value_cansleep(SC2355->pwdn_gpio, 1);
997
+
998
+ if (!IS_ERR(SC2355->reset_gpio))
999
+ gpiod_set_value_cansleep(SC2355->reset_gpio, 0);
1000
+
1001
+ /* 8192 cycles prior to first SCCB transaction */
1002
+ delay_us = SC2355_cal_delay(8192);
1003
+ usleep_range(delay_us, delay_us * 2);
1004
+
1005
+ return 0;
1006
+
1007
+disable_clk:
1008
+ clk_disable_unprepare(SC2355->xvclk);
1009
+
1010
+ return ret;
1011
+}
1012
+
1013
+static void __SC2355_power_off(struct SC2355 *SC2355)
1014
+{
1015
+ int ret;
1016
+
1017
+ if (!IS_ERR(SC2355->reset_gpio))
1018
+ gpiod_set_value_cansleep(SC2355->reset_gpio, 1);
1019
+
1020
+ if (!IS_ERR(SC2355->pwdn_gpio))
1021
+ gpiod_set_value_cansleep(SC2355->pwdn_gpio, 0);
1022
+ clk_disable_unprepare(SC2355->xvclk);
1023
+ if (!IS_ERR_OR_NULL(SC2355->pins_sleep)) {
1024
+ ret = pinctrl_select_state(SC2355->pinctrl,
1025
+ SC2355->pins_sleep);
1026
+ if (ret < 0)
1027
+ dev_dbg(&SC2355->client->dev, "could not set pins\n");
1028
+ }
1029
+ regulator_bulk_disable(SC2355_NUM_SUPPLIES, SC2355->supplies);
1030
+}
1031
+
1032
+static int SC2355_runtime_resume(struct device *dev)
1033
+{
1034
+ struct i2c_client *client = to_i2c_client(dev);
1035
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
1036
+ struct SC2355 *SC2355 = to_SC2355(sd);
1037
+
1038
+ return __SC2355_power_on(SC2355);
1039
+}
1040
+
1041
+static int SC2355_runtime_suspend(struct device *dev)
1042
+{
1043
+ struct i2c_client *client = to_i2c_client(dev);
1044
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
1045
+ struct SC2355 *SC2355 = to_SC2355(sd);
1046
+
1047
+ __SC2355_power_off(SC2355);
1048
+
1049
+ return 0;
1050
+}
1051
+
1052
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
1053
+static int SC2355_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1054
+{
1055
+ struct SC2355 *SC2355 = to_SC2355(sd);
1056
+ struct v4l2_mbus_framefmt *try_fmt =
1057
+ v4l2_subdev_get_try_format(sd, fh->pad, 0);
1058
+ const struct SC2355_mode *def_mode = &supported_modes[0];
1059
+
1060
+ mutex_lock(&SC2355->mutex);
1061
+ /* Initialize try_fmt */
1062
+ try_fmt->width = def_mode->width;
1063
+ try_fmt->height = def_mode->height;
1064
+ try_fmt->code = def_mode->bus_fmt;
1065
+ try_fmt->field = V4L2_FIELD_NONE;
1066
+
1067
+ mutex_unlock(&SC2355->mutex);
1068
+ /* No crop or compose */
1069
+
1070
+ return 0;
1071
+}
1072
+#endif
1073
+
1074
+static int SC2355_enum_frame_interval(struct v4l2_subdev *sd,
1075
+ struct v4l2_subdev_pad_config *cfg,
1076
+ struct v4l2_subdev_frame_interval_enum *fie)
1077
+{
1078
+ if (fie->index >= ARRAY_SIZE(supported_modes))
1079
+ return -EINVAL;
1080
+
1081
+ fie->code = supported_modes[fie->index].bus_fmt;
1082
+ fie->width = supported_modes[fie->index].width;
1083
+ fie->height = supported_modes[fie->index].height;
1084
+ fie->interval = supported_modes[fie->index].max_fps;
1085
+ return 0;
1086
+}
1087
+
1088
+static int SC2355_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
1089
+ struct v4l2_mbus_config *config)
1090
+{
1091
+ u32 val = 0;
1092
+ struct SC2355 *SC2355 = to_SC2355(sd);
1093
+
1094
+ val = 1 << (SC2355->cur_mode->lanes - 1) |
1095
+ V4L2_MBUS_CSI2_CHANNEL_0 |
1096
+ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
1097
+ config->type = V4L2_MBUS_CSI2_DPHY;
1098
+ config->flags = val;
1099
+
1100
+ return 0;
1101
+}
1102
+
1103
+static const struct dev_pm_ops SC2355_pm_ops = {
1104
+ SET_RUNTIME_PM_OPS(SC2355_runtime_suspend,
1105
+ SC2355_runtime_resume, NULL)
1106
+};
1107
+
1108
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
1109
+static const struct v4l2_subdev_internal_ops SC2355_internal_ops = {
1110
+ .open = SC2355_open,
1111
+};
1112
+#endif
1113
+
1114
+static const struct v4l2_subdev_core_ops SC2355_core_ops = {
1115
+ .s_power = SC2355_s_power,
1116
+ .ioctl = SC2355_ioctl,
1117
+#ifdef CONFIG_COMPAT
1118
+ .compat_ioctl32 = SC2355_compat_ioctl32,
1119
+#endif
1120
+};
1121
+
1122
+static const struct v4l2_subdev_video_ops SC2355_video_ops = {
1123
+ .s_stream = SC2355_s_stream,
1124
+ .g_frame_interval = SC2355_g_frame_interval,
1125
+};
1126
+
1127
+static const struct v4l2_subdev_pad_ops SC2355_pad_ops = {
1128
+ .enum_mbus_code = SC2355_enum_mbus_code,
1129
+ .enum_frame_size = SC2355_enum_frame_sizes,
1130
+ .enum_frame_interval = SC2355_enum_frame_interval,
1131
+ .get_fmt = SC2355_get_fmt,
1132
+ .set_fmt = SC2355_set_fmt,
1133
+ .get_mbus_config = SC2355_g_mbus_config,
1134
+};
1135
+
1136
+static const struct v4l2_subdev_ops SC2355_subdev_ops = {
1137
+ .core = &SC2355_core_ops,
1138
+ .video = &SC2355_video_ops,
1139
+ .pad = &SC2355_pad_ops,
1140
+};
1141
+
1142
+static void SC2355_modify_fps_info(struct SC2355 *SC2355)
1143
+{
1144
+ const struct SC2355_mode *mode = SC2355->cur_mode;
1145
+
1146
+ SC2355->cur_fps.denominator = mode->max_fps.denominator * SC2355->cur_vts /
1147
+ mode->vts_def;
1148
+}
1149
+
1150
+static int SC2355_set_ctrl(struct v4l2_ctrl *ctrl)
1151
+{
1152
+ struct SC2355 *SC2355 = container_of(ctrl->handler,
1153
+ struct SC2355, ctrl_handler);
1154
+ struct i2c_client *client = SC2355->client;
1155
+ s64 max;
1156
+ int ret = 0;
1157
+#ifndef SLAVE_MODE
1158
+ u16 rising_reg;
1159
+#endif
1160
+
1161
+ /* Propagate change of current control to all related controls */
1162
+ switch (ctrl->id) {
1163
+ case V4L2_CID_VBLANK:
1164
+ /* Update max exposure while meeting expected vblanking */
1165
+ max = SC2355->cur_mode->height + ctrl->val - 6;
1166
+ __v4l2_ctrl_modify_range(SC2355->exposure,
1167
+ SC2355->exposure->minimum, max,
1168
+ SC2355->exposure->step,
1169
+ SC2355->exposure->default_value);
1170
+ break;
1171
+ }
1172
+
1173
+ if (!pm_runtime_get_if_in_use(&client->dev))
1174
+ return 0;
1175
+
1176
+ switch (ctrl->id) {
1177
+ case V4L2_CID_EXPOSURE:
1178
+ /* 4 least significant bits of expsoure are fractional part */
1179
+ ret = SC2355_write_reg(SC2355->client, SC2355_REG_EXPOSURE,
1180
+ SC2355_REG_VALUE_16BIT, ctrl->val << 4);
1181
+
1182
+#ifndef SLAVE_MODE
1183
+ /* set fsync rising */
1184
+ rising_reg = SC2355_EXP_REG_TO_FSYNC_RISING(ctrl->val);
1185
+ if (rising_reg > 0xff) {
1186
+ rising_reg = 0xff;
1187
+ dev_warn(&client->dev,
1188
+ "error: rising reg exceed max val 0xff.\n");
1189
+ }
1190
+
1191
+ dev_info(&client->dev, "rising: reg:%d\n", rising_reg);
1192
+
1193
+ ret |= SC2355_write_reg(SC2355->client, SC2355_FSYNC_RISING_REG,
1194
+ SC2355_REG_VALUE_08BIT, rising_reg);
1195
+#endif
1196
+
1197
+ break;
1198
+ case V4L2_CID_ANALOGUE_GAIN:
1199
+ ret = SC2355_set_ctrl_gain(SC2355, ctrl->val);
1200
+ break;
1201
+ case V4L2_CID_VBLANK:
1202
+ ret = SC2355_write_reg(SC2355->client, SC2355_REG_VTS,
1203
+ SC2355_REG_VALUE_16BIT,
1204
+ ctrl->val + SC2355->cur_mode->height);
1205
+ if (!ret)
1206
+ SC2355->cur_vts = ctrl->val + SC2355->cur_mode->height;
1207
+ if (SC2355->cur_vts != SC2355->cur_mode->vts_def)
1208
+ SC2355_modify_fps_info(SC2355);
1209
+ break;
1210
+ case V4L2_CID_TEST_PATTERN:
1211
+ ret = SC2355_enable_test_pattern(SC2355, ctrl->val);
1212
+ break;
1213
+ default:
1214
+ dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
1215
+ __func__, ctrl->id, ctrl->val);
1216
+ break;
1217
+ }
1218
+
1219
+ pm_runtime_put(&client->dev);
1220
+
1221
+ return ret;
1222
+}
1223
+
1224
+static const struct v4l2_ctrl_ops SC2355_ctrl_ops = {
1225
+ .s_ctrl = SC2355_set_ctrl,
1226
+};
1227
+
1228
+static int SC2355_initialize_controls(struct SC2355 *SC2355)
1229
+{
1230
+ const struct SC2355_mode *mode;
1231
+ struct v4l2_ctrl_handler *handler;
1232
+ s64 exposure_max, vblank_def;
1233
+ u32 h_blank;
1234
+ int ret;
1235
+
1236
+ handler = &SC2355->ctrl_handler;
1237
+ mode = SC2355->cur_mode;
1238
+ ret = v4l2_ctrl_handler_init(handler, 8);
1239
+ if (ret)
1240
+ return ret;
1241
+ handler->lock = &SC2355->mutex;
1242
+
1243
+ SC2355->link_freq = v4l2_ctrl_new_int_menu(handler,
1244
+ NULL, V4L2_CID_LINK_FREQ,
1245
+ ARRAY_SIZE(link_freq_menu_items) - 1, 0,
1246
+ link_freq_menu_items);
1247
+
1248
+ SC2355->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
1249
+ V4L2_CID_PIXEL_RATE,
1250
+ 0, PIXEL_RATE_WITH_360M,
1251
+ 1, mode->pixel_rate);
1252
+
1253
+ __v4l2_ctrl_s_ctrl(SC2355->link_freq, mode->pixel_rate);
1254
+
1255
+ h_blank = mode->hts_def - mode->width;
1256
+ SC2355->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
1257
+ h_blank, h_blank, 1, h_blank);
1258
+ if (SC2355->hblank)
1259
+ SC2355->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1260
+
1261
+ vblank_def = mode->vts_def - mode->height;
1262
+ SC2355->cur_vts = mode->vts_def;
1263
+ SC2355->cur_fps = mode->max_fps;
1264
+ SC2355->vblank = v4l2_ctrl_new_std(handler, &SC2355_ctrl_ops,
1265
+ V4L2_CID_VBLANK, vblank_def,
1266
+ SC2355_VTS_MAX - mode->height,
1267
+ 1, vblank_def);
1268
+
1269
+ exposure_max = mode->vts_def - 6;
1270
+ SC2355->exposure = v4l2_ctrl_new_std(handler, &SC2355_ctrl_ops,
1271
+ V4L2_CID_EXPOSURE, SC2355_EXPOSURE_MIN,
1272
+ exposure_max, SC2355_EXPOSURE_STEP,
1273
+ mode->exp_def);
1274
+
1275
+ SC2355->anal_gain = v4l2_ctrl_new_std(handler, &SC2355_ctrl_ops,
1276
+ V4L2_CID_ANALOGUE_GAIN, ANALOG_GAIN_MIN,
1277
+ ANALOG_GAIN_MAX, ANALOG_GAIN_STEP,
1278
+ ANALOG_GAIN_DEFAULT);
1279
+
1280
+ SC2355->test_pattern = v4l2_ctrl_new_std_menu_items(handler,
1281
+ &SC2355_ctrl_ops, V4L2_CID_TEST_PATTERN,
1282
+ ARRAY_SIZE(SC2355_test_pattern_menu) - 1,
1283
+ 0, 0, SC2355_test_pattern_menu);
1284
+
1285
+ if (handler->error) {
1286
+ ret = handler->error;
1287
+ dev_err(&SC2355->client->dev,
1288
+ "Failed to init controls(%d)\n", ret);
1289
+ goto err_free_handler;
1290
+ }
1291
+
1292
+ SC2355->subdev.ctrl_handler = handler;
1293
+
1294
+ return 0;
1295
+
1296
+err_free_handler:
1297
+ v4l2_ctrl_handler_free(handler);
1298
+
1299
+ return ret;
1300
+}
1301
+
1302
+static int SC2355_check_sensor_id(struct SC2355 *SC2355,
1303
+ struct i2c_client *client)
1304
+{
1305
+ struct device *dev = &SC2355->client->dev;
1306
+ u32 id = 0;
1307
+ int ret;
1308
+
1309
+ ret = SC2355_read_reg(client, SC2355_REG_CHIP_ID,
1310
+ SC2355_REG_VALUE_16BIT, &id);
1311
+ if (ret || id != CHIP_ID) {
1312
+ dev_err(dev, "Unexpected sensor id(%04x), ret(%d)\n", id, ret);
1313
+ return -ENODEV;
1314
+ }
1315
+
1316
+ dev_info(dev, "Detected SC2355 CHIP ID = 0x%04x sensor\n", CHIP_ID);
1317
+
1318
+ return 0;
1319
+}
1320
+
1321
+static int SC2355_configure_regulators(struct SC2355 *SC2355)
1322
+{
1323
+ unsigned int i;
1324
+
1325
+ for (i = 0; i < SC2355_NUM_SUPPLIES; i++)
1326
+ SC2355->supplies[i].supply = SC2355_supply_names[i];
1327
+
1328
+ return devm_regulator_bulk_get(&SC2355->client->dev,
1329
+ SC2355_NUM_SUPPLIES,
1330
+ SC2355->supplies);
1331
+}
1332
+
1333
+static int SC2355_probe(struct i2c_client *client,
1334
+ const struct i2c_device_id *id)
1335
+{
1336
+ struct device *dev = &client->dev;
1337
+ struct device_node *node = dev->of_node;
1338
+ struct SC2355 *SC2355;
1339
+ struct v4l2_subdev *sd;
1340
+ char facing[2];
1341
+ int ret;
1342
+
1343
+ dev_info(dev, "driver version: %02x.%02x.%02x",
1344
+ DRIVER_VERSION >> 16,
1345
+ (DRIVER_VERSION & 0xff00) >> 8,
1346
+ DRIVER_VERSION & 0x00ff);
1347
+
1348
+ SC2355 = devm_kzalloc(dev, sizeof(*SC2355), GFP_KERNEL);
1349
+ if (!SC2355)
1350
+ return -ENOMEM;
1351
+
1352
+ ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
1353
+ &SC2355->module_index);
1354
+ ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
1355
+ &SC2355->module_facing);
1356
+ ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME,
1357
+ &SC2355->module_name);
1358
+ ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME,
1359
+ &SC2355->len_name);
1360
+ if (ret) {
1361
+ dev_err(dev, "could not get module information!\n");
1362
+ return -EINVAL;
1363
+ }
1364
+ SC2355->client = client;
1365
+ SC2355->cur_mode = &supported_modes[0];
1366
+
1367
+ SC2355->xvclk = devm_clk_get(dev, "xvclk");
1368
+ if (IS_ERR(SC2355->xvclk)) {
1369
+ dev_err(dev, "Failed to get xvclk\n");
1370
+ return -EINVAL;
1371
+ }
1372
+
1373
+ SC2355->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
1374
+ if (IS_ERR(SC2355->reset_gpio))
1375
+ dev_warn(dev, "Failed to get reset-gpios\n");
1376
+
1377
+ SC2355->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
1378
+ if (IS_ERR(SC2355->pwdn_gpio))
1379
+ dev_warn(dev, "Failed to get pwdn-gpios\n");
1380
+ ret = SC2355_configure_regulators(SC2355);
1381
+ if (ret) {
1382
+ dev_err(dev, "Failed to get power regulators\n");
1383
+ return ret;
1384
+ }
1385
+
1386
+ SC2355->pinctrl = devm_pinctrl_get(dev);
1387
+ if (!IS_ERR(SC2355->pinctrl)) {
1388
+ SC2355->pins_default =
1389
+ pinctrl_lookup_state(SC2355->pinctrl,
1390
+ OF_CAMERA_PINCTRL_STATE_DEFAULT);
1391
+ if (IS_ERR(SC2355->pins_default))
1392
+ dev_err(dev, "could not get default pinstate\n");
1393
+
1394
+ SC2355->pins_sleep =
1395
+ pinctrl_lookup_state(SC2355->pinctrl,
1396
+ OF_CAMERA_PINCTRL_STATE_SLEEP);
1397
+ if (IS_ERR(SC2355->pins_sleep))
1398
+ dev_err(dev, "could not get sleep pinstate\n");
1399
+ }
1400
+ mutex_init(&SC2355->mutex);
1401
+
1402
+ sd = &SC2355->subdev;
1403
+ v4l2_i2c_subdev_init(sd, client, &SC2355_subdev_ops);
1404
+ ret = SC2355_initialize_controls(SC2355);
1405
+ if (ret)
1406
+ goto err_destroy_mutex;
1407
+
1408
+ ret = __SC2355_power_on(SC2355);
1409
+ if (ret)
1410
+ goto err_free_handler;
1411
+
1412
+ ret = SC2355_check_sensor_id(SC2355, client);
1413
+ if (ret)
1414
+ goto err_power_off;
1415
+
1416
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
1417
+ sd->internal_ops = &SC2355_internal_ops;
1418
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
1419
+ V4L2_SUBDEV_FL_HAS_EVENTS;
1420
+#endif
1421
+#if defined(CONFIG_MEDIA_CONTROLLER)
1422
+ SC2355->pad.flags = MEDIA_PAD_FL_SOURCE;
1423
+ sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
1424
+ ret = media_entity_pads_init(&sd->entity, 1, &SC2355->pad);
1425
+ if (ret < 0)
1426
+ goto err_power_off;
1427
+#endif
1428
+
1429
+ memset(facing, 0, sizeof(facing));
1430
+ if (strcmp(SC2355->module_facing, "back") == 0)
1431
+ facing[0] = 'b';
1432
+ else
1433
+ facing[0] = 'f';
1434
+
1435
+ snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s",
1436
+ SC2355->module_index, facing,
1437
+ SC2355_NAME, dev_name(sd->dev));
1438
+ ret = v4l2_async_register_subdev_sensor_common(sd);
1439
+ if (ret) {
1440
+ dev_err(dev, "v4l2 async register subdev failed\n");
1441
+ goto err_clean_entity;
1442
+ }
1443
+
1444
+ pm_runtime_set_active(dev);
1445
+ pm_runtime_enable(dev);
1446
+ pm_runtime_idle(dev);
1447
+
1448
+ return 0;
1449
+
1450
+err_clean_entity:
1451
+#if defined(CONFIG_MEDIA_CONTROLLER)
1452
+ media_entity_cleanup(&sd->entity);
1453
+#endif
1454
+err_power_off:
1455
+ __SC2355_power_off(SC2355);
1456
+err_free_handler:
1457
+ v4l2_ctrl_handler_free(&SC2355->ctrl_handler);
1458
+err_destroy_mutex:
1459
+ mutex_destroy(&SC2355->mutex);
1460
+
1461
+ return ret;
1462
+}
1463
+
1464
+static int SC2355_remove(struct i2c_client *client)
1465
+{
1466
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
1467
+ struct SC2355 *SC2355 = to_SC2355(sd);
1468
+
1469
+ v4l2_async_unregister_subdev(sd);
1470
+#if defined(CONFIG_MEDIA_CONTROLLER)
1471
+ media_entity_cleanup(&sd->entity);
1472
+#endif
1473
+ v4l2_ctrl_handler_free(&SC2355->ctrl_handler);
1474
+ mutex_destroy(&SC2355->mutex);
1475
+
1476
+ pm_runtime_disable(&client->dev);
1477
+ if (!pm_runtime_status_suspended(&client->dev))
1478
+ __SC2355_power_off(SC2355);
1479
+ pm_runtime_set_suspended(&client->dev);
1480
+
1481
+ return 0;
1482
+}
1483
+
1484
+#if IS_ENABLED(CONFIG_OF)
1485
+static const struct of_device_id SC2355_of_match[] = {
1486
+ { .compatible = "smartsens,sc2355" },
1487
+ {},
1488
+};
1489
+MODULE_DEVICE_TABLE(of, SC2355_of_match);
1490
+#endif
1491
+
1492
+static const struct i2c_device_id SC2355_match_id[] = {
1493
+ { "smartsens,sc2355", 0 },
1494
+ { },
1495
+};
1496
+
1497
+static struct i2c_driver SC2355_i2c_driver = {
1498
+ .driver = {
1499
+ .name = SC2355_NAME,
1500
+ .pm = &SC2355_pm_ops,
1501
+ .of_match_table = of_match_ptr(SC2355_of_match),
1502
+ },
1503
+ .probe = &SC2355_probe,
1504
+ .remove = &SC2355_remove,
1505
+ .id_table = SC2355_match_id,
1506
+};
1507
+
1508
+static int __init sensor_mod_init(void)
1509
+{
1510
+ return i2c_add_driver(&SC2355_i2c_driver);
1511
+}
1512
+
1513
+static void __exit sensor_mod_exit(void)
1514
+{
1515
+ i2c_del_driver(&SC2355_i2c_driver);
1516
+}
1517
+
1518
+device_initcall_sync(sensor_mod_init);
1519
+module_exit(sensor_mod_exit);
1520
+
1521
+MODULE_DESCRIPTION("Smartsens SC2355 sensor driver");
1522
+MODULE_LICENSE("GPL");