| .. | .. |
|---|
| 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"); |
|---|