hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/media/i2c/sc200ai.c
....@@ -33,6 +33,7 @@
3333 #include <media/v4l2-ctrls.h>
3434 #include <media/v4l2-subdev.h>
3535 #include <linux/pinctrl/consumer.h>
36
+#include "../platform/rockchip/isp/rkisp_tb_helper.h"
3637
3738 #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x07)
3839
....@@ -46,6 +47,7 @@
4647
4748 #define PIXEL_RATE_WITH_371M_10BIT (SC200AI_LINK_FREQ_371 * 2 * \
4849 SC200AI_LANES / SC200AI_BITS_PER_SAMPLE)
50
+
4951 #define SC200AI_XVCLK_FREQ 27000000
5052
5153 #define CHIP_ID 0xcb1c
....@@ -125,14 +127,6 @@
125127
126128 #define SC200AI_NUM_SUPPLIES ARRAY_SIZE(sc200ai_supply_names)
127129
128
-enum sc200ai_max_pad {
129
- PAD0, /* link to isp */
130
- PAD1, /* link to csi wr0 | hdr x2:L x3:M */
131
- PAD2, /* link to csi wr1 | hdr x3:L */
132
- PAD3, /* link to csi wr2 | hdr x2:M x3:S */
133
- PAD_MAX,
134
-};
135
-
136130 struct regval {
137131 u16 addr;
138132 u8 val;
....@@ -172,6 +166,7 @@
172166 struct v4l2_ctrl *vblank;
173167 struct v4l2_ctrl *test_pattern;
174168 struct mutex mutex;
169
+ struct v4l2_fract cur_fps;
175170 bool streaming;
176171 bool power_on;
177172 const struct sc200ai_mode *cur_mode;
....@@ -181,6 +176,8 @@
181176 const char *len_name;
182177 u32 cur_vts;
183178 bool has_init_exp;
179
+ bool is_thunderboot;
180
+ bool is_first_streamoff;
184181 struct preisp_hdrae_exp_s init_hdrae_exp;
185182 };
186183
....@@ -195,10 +192,10 @@
195192
196193 /*
197194 * Xclk 24Mhz
198
- * max_framerate 90fps
195
+ * max_framerate 60fps
199196 * mipi_datarate per lane 1008Mbps, 4lane
200197 */
201
-static const struct regval sc200ai_linear_10_1920x1080_regs[] = {
198
+static const struct regval sc200ai_linear_10_1920x1080_60fps_regs[] = {
202199 {0x0103, 0x01},
203200 {0x0100, 0x00},
204201 {0x36e9, 0x80},
....@@ -338,6 +335,113 @@
338335 /*
339336 * Xclk 27Mhz
340337 * max_framerate 30fps
338
+ * mipi_datarate per lane 371.25Mbps, 2lane
339
+ */
340
+static const struct regval sc200ai_linear_10_1920x1080_30fps_regs[] = {
341
+ {0x0103, 0x01},
342
+ {0x0100, 0x00},
343
+ {0x36e9, 0x80},
344
+ {0x36f9, 0x80},
345
+ {0x301f, 0x03},
346
+ //HTS=1100*2=2200
347
+ {0x320c, 0x04},
348
+ {0x320d, 0x4c},
349
+ //VTS=1125
350
+ {0x320e, 0x04},
351
+ {0x320f, 0x65},
352
+ {0x3243, 0x01},
353
+ {0x3248, 0x02},
354
+ {0x3249, 0x09},
355
+ {0x3253, 0x08},
356
+ {0x3271, 0x0a},
357
+ {0x3301, 0x20},
358
+ {0x3304, 0x40},
359
+ {0x3306, 0x32},
360
+ {0x330b, 0x88},
361
+ {0x330f, 0x02},
362
+ {0x331e, 0x39},
363
+ {0x3333, 0x10},
364
+ {0x3621, 0xe8},
365
+ {0x3622, 0x16},
366
+ {0x3637, 0x1b},
367
+ {0x363a, 0x1f},
368
+ {0x363b, 0xc6},
369
+ {0x363c, 0x0e},
370
+ {0x3670, 0x0a},
371
+ {0x3674, 0x82},
372
+ {0x3675, 0x76},
373
+ {0x3676, 0x78},
374
+ {0x367c, 0x48},
375
+ {0x367d, 0x58},
376
+ {0x3690, 0x34},
377
+ {0x3691, 0x33},
378
+ {0x3692, 0x44},
379
+ {0x369c, 0x40},
380
+ {0x369d, 0x48},
381
+ {0x3901, 0x02},
382
+ {0x3904, 0x04},
383
+ {0x3908, 0x41},
384
+ {0x391d, 0x14},
385
+ {0x391f, 0x18},
386
+ {0x3e01, 0x8c},
387
+ {0x3e02, 0x20},
388
+ {0x3e16, 0x00},
389
+ {0x3e17, 0x80},
390
+ {0x3f09, 0x48},
391
+ {0x5787, 0x10},
392
+ {0x5788, 0x06},
393
+ {0x578a, 0x10},
394
+ {0x578b, 0x06},
395
+ {0x5790, 0x10},
396
+ {0x5791, 0x10},
397
+ {0x5792, 0x00},
398
+ {0x5793, 0x10},
399
+ {0x5794, 0x10},
400
+ {0x5795, 0x00},
401
+ {0x5799, 0x00},
402
+ {0x57c7, 0x10},
403
+ {0x57c8, 0x06},
404
+ {0x57ca, 0x10},
405
+ {0x57cb, 0x06},
406
+ {0x57d1, 0x10},
407
+ {0x57d4, 0x10},
408
+ {0x57d9, 0x00},
409
+ {0x59e0, 0x60},
410
+ {0x59e1, 0x08},
411
+ {0x59e2, 0x3f},
412
+ {0x59e3, 0x18},
413
+ {0x59e4, 0x18},
414
+ {0x59e5, 0x3f},
415
+ {0x59e6, 0x06},
416
+ {0x59e7, 0x02},
417
+ {0x59e8, 0x38},
418
+ {0x59e9, 0x10},
419
+ {0x59ea, 0x0c},
420
+ {0x59eb, 0x10},
421
+ {0x59ec, 0x04},
422
+ {0x59ed, 0x02},
423
+ {0x59ee, 0xa0},
424
+ {0x59ef, 0x08},
425
+ {0x59f4, 0x18},
426
+ {0x59f5, 0x10},
427
+ {0x59f6, 0x0c},
428
+ {0x59f7, 0x10},
429
+ {0x59f8, 0x06},
430
+ {0x59f9, 0x02},
431
+ {0x59fa, 0x18},
432
+ {0x59fb, 0x10},
433
+ {0x59fc, 0x0c},
434
+ {0x59fd, 0x10},
435
+ {0x59fe, 0x04},
436
+ {0x59ff, 0x02},
437
+ {0x36e9, 0x20},
438
+ {0x36f9, 0x27},
439
+ {REG_NULL, 0x00},
440
+};
441
+
442
+/*
443
+ * Xclk 27Mhz
444
+ * max_framerate 30fps
341445 * mipi_datarate per lane 742.5Mbps, HDR 2lane
342446 */
343447 static const struct regval sc200ai_hdr_10_1920x1080_regs[] = {
....@@ -346,8 +450,12 @@
346450 {0x36e9, 0x80},
347451 {0x36f9, 0x80},
348452 {0x301f, 0x02},
453
+ //HTS=1100*2=2200
454
+ {0x320c, 0x04},
455
+ {0x320d, 0x4c},
456
+ //VTS =2252
349457 {0x320e, 0x08},
350
- {0x320f, 0xca},
458
+ {0x320f, 0xcc},
351459 {0x3220, 0x53},
352460 {0x3243, 0x01},
353461 {0x3248, 0x02},
....@@ -372,9 +480,11 @@
372480 {0x331f, 0x61},
373481 {0x3320, 0x07},
374482 {0x3333, 0x10},
483
+ {0x3347, 0x77},
375484 {0x334c, 0x08},
376485 {0x3356, 0x09},
377486 {0x3364, 0x17},
487
+ {0x336c, 0xcc},
378488 {0x3390, 0x08},
379489 {0x3391, 0x18},
380490 {0x3392, 0x38},
....@@ -431,8 +541,8 @@
431541 {0x3e13, 0x40},
432542 {0x3e16, 0x00},
433543 {0x3e17, 0x80},
434
- {0x3e23, 0x00},
435
- {0x3e24, 0x40},
544
+ {0x3e23, 0x01},
545
+ {0x3e24, 0x9e},
436546 {0x3f09, 0x48},
437547 {0x4816, 0xb1},
438548 {0x4819, 0x09},
....@@ -501,13 +611,27 @@
501611 .height = 1080,
502612 .max_fps = {
503613 .numerator = 10000,
614
+ .denominator = 300000,
615
+ },
616
+ .exp_def = 0x0080,
617
+ .hts_def = 0x44C * 2,
618
+ .vts_def = 0x0465,
619
+ .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
620
+ .reg_list = sc200ai_linear_10_1920x1080_30fps_regs,
621
+ .hdr_mode = NO_HDR,
622
+ .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
623
+ }, {
624
+ .width = 1920,
625
+ .height = 1080,
626
+ .max_fps = {
627
+ .numerator = 10000,
504628 .denominator = 600000,
505629 },
506630 .exp_def = 0x0080,
507631 .hts_def = 0x44C * 2,
508632 .vts_def = 0x0465,
509633 .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
510
- .reg_list = sc200ai_linear_10_1920x1080_regs,
634
+ .reg_list = sc200ai_linear_10_1920x1080_60fps_regs,
511635 .hdr_mode = NO_HDR,
512636 .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
513637 }, {
....@@ -519,7 +643,7 @@
519643 },
520644 .exp_def = 0x0080,
521645 .hts_def = 0x44C * 2,
522
- .vts_def = 0x08CA,
646
+ .vts_def = 0x08CC,
523647 .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
524648 .reg_list = sc200ai_hdr_10_1920x1080_regs,
525649 .hdr_mode = HDR_X2,
....@@ -814,8 +938,8 @@
814938 s_exp_time = s_exp_time * 2;
815939 if (l_exp_time > 4362) //(2250 - 64 - 5) * 2
816940 l_exp_time = 4362;
817
- if (s_exp_time > 118) //(64 - 5) * 2
818
- s_exp_time = 118;
941
+ if (s_exp_time > 404) //(64 - 5) * 2
942
+ s_exp_time = 404;
819943
820944 ret = sc200ai_write_reg(sc200ai->client,
821945 SC200AI_REG_EXPOSURE_H,
....@@ -837,7 +961,6 @@
837961 SC200AI_REG_SEXPOSURE_L,
838962 SC200AI_REG_VALUE_08BIT,
839963 SC200AI_FETCH_EXP_L(s_exp_time));
840
-
841964
842965 ret |= sc200ai_set_gain_reg(sc200ai, l_a_gain, SC200AI_LGAIN);
843966 ret |= sc200ai_set_gain_reg(sc200ai, s_a_gain, SC200AI_SGAIN);
....@@ -902,6 +1025,8 @@
9021025 __v4l2_ctrl_modify_range(sc200ai->vblank, vblank_def,
9031026 SC200AI_VTS_MAX - mode->height,
9041027 1, vblank_def);
1028
+ sc200ai->cur_fps = mode->max_fps;
1029
+ sc200ai->cur_vts = mode->vts_def;
9051030 }
9061031
9071032 mutex_unlock(&sc200ai->mutex);
....@@ -994,14 +1119,15 @@
9941119 struct sc200ai *sc200ai = to_sc200ai(sd);
9951120 const struct sc200ai_mode *mode = sc200ai->cur_mode;
9961121
997
- mutex_lock(&sc200ai->mutex);
998
- fi->interval = mode->max_fps;
999
- mutex_unlock(&sc200ai->mutex);
1122
+ if (sc200ai->streaming)
1123
+ fi->interval = sc200ai->cur_fps;
1124
+ else
1125
+ fi->interval = mode->max_fps;
10001126
10011127 return 0;
10021128 }
10031129
1004
-static int sc200ai_g_mbus_config(struct v4l2_subdev *sd,
1130
+static int sc200ai_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
10051131 struct v4l2_mbus_config *config)
10061132 {
10071133 struct sc200ai *sc200ai = to_sc200ai(sd);
....@@ -1015,7 +1141,7 @@
10151141 if (mode->hdr_mode == HDR_X3)
10161142 val |= V4L2_MBUS_CSI2_CHANNEL_2;
10171143
1018
- config->type = V4L2_MBUS_CSI2;
1144
+ config->type = V4L2_MBUS_CSI2_DPHY;
10191145 config->flags = val;
10201146
10211147 return 0;
....@@ -1031,10 +1157,22 @@
10311157 strlcpy(inf->base.lens, sc200ai->len_name, sizeof(inf->base.lens));
10321158 }
10331159
1160
+static int sc200ai_get_channel_info(struct sc200ai *sc200ai, struct rkmodule_channel_info *ch_info)
1161
+{
1162
+ if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX)
1163
+ return -EINVAL;
1164
+ ch_info->vc = sc200ai->cur_mode->vc[ch_info->index];
1165
+ ch_info->width = sc200ai->cur_mode->width;
1166
+ ch_info->height = sc200ai->cur_mode->height;
1167
+ ch_info->bus_fmt = sc200ai->cur_mode->bus_fmt;
1168
+ return 0;
1169
+}
1170
+
10341171 static long sc200ai_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
10351172 {
10361173 struct sc200ai *sc200ai = to_sc200ai(sd);
10371174 struct rkmodule_hdr_cfg *hdr;
1175
+ struct rkmodule_channel_info *ch_info;
10381176 u32 i, h, w;
10391177 long ret = 0;
10401178 u32 stream = 0;
....@@ -1071,6 +1209,8 @@
10711209 __v4l2_ctrl_modify_range(sc200ai->hblank, w, w, 1, w);
10721210 __v4l2_ctrl_modify_range(sc200ai->vblank, h,
10731211 SC200AI_VTS_MAX - sc200ai->cur_mode->height, 1, h);
1212
+ sc200ai->cur_fps = sc200ai->cur_mode->max_fps;
1213
+ sc200ai->cur_vts = sc200ai->cur_mode->vts_def;
10741214 }
10751215 break;
10761216 case PREISP_CMD_SET_HDRAE_EXP:
....@@ -1086,6 +1226,10 @@
10861226 else
10871227 ret = sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE,
10881228 SC200AI_REG_VALUE_08BIT, SC200AI_MODE_SW_STANDBY);
1229
+ break;
1230
+ case RKMODULE_GET_CHANNEL_INFO:
1231
+ ch_info = (struct rkmodule_channel_info *)arg;
1232
+ ret = sc200ai_get_channel_info(sc200ai, ch_info);
10891233 break;
10901234 default:
10911235 ret = -ENOIOCTLCMD;
....@@ -1104,6 +1248,7 @@
11041248 struct rkmodule_awb_cfg *cfg;
11051249 struct rkmodule_hdr_cfg *hdr;
11061250 struct preisp_hdrae_exp_s *hdrae;
1251
+ struct rkmodule_channel_info *ch_info;
11071252 long ret;
11081253 u32 stream = 0;
11091254
....@@ -1116,8 +1261,11 @@
11161261 }
11171262
11181263 ret = sc200ai_ioctl(sd, cmd, inf);
1119
- if (!ret)
1264
+ if (!ret) {
11201265 ret = copy_to_user(up, inf, sizeof(*inf));
1266
+ if (ret)
1267
+ ret = -EFAULT;
1268
+ }
11211269 kfree(inf);
11221270 break;
11231271 case RKMODULE_AWB_CFG:
....@@ -1130,6 +1278,8 @@
11301278 ret = copy_from_user(cfg, up, sizeof(*cfg));
11311279 if (!ret)
11321280 ret = sc200ai_ioctl(sd, cmd, cfg);
1281
+ else
1282
+ ret = -EFAULT;
11331283 kfree(cfg);
11341284 break;
11351285 case RKMODULE_GET_HDR_CFG:
....@@ -1140,8 +1290,11 @@
11401290 }
11411291
11421292 ret = sc200ai_ioctl(sd, cmd, hdr);
1143
- if (!ret)
1293
+ if (!ret) {
11441294 ret = copy_to_user(up, hdr, sizeof(*hdr));
1295
+ if (ret)
1296
+ ret = -EFAULT;
1297
+ }
11451298 kfree(hdr);
11461299 break;
11471300 case RKMODULE_SET_HDR_CFG:
....@@ -1154,6 +1307,8 @@
11541307 ret = copy_from_user(hdr, up, sizeof(*hdr));
11551308 if (!ret)
11561309 ret = sc200ai_ioctl(sd, cmd, hdr);
1310
+ else
1311
+ ret = -EFAULT;
11571312 kfree(hdr);
11581313 break;
11591314 case PREISP_CMD_SET_HDRAE_EXP:
....@@ -1166,12 +1321,31 @@
11661321 ret = copy_from_user(hdrae, up, sizeof(*hdrae));
11671322 if (!ret)
11681323 ret = sc200ai_ioctl(sd, cmd, hdrae);
1324
+ else
1325
+ ret = -EFAULT;
11691326 kfree(hdrae);
11701327 break;
11711328 case RKMODULE_SET_QUICK_STREAM:
11721329 ret = copy_from_user(&stream, up, sizeof(u32));
11731330 if (!ret)
11741331 ret = sc200ai_ioctl(sd, cmd, &stream);
1332
+ else
1333
+ ret = -EFAULT;
1334
+ break;
1335
+ case RKMODULE_GET_CHANNEL_INFO:
1336
+ ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
1337
+ if (!ch_info) {
1338
+ ret = -ENOMEM;
1339
+ return ret;
1340
+ }
1341
+
1342
+ ret = sc200ai_ioctl(sd, cmd, ch_info);
1343
+ if (!ret) {
1344
+ ret = copy_to_user(up, ch_info, sizeof(*ch_info));
1345
+ if (ret)
1346
+ ret = -EFAULT;
1347
+ }
1348
+ kfree(ch_info);
11751349 break;
11761350 default:
11771351 ret = -ENOIOCTLCMD;
....@@ -1186,21 +1360,30 @@
11861360 {
11871361 int ret;
11881362
1189
- ret = sc200ai_write_array(sc200ai->client, sc200ai->cur_mode->reg_list);
1190
- if (ret)
1191
- return ret;
1192
-
1193
- /* In case these controls are set before streaming */
1194
- ret = __v4l2_ctrl_handler_setup(&sc200ai->ctrl_handler);
1195
- if (ret)
1196
- return ret;
1197
- if (sc200ai->has_init_exp && sc200ai->cur_mode->hdr_mode != NO_HDR) {
1198
- ret = sc200ai_ioctl(&sc200ai->subdev, PREISP_CMD_SET_HDRAE_EXP,
1199
- &sc200ai->init_hdrae_exp);
1200
- if (ret) {
1201
- dev_err(&sc200ai->client->dev,
1202
- "init exp fail in hdr mode\n");
1363
+ dev_info(&sc200ai->client->dev,
1364
+ "%dx%d@%d, mode %d, vts 0x%x\n",
1365
+ sc200ai->cur_mode->width,
1366
+ sc200ai->cur_mode->height,
1367
+ sc200ai->cur_fps.denominator / sc200ai->cur_fps.numerator,
1368
+ sc200ai->cur_mode->hdr_mode,
1369
+ sc200ai->cur_vts);
1370
+ if (!sc200ai->is_thunderboot) {
1371
+ ret = sc200ai_write_array(sc200ai->client, sc200ai->cur_mode->reg_list);
1372
+ if (ret)
12031373 return ret;
1374
+
1375
+ /* In case these controls are set before streaming */
1376
+ ret = __v4l2_ctrl_handler_setup(&sc200ai->ctrl_handler);
1377
+ if (ret)
1378
+ return ret;
1379
+ if (sc200ai->has_init_exp && sc200ai->cur_mode->hdr_mode != NO_HDR) {
1380
+ ret = sc200ai_ioctl(&sc200ai->subdev, PREISP_CMD_SET_HDRAE_EXP,
1381
+ &sc200ai->init_hdrae_exp);
1382
+ if (ret) {
1383
+ dev_err(&sc200ai->client->dev,
1384
+ "init exp fail in hdr mode\n");
1385
+ return ret;
1386
+ }
12041387 }
12051388 }
12061389
....@@ -1211,10 +1394,15 @@
12111394 static int __sc200ai_stop_stream(struct sc200ai *sc200ai)
12121395 {
12131396 sc200ai->has_init_exp = false;
1397
+ if (sc200ai->is_thunderboot) {
1398
+ sc200ai->is_first_streamoff = true;
1399
+ pm_runtime_put(&sc200ai->client->dev);
1400
+ }
12141401 return sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE,
12151402 SC200AI_REG_VALUE_08BIT, SC200AI_MODE_SW_STANDBY);
12161403 }
12171404
1405
+static int __sc200ai_power_on(struct sc200ai *sc200ai);
12181406 static int sc200ai_s_stream(struct v4l2_subdev *sd, int on)
12191407 {
12201408 struct sc200ai *sc200ai = to_sc200ai(sd);
....@@ -1227,6 +1415,10 @@
12271415 goto unlock_and_return;
12281416
12291417 if (on) {
1418
+ if (sc200ai->is_thunderboot && rkisp_tb_get_state() == RKISP_TB_NG) {
1419
+ sc200ai->is_thunderboot = false;
1420
+ __sc200ai_power_on(sc200ai);
1421
+ }
12301422 ret = pm_runtime_get_sync(&client->dev);
12311423 if (ret < 0) {
12321424 pm_runtime_put_noidle(&client->dev);
....@@ -1271,11 +1463,13 @@
12711463 goto unlock_and_return;
12721464 }
12731465
1274
- ret = sc200ai_write_array(sc200ai->client, sc200ai_global_regs);
1275
- if (ret) {
1276
- v4l2_err(sd, "could not set init registers\n");
1277
- pm_runtime_put_noidle(&client->dev);
1278
- goto unlock_and_return;
1466
+ if (!sc200ai->is_thunderboot) {
1467
+ ret = sc200ai_write_array(sc200ai->client, sc200ai_global_regs);
1468
+ if (ret) {
1469
+ v4l2_err(sd, "could not set init registers\n");
1470
+ pm_runtime_put_noidle(&client->dev);
1471
+ goto unlock_and_return;
1472
+ }
12791473 }
12801474
12811475 sc200ai->power_on = true;
....@@ -1318,6 +1512,9 @@
13181512 dev_err(dev, "Failed to enable xvclk\n");
13191513 return ret;
13201514 }
1515
+ if (sc200ai->is_thunderboot)
1516
+ return 0;
1517
+
13211518 if (!IS_ERR(sc200ai->reset_gpio))
13221519 gpiod_set_value_cansleep(sc200ai->reset_gpio, 0);
13231520
....@@ -1356,6 +1553,15 @@
13561553 int ret;
13571554 struct device *dev = &sc200ai->client->dev;
13581555
1556
+ clk_disable_unprepare(sc200ai->xvclk);
1557
+ if (sc200ai->is_thunderboot) {
1558
+ if (sc200ai->is_first_streamoff) {
1559
+ sc200ai->is_thunderboot = false;
1560
+ sc200ai->is_first_streamoff = false;
1561
+ } else {
1562
+ return;
1563
+ }
1564
+ }
13591565 if (!IS_ERR(sc200ai->pwdn_gpio))
13601566 gpiod_set_value_cansleep(sc200ai->pwdn_gpio, 0);
13611567 clk_disable_unprepare(sc200ai->xvclk);
....@@ -1449,7 +1655,6 @@
14491655 static const struct v4l2_subdev_video_ops sc200ai_video_ops = {
14501656 .s_stream = sc200ai_s_stream,
14511657 .g_frame_interval = sc200ai_g_frame_interval,
1452
- .g_mbus_config = sc200ai_g_mbus_config,
14531658 };
14541659
14551660 static const struct v4l2_subdev_pad_ops sc200ai_pad_ops = {
....@@ -1458,6 +1663,7 @@
14581663 .enum_frame_interval = sc200ai_enum_frame_interval,
14591664 .get_fmt = sc200ai_get_fmt,
14601665 .set_fmt = sc200ai_set_fmt,
1666
+ .get_mbus_config = sc200ai_g_mbus_config,
14611667 };
14621668
14631669 static const struct v4l2_subdev_ops sc200ai_subdev_ops = {
....@@ -1465,6 +1671,14 @@
14651671 .video = &sc200ai_video_ops,
14661672 .pad = &sc200ai_pad_ops,
14671673 };
1674
+
1675
+static void sc200ai_modify_fps_info(struct sc200ai *sc200ai)
1676
+{
1677
+ const struct sc200ai_mode *mode = sc200ai->cur_mode;
1678
+
1679
+ sc200ai->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def/
1680
+ sc200ai->cur_vts;
1681
+}
14681682
14691683 static int sc200ai_set_ctrl(struct v4l2_ctrl *ctrl)
14701684 {
....@@ -1528,7 +1742,10 @@
15281742 SC200AI_REG_VALUE_08BIT,
15291743 (ctrl->val + sc200ai->cur_mode->height)
15301744 & 0xff);
1531
- sc200ai->cur_vts = ctrl->val + sc200ai->cur_mode->height;
1745
+ if (!ret)
1746
+ sc200ai->cur_vts = ctrl->val + sc200ai->cur_mode->height;
1747
+ if (sc200ai->cur_vts != sc200ai->cur_mode->vts_def)
1748
+ sc200ai_modify_fps_info(sc200ai);
15321749 break;
15331750 case V4L2_CID_TEST_PATTERN:
15341751 ret = sc200ai_enable_test_pattern(sc200ai, ctrl->val);
....@@ -1591,12 +1808,14 @@
15911808 h_blank, h_blank, 1, h_blank);
15921809 if (sc200ai->hblank)
15931810 sc200ai->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1811
+ sc200ai->cur_fps = mode->max_fps;
15941812 vblank_def = mode->vts_def - mode->height;
1813
+ sc200ai->cur_vts = mode->vts_def;
15951814 sc200ai->vblank = v4l2_ctrl_new_std(handler, &sc200ai_ctrl_ops,
15961815 V4L2_CID_VBLANK, vblank_def,
15971816 SC200AI_VTS_MAX - mode->height,
15981817 1, vblank_def);
1599
- exposure_max = mode->vts_def - 4;
1818
+ exposure_max = 2 * mode->vts_def - 8;
16001819 sc200ai->exposure = v4l2_ctrl_new_std(handler, &sc200ai_ctrl_ops,
16011820 V4L2_CID_EXPOSURE, SC200AI_EXPOSURE_MIN,
16021821 exposure_max, SC200AI_EXPOSURE_STEP,
....@@ -1641,6 +1860,11 @@
16411860 u32 id = 0;
16421861 int ret;
16431862
1863
+ if (sc200ai->is_thunderboot) {
1864
+ dev_info(dev, "Enable thunderboot mode, skip sensor id check\n");
1865
+ return 0;
1866
+ }
1867
+
16441868 ret = sc200ai_read_reg(client, SC200AI_REG_CHIP_ID,
16451869 SC200AI_REG_VALUE_16BIT, &id);
16461870 if (id != CHIP_ID) {
....@@ -1665,6 +1889,132 @@
16651889 sc200ai->supplies);
16661890 }
16671891
1892
+#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP
1893
+static u32 rk_cam_hdr;
1894
+static u32 rk_cam_w;
1895
+static u32 rk_cam_h;
1896
+static u32 rk_cam_fps;
1897
+
1898
+static int __init __maybe_unused rk_cam_hdr_setup(char *str)
1899
+{
1900
+ int ret = 0;
1901
+ unsigned long val = 0;
1902
+
1903
+ ret = kstrtoul(str, 0, &val);
1904
+ if (!ret)
1905
+ rk_cam_hdr = (u32)val;
1906
+ else
1907
+ pr_err("get rk_cam_hdr fail\n");
1908
+ return 1;
1909
+}
1910
+
1911
+static int __init __maybe_unused rk_cam_w_setup(char *str)
1912
+{
1913
+ int ret = 0;
1914
+ unsigned long val = 0;
1915
+
1916
+ ret = kstrtoul(str, 0, &val);
1917
+ if (!ret)
1918
+ rk_cam_w = (u32)val;
1919
+ else
1920
+ pr_err("get rk_cam_w fail\n");
1921
+ return 1;
1922
+}
1923
+
1924
+static int __init __maybe_unused rk_cam_h_setup(char *str)
1925
+{
1926
+ int ret = 0;
1927
+ unsigned long val = 0;
1928
+
1929
+ ret = kstrtoul(str, 0, &val);
1930
+ if (!ret)
1931
+ rk_cam_h = (u32)val;
1932
+ else
1933
+ pr_err("get rk_cam_h fail\n");
1934
+ return 1;
1935
+}
1936
+
1937
+static int __init __maybe_unused rk_cam_fps_setup(char *str)
1938
+{
1939
+ int ret = 0;
1940
+ unsigned long val = 0;
1941
+
1942
+ ret = kstrtoul(str, 0, &val);
1943
+ if (!ret)
1944
+ rk_cam_fps = (u32)val;
1945
+ else
1946
+ pr_err("get rk_cam_fps fail\n");
1947
+ return 1;
1948
+}
1949
+
1950
+__setup("rk_cam_hdr=", rk_cam_hdr_setup);
1951
+__setup("rk_cam_w=", rk_cam_w_setup);
1952
+__setup("rk_cam_h=", rk_cam_h_setup);
1953
+__setup("rk_cam_fps=", rk_cam_fps_setup);
1954
+
1955
+static void find_terminal_resolution(struct sc200ai *sc200ai)
1956
+{
1957
+ int i = 0;
1958
+ const struct sc200ai_mode *mode = NULL;
1959
+ const struct sc200ai_mode *fit_mode = NULL;
1960
+ u32 cur_fps = 0;
1961
+ u32 dst_fps = 0;
1962
+ u32 tmp_fps = 0;
1963
+
1964
+ if (rk_cam_w == 0 || rk_cam_h == 0 ||
1965
+ rk_cam_fps == 0)
1966
+ goto err_find_res;
1967
+
1968
+ dst_fps = rk_cam_fps;
1969
+ for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
1970
+ mode = &supported_modes[i];
1971
+ cur_fps = mode->max_fps.denominator / mode->max_fps.numerator;
1972
+ if (mode->width == rk_cam_w && mode->height == rk_cam_h &&
1973
+ mode->hdr_mode == rk_cam_hdr) {
1974
+ if (cur_fps == dst_fps) {
1975
+ sc200ai->cur_mode = mode;
1976
+ return;
1977
+ }
1978
+ if (cur_fps >= dst_fps) {
1979
+ if (fit_mode) {
1980
+ tmp_fps = fit_mode->max_fps.denominator / fit_mode->max_fps.numerator;
1981
+ if (tmp_fps - dst_fps > cur_fps - dst_fps)
1982
+ fit_mode = mode;
1983
+ } else {
1984
+ fit_mode = mode;
1985
+ }
1986
+ }
1987
+ }
1988
+ }
1989
+ if (fit_mode) {
1990
+ sc200ai->cur_mode = fit_mode;
1991
+ return;
1992
+ }
1993
+err_find_res:
1994
+ dev_err(&sc200ai->client->dev, "not match %dx%d@%dfps mode %d\n!",
1995
+ rk_cam_w, rk_cam_h, dst_fps, rk_cam_hdr);
1996
+ sc200ai->cur_mode = &supported_modes[0];
1997
+}
1998
+#else
1999
+static void find_terminal_resolution(struct sc200ai *sc200ai)
2000
+{
2001
+ u32 hdr_mode = 0;
2002
+ struct device_node *node = sc200ai->client->dev.of_node;
2003
+ int i = 0;
2004
+
2005
+ of_property_read_u32(node, OF_CAMERA_HDR_MODE, &hdr_mode);
2006
+ for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
2007
+ if (hdr_mode == supported_modes[i].hdr_mode) {
2008
+ sc200ai->cur_mode = &supported_modes[i];
2009
+ break;
2010
+ }
2011
+ }
2012
+ if (i == ARRAY_SIZE(supported_modes))
2013
+ sc200ai->cur_mode = &supported_modes[0];
2014
+
2015
+}
2016
+#endif
2017
+
16682018 static int sc200ai_probe(struct i2c_client *client,
16692019 const struct i2c_device_id *id)
16702020 {
....@@ -1674,7 +2024,6 @@
16742024 struct v4l2_subdev *sd;
16752025 char facing[2];
16762026 int ret;
1677
- u32 i, hdr_mode = 0;
16782027
16792028 dev_info(dev, "driver version: %02x.%02x.%02x",
16802029 DRIVER_VERSION >> 16,
....@@ -1685,7 +2034,6 @@
16852034 if (!sc200ai)
16862035 return -ENOMEM;
16872036
1688
- of_property_read_u32(node, OF_CAMERA_HDR_MODE, &hdr_mode);
16892037 ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
16902038 &sc200ai->module_index);
16912039 ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
....@@ -1699,15 +2047,10 @@
16992047 return -EINVAL;
17002048 }
17012049
2050
+ sc200ai->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP);
17022051 sc200ai->client = client;
1703
- for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
1704
- if (hdr_mode == supported_modes[i].hdr_mode) {
1705
- sc200ai->cur_mode = &supported_modes[i];
1706
- break;
1707
- }
1708
- }
1709
- if (i == ARRAY_SIZE(supported_modes))
1710
- sc200ai->cur_mode = &supported_modes[0];
2052
+
2053
+ find_terminal_resolution(sc200ai);
17112054
17122055 sc200ai->xvclk = devm_clk_get(dev, "xvclk");
17132056 if (IS_ERR(sc200ai->xvclk)) {
....@@ -1715,11 +2058,11 @@
17152058 return -EINVAL;
17162059 }
17172060
1718
- sc200ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
2061
+ sc200ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
17192062 if (IS_ERR(sc200ai->reset_gpio))
17202063 dev_warn(dev, "Failed to get reset-gpios\n");
17212064
1722
- sc200ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
2065
+ sc200ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_ASIS);
17232066 if (IS_ERR(sc200ai->pwdn_gpio))
17242067 dev_warn(dev, "Failed to get pwdn-gpios\n");
17252068
....@@ -1792,7 +2135,10 @@
17922135
17932136 pm_runtime_set_active(dev);
17942137 pm_runtime_enable(dev);
1795
- pm_runtime_idle(dev);
2138
+ if (sc200ai->is_thunderboot)
2139
+ pm_runtime_get_sync(dev);
2140
+ else
2141
+ pm_runtime_idle(dev);
17962142
17972143 return 0;
17982144
....@@ -1864,8 +2210,12 @@
18642210 i2c_del_driver(&sc200ai_i2c_driver);
18652211 }
18662212
2213
+#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC)
2214
+subsys_initcall(sensor_mod_init);
2215
+#else
18672216 device_initcall_sync(sensor_mod_init);
2217
+#endif
18682218 module_exit(sensor_mod_exit);
18692219
18702220 MODULE_DESCRIPTION("smartsens sc200ai sensor driver");
1871
-MODULE_LICENSE("GPL v2");
2221
+MODULE_LICENSE("GPL");