.. | .. |
---|
33 | 33 | #include <media/v4l2-ctrls.h> |
---|
34 | 34 | #include <media/v4l2-subdev.h> |
---|
35 | 35 | #include <linux/pinctrl/consumer.h> |
---|
| 36 | +#include "../platform/rockchip/isp/rkisp_tb_helper.h" |
---|
36 | 37 | |
---|
37 | 38 | #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x07) |
---|
38 | 39 | |
---|
.. | .. |
---|
46 | 47 | |
---|
47 | 48 | #define PIXEL_RATE_WITH_371M_10BIT (SC200AI_LINK_FREQ_371 * 2 * \ |
---|
48 | 49 | SC200AI_LANES / SC200AI_BITS_PER_SAMPLE) |
---|
| 50 | + |
---|
49 | 51 | #define SC200AI_XVCLK_FREQ 27000000 |
---|
50 | 52 | |
---|
51 | 53 | #define CHIP_ID 0xcb1c |
---|
.. | .. |
---|
125 | 127 | |
---|
126 | 128 | #define SC200AI_NUM_SUPPLIES ARRAY_SIZE(sc200ai_supply_names) |
---|
127 | 129 | |
---|
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 | | - |
---|
136 | 130 | struct regval { |
---|
137 | 131 | u16 addr; |
---|
138 | 132 | u8 val; |
---|
.. | .. |
---|
172 | 166 | struct v4l2_ctrl *vblank; |
---|
173 | 167 | struct v4l2_ctrl *test_pattern; |
---|
174 | 168 | struct mutex mutex; |
---|
| 169 | + struct v4l2_fract cur_fps; |
---|
175 | 170 | bool streaming; |
---|
176 | 171 | bool power_on; |
---|
177 | 172 | const struct sc200ai_mode *cur_mode; |
---|
.. | .. |
---|
181 | 176 | const char *len_name; |
---|
182 | 177 | u32 cur_vts; |
---|
183 | 178 | bool has_init_exp; |
---|
| 179 | + bool is_thunderboot; |
---|
| 180 | + bool is_first_streamoff; |
---|
184 | 181 | struct preisp_hdrae_exp_s init_hdrae_exp; |
---|
185 | 182 | }; |
---|
186 | 183 | |
---|
.. | .. |
---|
195 | 192 | |
---|
196 | 193 | /* |
---|
197 | 194 | * Xclk 24Mhz |
---|
198 | | - * max_framerate 90fps |
---|
| 195 | + * max_framerate 60fps |
---|
199 | 196 | * mipi_datarate per lane 1008Mbps, 4lane |
---|
200 | 197 | */ |
---|
201 | | -static const struct regval sc200ai_linear_10_1920x1080_regs[] = { |
---|
| 198 | +static const struct regval sc200ai_linear_10_1920x1080_60fps_regs[] = { |
---|
202 | 199 | {0x0103, 0x01}, |
---|
203 | 200 | {0x0100, 0x00}, |
---|
204 | 201 | {0x36e9, 0x80}, |
---|
.. | .. |
---|
338 | 335 | /* |
---|
339 | 336 | * Xclk 27Mhz |
---|
340 | 337 | * 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 |
---|
341 | 445 | * mipi_datarate per lane 742.5Mbps, HDR 2lane |
---|
342 | 446 | */ |
---|
343 | 447 | static const struct regval sc200ai_hdr_10_1920x1080_regs[] = { |
---|
.. | .. |
---|
346 | 450 | {0x36e9, 0x80}, |
---|
347 | 451 | {0x36f9, 0x80}, |
---|
348 | 452 | {0x301f, 0x02}, |
---|
| 453 | + //HTS=1100*2=2200 |
---|
| 454 | + {0x320c, 0x04}, |
---|
| 455 | + {0x320d, 0x4c}, |
---|
| 456 | + //VTS =2252 |
---|
349 | 457 | {0x320e, 0x08}, |
---|
350 | | - {0x320f, 0xca}, |
---|
| 458 | + {0x320f, 0xcc}, |
---|
351 | 459 | {0x3220, 0x53}, |
---|
352 | 460 | {0x3243, 0x01}, |
---|
353 | 461 | {0x3248, 0x02}, |
---|
.. | .. |
---|
372 | 480 | {0x331f, 0x61}, |
---|
373 | 481 | {0x3320, 0x07}, |
---|
374 | 482 | {0x3333, 0x10}, |
---|
| 483 | + {0x3347, 0x77}, |
---|
375 | 484 | {0x334c, 0x08}, |
---|
376 | 485 | {0x3356, 0x09}, |
---|
377 | 486 | {0x3364, 0x17}, |
---|
| 487 | + {0x336c, 0xcc}, |
---|
378 | 488 | {0x3390, 0x08}, |
---|
379 | 489 | {0x3391, 0x18}, |
---|
380 | 490 | {0x3392, 0x38}, |
---|
.. | .. |
---|
431 | 541 | {0x3e13, 0x40}, |
---|
432 | 542 | {0x3e16, 0x00}, |
---|
433 | 543 | {0x3e17, 0x80}, |
---|
434 | | - {0x3e23, 0x00}, |
---|
435 | | - {0x3e24, 0x40}, |
---|
| 544 | + {0x3e23, 0x01}, |
---|
| 545 | + {0x3e24, 0x9e}, |
---|
436 | 546 | {0x3f09, 0x48}, |
---|
437 | 547 | {0x4816, 0xb1}, |
---|
438 | 548 | {0x4819, 0x09}, |
---|
.. | .. |
---|
501 | 611 | .height = 1080, |
---|
502 | 612 | .max_fps = { |
---|
503 | 613 | .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, |
---|
504 | 628 | .denominator = 600000, |
---|
505 | 629 | }, |
---|
506 | 630 | .exp_def = 0x0080, |
---|
507 | 631 | .hts_def = 0x44C * 2, |
---|
508 | 632 | .vts_def = 0x0465, |
---|
509 | 633 | .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, |
---|
510 | | - .reg_list = sc200ai_linear_10_1920x1080_regs, |
---|
| 634 | + .reg_list = sc200ai_linear_10_1920x1080_60fps_regs, |
---|
511 | 635 | .hdr_mode = NO_HDR, |
---|
512 | 636 | .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, |
---|
513 | 637 | }, { |
---|
.. | .. |
---|
519 | 643 | }, |
---|
520 | 644 | .exp_def = 0x0080, |
---|
521 | 645 | .hts_def = 0x44C * 2, |
---|
522 | | - .vts_def = 0x08CA, |
---|
| 646 | + .vts_def = 0x08CC, |
---|
523 | 647 | .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, |
---|
524 | 648 | .reg_list = sc200ai_hdr_10_1920x1080_regs, |
---|
525 | 649 | .hdr_mode = HDR_X2, |
---|
.. | .. |
---|
814 | 938 | s_exp_time = s_exp_time * 2; |
---|
815 | 939 | if (l_exp_time > 4362) //(2250 - 64 - 5) * 2 |
---|
816 | 940 | 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; |
---|
819 | 943 | |
---|
820 | 944 | ret = sc200ai_write_reg(sc200ai->client, |
---|
821 | 945 | SC200AI_REG_EXPOSURE_H, |
---|
.. | .. |
---|
837 | 961 | SC200AI_REG_SEXPOSURE_L, |
---|
838 | 962 | SC200AI_REG_VALUE_08BIT, |
---|
839 | 963 | SC200AI_FETCH_EXP_L(s_exp_time)); |
---|
840 | | - |
---|
841 | 964 | |
---|
842 | 965 | ret |= sc200ai_set_gain_reg(sc200ai, l_a_gain, SC200AI_LGAIN); |
---|
843 | 966 | ret |= sc200ai_set_gain_reg(sc200ai, s_a_gain, SC200AI_SGAIN); |
---|
.. | .. |
---|
902 | 1025 | __v4l2_ctrl_modify_range(sc200ai->vblank, vblank_def, |
---|
903 | 1026 | SC200AI_VTS_MAX - mode->height, |
---|
904 | 1027 | 1, vblank_def); |
---|
| 1028 | + sc200ai->cur_fps = mode->max_fps; |
---|
| 1029 | + sc200ai->cur_vts = mode->vts_def; |
---|
905 | 1030 | } |
---|
906 | 1031 | |
---|
907 | 1032 | mutex_unlock(&sc200ai->mutex); |
---|
.. | .. |
---|
994 | 1119 | struct sc200ai *sc200ai = to_sc200ai(sd); |
---|
995 | 1120 | const struct sc200ai_mode *mode = sc200ai->cur_mode; |
---|
996 | 1121 | |
---|
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; |
---|
1000 | 1126 | |
---|
1001 | 1127 | return 0; |
---|
1002 | 1128 | } |
---|
1003 | 1129 | |
---|
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, |
---|
1005 | 1131 | struct v4l2_mbus_config *config) |
---|
1006 | 1132 | { |
---|
1007 | 1133 | struct sc200ai *sc200ai = to_sc200ai(sd); |
---|
.. | .. |
---|
1015 | 1141 | if (mode->hdr_mode == HDR_X3) |
---|
1016 | 1142 | val |= V4L2_MBUS_CSI2_CHANNEL_2; |
---|
1017 | 1143 | |
---|
1018 | | - config->type = V4L2_MBUS_CSI2; |
---|
| 1144 | + config->type = V4L2_MBUS_CSI2_DPHY; |
---|
1019 | 1145 | config->flags = val; |
---|
1020 | 1146 | |
---|
1021 | 1147 | return 0; |
---|
.. | .. |
---|
1031 | 1157 | strlcpy(inf->base.lens, sc200ai->len_name, sizeof(inf->base.lens)); |
---|
1032 | 1158 | } |
---|
1033 | 1159 | |
---|
| 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 | + |
---|
1034 | 1171 | static long sc200ai_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) |
---|
1035 | 1172 | { |
---|
1036 | 1173 | struct sc200ai *sc200ai = to_sc200ai(sd); |
---|
1037 | 1174 | struct rkmodule_hdr_cfg *hdr; |
---|
| 1175 | + struct rkmodule_channel_info *ch_info; |
---|
1038 | 1176 | u32 i, h, w; |
---|
1039 | 1177 | long ret = 0; |
---|
1040 | 1178 | u32 stream = 0; |
---|
.. | .. |
---|
1071 | 1209 | __v4l2_ctrl_modify_range(sc200ai->hblank, w, w, 1, w); |
---|
1072 | 1210 | __v4l2_ctrl_modify_range(sc200ai->vblank, h, |
---|
1073 | 1211 | 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; |
---|
1074 | 1214 | } |
---|
1075 | 1215 | break; |
---|
1076 | 1216 | case PREISP_CMD_SET_HDRAE_EXP: |
---|
.. | .. |
---|
1086 | 1226 | else |
---|
1087 | 1227 | ret = sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE, |
---|
1088 | 1228 | 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); |
---|
1089 | 1233 | break; |
---|
1090 | 1234 | default: |
---|
1091 | 1235 | ret = -ENOIOCTLCMD; |
---|
.. | .. |
---|
1104 | 1248 | struct rkmodule_awb_cfg *cfg; |
---|
1105 | 1249 | struct rkmodule_hdr_cfg *hdr; |
---|
1106 | 1250 | struct preisp_hdrae_exp_s *hdrae; |
---|
| 1251 | + struct rkmodule_channel_info *ch_info; |
---|
1107 | 1252 | long ret; |
---|
1108 | 1253 | u32 stream = 0; |
---|
1109 | 1254 | |
---|
.. | .. |
---|
1116 | 1261 | } |
---|
1117 | 1262 | |
---|
1118 | 1263 | ret = sc200ai_ioctl(sd, cmd, inf); |
---|
1119 | | - if (!ret) |
---|
| 1264 | + if (!ret) { |
---|
1120 | 1265 | ret = copy_to_user(up, inf, sizeof(*inf)); |
---|
| 1266 | + if (ret) |
---|
| 1267 | + ret = -EFAULT; |
---|
| 1268 | + } |
---|
1121 | 1269 | kfree(inf); |
---|
1122 | 1270 | break; |
---|
1123 | 1271 | case RKMODULE_AWB_CFG: |
---|
.. | .. |
---|
1130 | 1278 | ret = copy_from_user(cfg, up, sizeof(*cfg)); |
---|
1131 | 1279 | if (!ret) |
---|
1132 | 1280 | ret = sc200ai_ioctl(sd, cmd, cfg); |
---|
| 1281 | + else |
---|
| 1282 | + ret = -EFAULT; |
---|
1133 | 1283 | kfree(cfg); |
---|
1134 | 1284 | break; |
---|
1135 | 1285 | case RKMODULE_GET_HDR_CFG: |
---|
.. | .. |
---|
1140 | 1290 | } |
---|
1141 | 1291 | |
---|
1142 | 1292 | ret = sc200ai_ioctl(sd, cmd, hdr); |
---|
1143 | | - if (!ret) |
---|
| 1293 | + if (!ret) { |
---|
1144 | 1294 | ret = copy_to_user(up, hdr, sizeof(*hdr)); |
---|
| 1295 | + if (ret) |
---|
| 1296 | + ret = -EFAULT; |
---|
| 1297 | + } |
---|
1145 | 1298 | kfree(hdr); |
---|
1146 | 1299 | break; |
---|
1147 | 1300 | case RKMODULE_SET_HDR_CFG: |
---|
.. | .. |
---|
1154 | 1307 | ret = copy_from_user(hdr, up, sizeof(*hdr)); |
---|
1155 | 1308 | if (!ret) |
---|
1156 | 1309 | ret = sc200ai_ioctl(sd, cmd, hdr); |
---|
| 1310 | + else |
---|
| 1311 | + ret = -EFAULT; |
---|
1157 | 1312 | kfree(hdr); |
---|
1158 | 1313 | break; |
---|
1159 | 1314 | case PREISP_CMD_SET_HDRAE_EXP: |
---|
.. | .. |
---|
1166 | 1321 | ret = copy_from_user(hdrae, up, sizeof(*hdrae)); |
---|
1167 | 1322 | if (!ret) |
---|
1168 | 1323 | ret = sc200ai_ioctl(sd, cmd, hdrae); |
---|
| 1324 | + else |
---|
| 1325 | + ret = -EFAULT; |
---|
1169 | 1326 | kfree(hdrae); |
---|
1170 | 1327 | break; |
---|
1171 | 1328 | case RKMODULE_SET_QUICK_STREAM: |
---|
1172 | 1329 | ret = copy_from_user(&stream, up, sizeof(u32)); |
---|
1173 | 1330 | if (!ret) |
---|
1174 | 1331 | 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); |
---|
1175 | 1349 | break; |
---|
1176 | 1350 | default: |
---|
1177 | 1351 | ret = -ENOIOCTLCMD; |
---|
.. | .. |
---|
1186 | 1360 | { |
---|
1187 | 1361 | int ret; |
---|
1188 | 1362 | |
---|
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) |
---|
1203 | 1373 | 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 | + } |
---|
1204 | 1387 | } |
---|
1205 | 1388 | } |
---|
1206 | 1389 | |
---|
.. | .. |
---|
1211 | 1394 | static int __sc200ai_stop_stream(struct sc200ai *sc200ai) |
---|
1212 | 1395 | { |
---|
1213 | 1396 | sc200ai->has_init_exp = false; |
---|
| 1397 | + if (sc200ai->is_thunderboot) { |
---|
| 1398 | + sc200ai->is_first_streamoff = true; |
---|
| 1399 | + pm_runtime_put(&sc200ai->client->dev); |
---|
| 1400 | + } |
---|
1214 | 1401 | return sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE, |
---|
1215 | 1402 | SC200AI_REG_VALUE_08BIT, SC200AI_MODE_SW_STANDBY); |
---|
1216 | 1403 | } |
---|
1217 | 1404 | |
---|
| 1405 | +static int __sc200ai_power_on(struct sc200ai *sc200ai); |
---|
1218 | 1406 | static int sc200ai_s_stream(struct v4l2_subdev *sd, int on) |
---|
1219 | 1407 | { |
---|
1220 | 1408 | struct sc200ai *sc200ai = to_sc200ai(sd); |
---|
.. | .. |
---|
1227 | 1415 | goto unlock_and_return; |
---|
1228 | 1416 | |
---|
1229 | 1417 | 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 | + } |
---|
1230 | 1422 | ret = pm_runtime_get_sync(&client->dev); |
---|
1231 | 1423 | if (ret < 0) { |
---|
1232 | 1424 | pm_runtime_put_noidle(&client->dev); |
---|
.. | .. |
---|
1271 | 1463 | goto unlock_and_return; |
---|
1272 | 1464 | } |
---|
1273 | 1465 | |
---|
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 | + } |
---|
1279 | 1473 | } |
---|
1280 | 1474 | |
---|
1281 | 1475 | sc200ai->power_on = true; |
---|
.. | .. |
---|
1318 | 1512 | dev_err(dev, "Failed to enable xvclk\n"); |
---|
1319 | 1513 | return ret; |
---|
1320 | 1514 | } |
---|
| 1515 | + if (sc200ai->is_thunderboot) |
---|
| 1516 | + return 0; |
---|
| 1517 | + |
---|
1321 | 1518 | if (!IS_ERR(sc200ai->reset_gpio)) |
---|
1322 | 1519 | gpiod_set_value_cansleep(sc200ai->reset_gpio, 0); |
---|
1323 | 1520 | |
---|
.. | .. |
---|
1356 | 1553 | int ret; |
---|
1357 | 1554 | struct device *dev = &sc200ai->client->dev; |
---|
1358 | 1555 | |
---|
| 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 | + } |
---|
1359 | 1565 | if (!IS_ERR(sc200ai->pwdn_gpio)) |
---|
1360 | 1566 | gpiod_set_value_cansleep(sc200ai->pwdn_gpio, 0); |
---|
1361 | 1567 | clk_disable_unprepare(sc200ai->xvclk); |
---|
.. | .. |
---|
1449 | 1655 | static const struct v4l2_subdev_video_ops sc200ai_video_ops = { |
---|
1450 | 1656 | .s_stream = sc200ai_s_stream, |
---|
1451 | 1657 | .g_frame_interval = sc200ai_g_frame_interval, |
---|
1452 | | - .g_mbus_config = sc200ai_g_mbus_config, |
---|
1453 | 1658 | }; |
---|
1454 | 1659 | |
---|
1455 | 1660 | static const struct v4l2_subdev_pad_ops sc200ai_pad_ops = { |
---|
.. | .. |
---|
1458 | 1663 | .enum_frame_interval = sc200ai_enum_frame_interval, |
---|
1459 | 1664 | .get_fmt = sc200ai_get_fmt, |
---|
1460 | 1665 | .set_fmt = sc200ai_set_fmt, |
---|
| 1666 | + .get_mbus_config = sc200ai_g_mbus_config, |
---|
1461 | 1667 | }; |
---|
1462 | 1668 | |
---|
1463 | 1669 | static const struct v4l2_subdev_ops sc200ai_subdev_ops = { |
---|
.. | .. |
---|
1465 | 1671 | .video = &sc200ai_video_ops, |
---|
1466 | 1672 | .pad = &sc200ai_pad_ops, |
---|
1467 | 1673 | }; |
---|
| 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 | +} |
---|
1468 | 1682 | |
---|
1469 | 1683 | static int sc200ai_set_ctrl(struct v4l2_ctrl *ctrl) |
---|
1470 | 1684 | { |
---|
.. | .. |
---|
1528 | 1742 | SC200AI_REG_VALUE_08BIT, |
---|
1529 | 1743 | (ctrl->val + sc200ai->cur_mode->height) |
---|
1530 | 1744 | & 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); |
---|
1532 | 1749 | break; |
---|
1533 | 1750 | case V4L2_CID_TEST_PATTERN: |
---|
1534 | 1751 | ret = sc200ai_enable_test_pattern(sc200ai, ctrl->val); |
---|
.. | .. |
---|
1591 | 1808 | h_blank, h_blank, 1, h_blank); |
---|
1592 | 1809 | if (sc200ai->hblank) |
---|
1593 | 1810 | sc200ai->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
---|
| 1811 | + sc200ai->cur_fps = mode->max_fps; |
---|
1594 | 1812 | vblank_def = mode->vts_def - mode->height; |
---|
| 1813 | + sc200ai->cur_vts = mode->vts_def; |
---|
1595 | 1814 | sc200ai->vblank = v4l2_ctrl_new_std(handler, &sc200ai_ctrl_ops, |
---|
1596 | 1815 | V4L2_CID_VBLANK, vblank_def, |
---|
1597 | 1816 | SC200AI_VTS_MAX - mode->height, |
---|
1598 | 1817 | 1, vblank_def); |
---|
1599 | | - exposure_max = mode->vts_def - 4; |
---|
| 1818 | + exposure_max = 2 * mode->vts_def - 8; |
---|
1600 | 1819 | sc200ai->exposure = v4l2_ctrl_new_std(handler, &sc200ai_ctrl_ops, |
---|
1601 | 1820 | V4L2_CID_EXPOSURE, SC200AI_EXPOSURE_MIN, |
---|
1602 | 1821 | exposure_max, SC200AI_EXPOSURE_STEP, |
---|
.. | .. |
---|
1641 | 1860 | u32 id = 0; |
---|
1642 | 1861 | int ret; |
---|
1643 | 1862 | |
---|
| 1863 | + if (sc200ai->is_thunderboot) { |
---|
| 1864 | + dev_info(dev, "Enable thunderboot mode, skip sensor id check\n"); |
---|
| 1865 | + return 0; |
---|
| 1866 | + } |
---|
| 1867 | + |
---|
1644 | 1868 | ret = sc200ai_read_reg(client, SC200AI_REG_CHIP_ID, |
---|
1645 | 1869 | SC200AI_REG_VALUE_16BIT, &id); |
---|
1646 | 1870 | if (id != CHIP_ID) { |
---|
.. | .. |
---|
1665 | 1889 | sc200ai->supplies); |
---|
1666 | 1890 | } |
---|
1667 | 1891 | |
---|
| 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 | + |
---|
1668 | 2018 | static int sc200ai_probe(struct i2c_client *client, |
---|
1669 | 2019 | const struct i2c_device_id *id) |
---|
1670 | 2020 | { |
---|
.. | .. |
---|
1674 | 2024 | struct v4l2_subdev *sd; |
---|
1675 | 2025 | char facing[2]; |
---|
1676 | 2026 | int ret; |
---|
1677 | | - u32 i, hdr_mode = 0; |
---|
1678 | 2027 | |
---|
1679 | 2028 | dev_info(dev, "driver version: %02x.%02x.%02x", |
---|
1680 | 2029 | DRIVER_VERSION >> 16, |
---|
.. | .. |
---|
1685 | 2034 | if (!sc200ai) |
---|
1686 | 2035 | return -ENOMEM; |
---|
1687 | 2036 | |
---|
1688 | | - of_property_read_u32(node, OF_CAMERA_HDR_MODE, &hdr_mode); |
---|
1689 | 2037 | ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, |
---|
1690 | 2038 | &sc200ai->module_index); |
---|
1691 | 2039 | ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING, |
---|
.. | .. |
---|
1699 | 2047 | return -EINVAL; |
---|
1700 | 2048 | } |
---|
1701 | 2049 | |
---|
| 2050 | + sc200ai->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); |
---|
1702 | 2051 | 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); |
---|
1711 | 2054 | |
---|
1712 | 2055 | sc200ai->xvclk = devm_clk_get(dev, "xvclk"); |
---|
1713 | 2056 | if (IS_ERR(sc200ai->xvclk)) { |
---|
.. | .. |
---|
1715 | 2058 | return -EINVAL; |
---|
1716 | 2059 | } |
---|
1717 | 2060 | |
---|
1718 | | - sc200ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); |
---|
| 2061 | + sc200ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS); |
---|
1719 | 2062 | if (IS_ERR(sc200ai->reset_gpio)) |
---|
1720 | 2063 | dev_warn(dev, "Failed to get reset-gpios\n"); |
---|
1721 | 2064 | |
---|
1722 | | - sc200ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); |
---|
| 2065 | + sc200ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_ASIS); |
---|
1723 | 2066 | if (IS_ERR(sc200ai->pwdn_gpio)) |
---|
1724 | 2067 | dev_warn(dev, "Failed to get pwdn-gpios\n"); |
---|
1725 | 2068 | |
---|
.. | .. |
---|
1792 | 2135 | |
---|
1793 | 2136 | pm_runtime_set_active(dev); |
---|
1794 | 2137 | 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); |
---|
1796 | 2142 | |
---|
1797 | 2143 | return 0; |
---|
1798 | 2144 | |
---|
.. | .. |
---|
1864 | 2210 | i2c_del_driver(&sc200ai_i2c_driver); |
---|
1865 | 2211 | } |
---|
1866 | 2212 | |
---|
| 2213 | +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) |
---|
| 2214 | +subsys_initcall(sensor_mod_init); |
---|
| 2215 | +#else |
---|
1867 | 2216 | device_initcall_sync(sensor_mod_init); |
---|
| 2217 | +#endif |
---|
1868 | 2218 | module_exit(sensor_mod_exit); |
---|
1869 | 2219 | |
---|
1870 | 2220 | MODULE_DESCRIPTION("smartsens sc200ai sensor driver"); |
---|
1871 | | -MODULE_LICENSE("GPL v2"); |
---|
| 2221 | +MODULE_LICENSE("GPL"); |
---|