.. | .. |
---|
11 | 11 | * V0.0X01.0X05 add quick stream on/off. |
---|
12 | 12 | * V0.0X01.0X06 fix set vflip/hflip failed bug. |
---|
13 | 13 | * V0.0X01.0X07 |
---|
14 | | - * 1. fix set double times exposue value failed issue. |
---|
15 | | - * 2. add some debug info. |
---|
| 14 | + * 1. fix set double times exposue value failed issue. |
---|
| 15 | + * 2. add some debug info. |
---|
| 16 | + * V0.0X01.0X08 |
---|
| 17 | + * 1. add support wakeup & sleep for aov function |
---|
| 18 | + * 2. using 60fps output default |
---|
16 | 19 | */ |
---|
17 | 20 | |
---|
18 | 21 | #include <linux/clk.h> |
---|
.. | .. |
---|
33 | 36 | #include <media/v4l2-ctrls.h> |
---|
34 | 37 | #include <media/v4l2-subdev.h> |
---|
35 | 38 | #include <linux/pinctrl/consumer.h> |
---|
| 39 | +#include "../platform/rockchip/isp/rkisp_tb_helper.h" |
---|
| 40 | +#include "cam-tb-setup.h" |
---|
| 41 | +#include "cam-sleep-wakeup.h" |
---|
36 | 42 | |
---|
37 | | -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x07) |
---|
| 43 | +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x08) |
---|
38 | 44 | |
---|
39 | 45 | #ifndef V4L2_CID_DIGITAL_GAIN |
---|
40 | 46 | #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN |
---|
.. | .. |
---|
46 | 52 | |
---|
47 | 53 | #define PIXEL_RATE_WITH_371M_10BIT (SC200AI_LINK_FREQ_371 * 2 * \ |
---|
48 | 54 | SC200AI_LANES / SC200AI_BITS_PER_SAMPLE) |
---|
| 55 | + |
---|
49 | 56 | #define SC200AI_XVCLK_FREQ 27000000 |
---|
50 | 57 | |
---|
51 | 58 | #define CHIP_ID 0xcb1c |
---|
.. | .. |
---|
125 | 132 | |
---|
126 | 133 | #define SC200AI_NUM_SUPPLIES ARRAY_SIZE(sc200ai_supply_names) |
---|
127 | 134 | |
---|
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 | 135 | struct regval { |
---|
137 | 136 | u16 addr; |
---|
138 | 137 | u8 val; |
---|
.. | .. |
---|
172 | 171 | struct v4l2_ctrl *vblank; |
---|
173 | 172 | struct v4l2_ctrl *test_pattern; |
---|
174 | 173 | struct mutex mutex; |
---|
| 174 | + struct v4l2_fract cur_fps; |
---|
175 | 175 | bool streaming; |
---|
176 | 176 | bool power_on; |
---|
177 | 177 | const struct sc200ai_mode *cur_mode; |
---|
.. | .. |
---|
181 | 181 | const char *len_name; |
---|
182 | 182 | u32 cur_vts; |
---|
183 | 183 | bool has_init_exp; |
---|
| 184 | + bool is_thunderboot; |
---|
| 185 | + bool is_first_streamoff; |
---|
184 | 186 | struct preisp_hdrae_exp_s init_hdrae_exp; |
---|
| 187 | + struct cam_sw_info *cam_sw_inf; |
---|
185 | 188 | }; |
---|
186 | 189 | |
---|
187 | 190 | #define to_sc200ai(sd) container_of(sd, struct sc200ai, subdev) |
---|
.. | .. |
---|
195 | 198 | |
---|
196 | 199 | /* |
---|
197 | 200 | * Xclk 24Mhz |
---|
198 | | - * max_framerate 90fps |
---|
| 201 | + * max_framerate 60fps |
---|
199 | 202 | * mipi_datarate per lane 1008Mbps, 4lane |
---|
200 | 203 | */ |
---|
201 | | -static const struct regval sc200ai_linear_10_1920x1080_regs[] = { |
---|
| 204 | +static const struct regval sc200ai_linear_10_1920x1080_60fps_regs[] = { |
---|
202 | 205 | {0x0103, 0x01}, |
---|
203 | 206 | {0x0100, 0x00}, |
---|
204 | 207 | {0x36e9, 0x80}, |
---|
.. | .. |
---|
338 | 341 | /* |
---|
339 | 342 | * Xclk 27Mhz |
---|
340 | 343 | * max_framerate 30fps |
---|
| 344 | + * mipi_datarate per lane 371.25Mbps, 2lane |
---|
| 345 | + */ |
---|
| 346 | +static const struct regval sc200ai_linear_10_1920x1080_30fps_regs[] = { |
---|
| 347 | + {0x0103, 0x01}, |
---|
| 348 | + {0x0100, 0x00}, |
---|
| 349 | + {0x36e9, 0x80}, |
---|
| 350 | + {0x36f9, 0x80}, |
---|
| 351 | + {0x301f, 0x03}, |
---|
| 352 | + //HTS=1100*2=2200 |
---|
| 353 | + {0x320c, 0x04}, |
---|
| 354 | + {0x320d, 0x4c}, |
---|
| 355 | + //VTS=1125 |
---|
| 356 | + {0x320e, 0x04}, |
---|
| 357 | + {0x320f, 0x65}, |
---|
| 358 | + {0x3243, 0x01}, |
---|
| 359 | + {0x3248, 0x02}, |
---|
| 360 | + {0x3249, 0x09}, |
---|
| 361 | + {0x3253, 0x08}, |
---|
| 362 | + {0x3271, 0x0a}, |
---|
| 363 | + {0x3301, 0x20}, |
---|
| 364 | + {0x3304, 0x40}, |
---|
| 365 | + {0x3306, 0x32}, |
---|
| 366 | + {0x330b, 0x88}, |
---|
| 367 | + {0x330f, 0x02}, |
---|
| 368 | + {0x331e, 0x39}, |
---|
| 369 | + {0x3333, 0x10}, |
---|
| 370 | + {0x3621, 0xe8}, |
---|
| 371 | + {0x3622, 0x16}, |
---|
| 372 | + {0x3637, 0x1b}, |
---|
| 373 | + {0x363a, 0x1f}, |
---|
| 374 | + {0x363b, 0xc6}, |
---|
| 375 | + {0x363c, 0x0e}, |
---|
| 376 | + {0x3670, 0x0a}, |
---|
| 377 | + {0x3674, 0x82}, |
---|
| 378 | + {0x3675, 0x76}, |
---|
| 379 | + {0x3676, 0x78}, |
---|
| 380 | + {0x367c, 0x48}, |
---|
| 381 | + {0x367d, 0x58}, |
---|
| 382 | + {0x3690, 0x34}, |
---|
| 383 | + {0x3691, 0x33}, |
---|
| 384 | + {0x3692, 0x44}, |
---|
| 385 | + {0x369c, 0x40}, |
---|
| 386 | + {0x369d, 0x48}, |
---|
| 387 | + {0x3901, 0x02}, |
---|
| 388 | + {0x3904, 0x04}, |
---|
| 389 | + {0x3908, 0x41}, |
---|
| 390 | + {0x391d, 0x14}, |
---|
| 391 | + {0x391f, 0x18}, |
---|
| 392 | + {0x3e01, 0x8c}, |
---|
| 393 | + {0x3e02, 0x20}, |
---|
| 394 | + {0x3e16, 0x00}, |
---|
| 395 | + {0x3e17, 0x80}, |
---|
| 396 | + {0x3f09, 0x48}, |
---|
| 397 | + {0x5787, 0x10}, |
---|
| 398 | + {0x5788, 0x06}, |
---|
| 399 | + {0x578a, 0x10}, |
---|
| 400 | + {0x578b, 0x06}, |
---|
| 401 | + {0x5790, 0x10}, |
---|
| 402 | + {0x5791, 0x10}, |
---|
| 403 | + {0x5792, 0x00}, |
---|
| 404 | + {0x5793, 0x10}, |
---|
| 405 | + {0x5794, 0x10}, |
---|
| 406 | + {0x5795, 0x00}, |
---|
| 407 | + {0x5799, 0x00}, |
---|
| 408 | + {0x57c7, 0x10}, |
---|
| 409 | + {0x57c8, 0x06}, |
---|
| 410 | + {0x57ca, 0x10}, |
---|
| 411 | + {0x57cb, 0x06}, |
---|
| 412 | + {0x57d1, 0x10}, |
---|
| 413 | + {0x57d4, 0x10}, |
---|
| 414 | + {0x57d9, 0x00}, |
---|
| 415 | + {0x59e0, 0x60}, |
---|
| 416 | + {0x59e1, 0x08}, |
---|
| 417 | + {0x59e2, 0x3f}, |
---|
| 418 | + {0x59e3, 0x18}, |
---|
| 419 | + {0x59e4, 0x18}, |
---|
| 420 | + {0x59e5, 0x3f}, |
---|
| 421 | + {0x59e6, 0x06}, |
---|
| 422 | + {0x59e7, 0x02}, |
---|
| 423 | + {0x59e8, 0x38}, |
---|
| 424 | + {0x59e9, 0x10}, |
---|
| 425 | + {0x59ea, 0x0c}, |
---|
| 426 | + {0x59eb, 0x10}, |
---|
| 427 | + {0x59ec, 0x04}, |
---|
| 428 | + {0x59ed, 0x02}, |
---|
| 429 | + {0x59ee, 0xa0}, |
---|
| 430 | + {0x59ef, 0x08}, |
---|
| 431 | + {0x59f4, 0x18}, |
---|
| 432 | + {0x59f5, 0x10}, |
---|
| 433 | + {0x59f6, 0x0c}, |
---|
| 434 | + {0x59f7, 0x10}, |
---|
| 435 | + {0x59f8, 0x06}, |
---|
| 436 | + {0x59f9, 0x02}, |
---|
| 437 | + {0x59fa, 0x18}, |
---|
| 438 | + {0x59fb, 0x10}, |
---|
| 439 | + {0x59fc, 0x0c}, |
---|
| 440 | + {0x59fd, 0x10}, |
---|
| 441 | + {0x59fe, 0x04}, |
---|
| 442 | + {0x59ff, 0x02}, |
---|
| 443 | + {0x36e9, 0x20}, |
---|
| 444 | + {0x36f9, 0x27}, |
---|
| 445 | + {REG_NULL, 0x00}, |
---|
| 446 | +}; |
---|
| 447 | + |
---|
| 448 | +/* |
---|
| 449 | + * Xclk 27Mhz |
---|
| 450 | + * max_framerate 30fps |
---|
341 | 451 | * mipi_datarate per lane 742.5Mbps, HDR 2lane |
---|
342 | 452 | */ |
---|
343 | 453 | static const struct regval sc200ai_hdr_10_1920x1080_regs[] = { |
---|
.. | .. |
---|
346 | 456 | {0x36e9, 0x80}, |
---|
347 | 457 | {0x36f9, 0x80}, |
---|
348 | 458 | {0x301f, 0x02}, |
---|
| 459 | + //HTS=1100*2=2200 |
---|
| 460 | + {0x320c, 0x04}, |
---|
| 461 | + {0x320d, 0x4c}, |
---|
| 462 | + //VTS =2252 |
---|
349 | 463 | {0x320e, 0x08}, |
---|
350 | | - {0x320f, 0xca}, |
---|
| 464 | + {0x320f, 0xcc}, |
---|
351 | 465 | {0x3220, 0x53}, |
---|
352 | 466 | {0x3243, 0x01}, |
---|
353 | 467 | {0x3248, 0x02}, |
---|
.. | .. |
---|
372 | 486 | {0x331f, 0x61}, |
---|
373 | 487 | {0x3320, 0x07}, |
---|
374 | 488 | {0x3333, 0x10}, |
---|
| 489 | + {0x3347, 0x77}, |
---|
375 | 490 | {0x334c, 0x08}, |
---|
376 | 491 | {0x3356, 0x09}, |
---|
377 | 492 | {0x3364, 0x17}, |
---|
| 493 | + {0x336c, 0xcc}, |
---|
378 | 494 | {0x3390, 0x08}, |
---|
379 | 495 | {0x3391, 0x18}, |
---|
380 | 496 | {0x3392, 0x38}, |
---|
.. | .. |
---|
431 | 547 | {0x3e13, 0x40}, |
---|
432 | 548 | {0x3e16, 0x00}, |
---|
433 | 549 | {0x3e17, 0x80}, |
---|
434 | | - {0x3e23, 0x00}, |
---|
435 | | - {0x3e24, 0x40}, |
---|
| 550 | + {0x3e23, 0x01}, |
---|
| 551 | + {0x3e24, 0x9e}, |
---|
436 | 552 | {0x3f09, 0x48}, |
---|
437 | 553 | {0x4816, 0xb1}, |
---|
438 | 554 | {0x4819, 0x09}, |
---|
.. | .. |
---|
507 | 623 | .hts_def = 0x44C * 2, |
---|
508 | 624 | .vts_def = 0x0465, |
---|
509 | 625 | .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, |
---|
510 | | - .reg_list = sc200ai_linear_10_1920x1080_regs, |
---|
| 626 | + .reg_list = sc200ai_linear_10_1920x1080_60fps_regs, |
---|
511 | 627 | .hdr_mode = NO_HDR, |
---|
512 | 628 | .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, |
---|
513 | | - }, { |
---|
| 629 | + }, |
---|
| 630 | + { |
---|
514 | 631 | .width = 1920, |
---|
515 | 632 | .height = 1080, |
---|
516 | 633 | .max_fps = { |
---|
.. | .. |
---|
519 | 636 | }, |
---|
520 | 637 | .exp_def = 0x0080, |
---|
521 | 638 | .hts_def = 0x44C * 2, |
---|
522 | | - .vts_def = 0x08CA, |
---|
| 639 | + .vts_def = 0x0465, |
---|
| 640 | + .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, |
---|
| 641 | + .reg_list = sc200ai_linear_10_1920x1080_30fps_regs, |
---|
| 642 | + .hdr_mode = NO_HDR, |
---|
| 643 | + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, |
---|
| 644 | + }, |
---|
| 645 | + { |
---|
| 646 | + .width = 1920, |
---|
| 647 | + .height = 1080, |
---|
| 648 | + .max_fps = { |
---|
| 649 | + .numerator = 10000, |
---|
| 650 | + .denominator = 300000, |
---|
| 651 | + }, |
---|
| 652 | + .exp_def = 0x0080, |
---|
| 653 | + .hts_def = 0x44C * 2, |
---|
| 654 | + .vts_def = 0x08CC, |
---|
523 | 655 | .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, |
---|
524 | 656 | .reg_list = sc200ai_hdr_10_1920x1080_regs, |
---|
525 | 657 | .hdr_mode = HDR_X2, |
---|
.. | .. |
---|
814 | 946 | s_exp_time = s_exp_time * 2; |
---|
815 | 947 | if (l_exp_time > 4362) //(2250 - 64 - 5) * 2 |
---|
816 | 948 | l_exp_time = 4362; |
---|
817 | | - if (s_exp_time > 118) //(64 - 5) * 2 |
---|
818 | | - s_exp_time = 118; |
---|
| 949 | + if (s_exp_time > 404) //(64 - 5) * 2 |
---|
| 950 | + s_exp_time = 404; |
---|
819 | 951 | |
---|
820 | 952 | ret = sc200ai_write_reg(sc200ai->client, |
---|
821 | 953 | SC200AI_REG_EXPOSURE_H, |
---|
.. | .. |
---|
837 | 969 | SC200AI_REG_SEXPOSURE_L, |
---|
838 | 970 | SC200AI_REG_VALUE_08BIT, |
---|
839 | 971 | SC200AI_FETCH_EXP_L(s_exp_time)); |
---|
840 | | - |
---|
841 | 972 | |
---|
842 | 973 | ret |= sc200ai_set_gain_reg(sc200ai, l_a_gain, SC200AI_LGAIN); |
---|
843 | 974 | ret |= sc200ai_set_gain_reg(sc200ai, s_a_gain, SC200AI_SGAIN); |
---|
.. | .. |
---|
902 | 1033 | __v4l2_ctrl_modify_range(sc200ai->vblank, vblank_def, |
---|
903 | 1034 | SC200AI_VTS_MAX - mode->height, |
---|
904 | 1035 | 1, vblank_def); |
---|
| 1036 | + sc200ai->cur_fps = mode->max_fps; |
---|
| 1037 | + sc200ai->cur_vts = mode->vts_def; |
---|
905 | 1038 | } |
---|
906 | 1039 | |
---|
907 | 1040 | mutex_unlock(&sc200ai->mutex); |
---|
.. | .. |
---|
994 | 1127 | struct sc200ai *sc200ai = to_sc200ai(sd); |
---|
995 | 1128 | const struct sc200ai_mode *mode = sc200ai->cur_mode; |
---|
996 | 1129 | |
---|
997 | | - mutex_lock(&sc200ai->mutex); |
---|
998 | | - fi->interval = mode->max_fps; |
---|
999 | | - mutex_unlock(&sc200ai->mutex); |
---|
| 1130 | + if (sc200ai->streaming) |
---|
| 1131 | + fi->interval = sc200ai->cur_fps; |
---|
| 1132 | + else |
---|
| 1133 | + fi->interval = mode->max_fps; |
---|
1000 | 1134 | |
---|
1001 | 1135 | return 0; |
---|
1002 | 1136 | } |
---|
1003 | 1137 | |
---|
1004 | | -static int sc200ai_g_mbus_config(struct v4l2_subdev *sd, |
---|
| 1138 | +static int sc200ai_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, |
---|
1005 | 1139 | struct v4l2_mbus_config *config) |
---|
1006 | 1140 | { |
---|
1007 | 1141 | struct sc200ai *sc200ai = to_sc200ai(sd); |
---|
.. | .. |
---|
1015 | 1149 | if (mode->hdr_mode == HDR_X3) |
---|
1016 | 1150 | val |= V4L2_MBUS_CSI2_CHANNEL_2; |
---|
1017 | 1151 | |
---|
1018 | | - config->type = V4L2_MBUS_CSI2; |
---|
| 1152 | + config->type = V4L2_MBUS_CSI2_DPHY; |
---|
1019 | 1153 | config->flags = val; |
---|
1020 | 1154 | |
---|
1021 | 1155 | return 0; |
---|
.. | .. |
---|
1031 | 1165 | strlcpy(inf->base.lens, sc200ai->len_name, sizeof(inf->base.lens)); |
---|
1032 | 1166 | } |
---|
1033 | 1167 | |
---|
| 1168 | +static int sc200ai_get_channel_info(struct sc200ai *sc200ai, struct rkmodule_channel_info *ch_info) |
---|
| 1169 | +{ |
---|
| 1170 | + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) |
---|
| 1171 | + return -EINVAL; |
---|
| 1172 | + ch_info->vc = sc200ai->cur_mode->vc[ch_info->index]; |
---|
| 1173 | + ch_info->width = sc200ai->cur_mode->width; |
---|
| 1174 | + ch_info->height = sc200ai->cur_mode->height; |
---|
| 1175 | + ch_info->bus_fmt = sc200ai->cur_mode->bus_fmt; |
---|
| 1176 | + return 0; |
---|
| 1177 | +} |
---|
| 1178 | + |
---|
1034 | 1179 | static long sc200ai_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) |
---|
1035 | 1180 | { |
---|
1036 | 1181 | struct sc200ai *sc200ai = to_sc200ai(sd); |
---|
1037 | 1182 | struct rkmodule_hdr_cfg *hdr; |
---|
| 1183 | + struct rkmodule_channel_info *ch_info; |
---|
1038 | 1184 | u32 i, h, w; |
---|
1039 | 1185 | long ret = 0; |
---|
1040 | 1186 | u32 stream = 0; |
---|
.. | .. |
---|
1071 | 1217 | __v4l2_ctrl_modify_range(sc200ai->hblank, w, w, 1, w); |
---|
1072 | 1218 | __v4l2_ctrl_modify_range(sc200ai->vblank, h, |
---|
1073 | 1219 | SC200AI_VTS_MAX - sc200ai->cur_mode->height, 1, h); |
---|
| 1220 | + sc200ai->cur_fps = sc200ai->cur_mode->max_fps; |
---|
| 1221 | + sc200ai->cur_vts = sc200ai->cur_mode->vts_def; |
---|
1074 | 1222 | } |
---|
1075 | 1223 | break; |
---|
1076 | 1224 | case PREISP_CMD_SET_HDRAE_EXP: |
---|
1077 | 1225 | sc200ai_set_hdrae(sc200ai, arg); |
---|
| 1226 | + if (sc200ai->cam_sw_inf) |
---|
| 1227 | + memcpy(&sc200ai->cam_sw_inf->hdr_ae, (struct preisp_hdrae_exp_s *)(arg), |
---|
| 1228 | + sizeof(struct preisp_hdrae_exp_s)); |
---|
1078 | 1229 | break; |
---|
1079 | 1230 | case RKMODULE_SET_QUICK_STREAM: |
---|
1080 | 1231 | |
---|
1081 | 1232 | stream = *((u32 *)arg); |
---|
1082 | 1233 | |
---|
1083 | | - if (stream) |
---|
| 1234 | + if (stream) { |
---|
| 1235 | + gpiod_set_value_cansleep(sc200ai->pwdn_gpio, 1); |
---|
1084 | 1236 | ret = sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE, |
---|
1085 | 1237 | SC200AI_REG_VALUE_08BIT, SC200AI_MODE_STREAMING); |
---|
1086 | | - else |
---|
| 1238 | + } else { |
---|
1087 | 1239 | ret = sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE, |
---|
1088 | 1240 | SC200AI_REG_VALUE_08BIT, SC200AI_MODE_SW_STANDBY); |
---|
| 1241 | + gpiod_set_value_cansleep(sc200ai->pwdn_gpio, 0); |
---|
| 1242 | + } |
---|
| 1243 | + break; |
---|
| 1244 | + case RKMODULE_GET_CHANNEL_INFO: |
---|
| 1245 | + ch_info = (struct rkmodule_channel_info *)arg; |
---|
| 1246 | + ret = sc200ai_get_channel_info(sc200ai, ch_info); |
---|
1089 | 1247 | break; |
---|
1090 | 1248 | default: |
---|
1091 | 1249 | ret = -ENOIOCTLCMD; |
---|
.. | .. |
---|
1104 | 1262 | struct rkmodule_awb_cfg *cfg; |
---|
1105 | 1263 | struct rkmodule_hdr_cfg *hdr; |
---|
1106 | 1264 | struct preisp_hdrae_exp_s *hdrae; |
---|
| 1265 | + struct rkmodule_channel_info *ch_info; |
---|
1107 | 1266 | long ret; |
---|
1108 | 1267 | u32 stream = 0; |
---|
1109 | 1268 | |
---|
.. | .. |
---|
1116 | 1275 | } |
---|
1117 | 1276 | |
---|
1118 | 1277 | ret = sc200ai_ioctl(sd, cmd, inf); |
---|
1119 | | - if (!ret) |
---|
| 1278 | + if (!ret) { |
---|
1120 | 1279 | ret = copy_to_user(up, inf, sizeof(*inf)); |
---|
| 1280 | + if (ret) |
---|
| 1281 | + ret = -EFAULT; |
---|
| 1282 | + } |
---|
1121 | 1283 | kfree(inf); |
---|
1122 | 1284 | break; |
---|
1123 | 1285 | case RKMODULE_AWB_CFG: |
---|
.. | .. |
---|
1130 | 1292 | ret = copy_from_user(cfg, up, sizeof(*cfg)); |
---|
1131 | 1293 | if (!ret) |
---|
1132 | 1294 | ret = sc200ai_ioctl(sd, cmd, cfg); |
---|
| 1295 | + else |
---|
| 1296 | + ret = -EFAULT; |
---|
1133 | 1297 | kfree(cfg); |
---|
1134 | 1298 | break; |
---|
1135 | 1299 | case RKMODULE_GET_HDR_CFG: |
---|
.. | .. |
---|
1140 | 1304 | } |
---|
1141 | 1305 | |
---|
1142 | 1306 | ret = sc200ai_ioctl(sd, cmd, hdr); |
---|
1143 | | - if (!ret) |
---|
| 1307 | + if (!ret) { |
---|
1144 | 1308 | ret = copy_to_user(up, hdr, sizeof(*hdr)); |
---|
| 1309 | + if (ret) |
---|
| 1310 | + ret = -EFAULT; |
---|
| 1311 | + } |
---|
1145 | 1312 | kfree(hdr); |
---|
1146 | 1313 | break; |
---|
1147 | 1314 | case RKMODULE_SET_HDR_CFG: |
---|
.. | .. |
---|
1154 | 1321 | ret = copy_from_user(hdr, up, sizeof(*hdr)); |
---|
1155 | 1322 | if (!ret) |
---|
1156 | 1323 | ret = sc200ai_ioctl(sd, cmd, hdr); |
---|
| 1324 | + else |
---|
| 1325 | + ret = -EFAULT; |
---|
1157 | 1326 | kfree(hdr); |
---|
1158 | 1327 | break; |
---|
1159 | 1328 | case PREISP_CMD_SET_HDRAE_EXP: |
---|
.. | .. |
---|
1166 | 1335 | ret = copy_from_user(hdrae, up, sizeof(*hdrae)); |
---|
1167 | 1336 | if (!ret) |
---|
1168 | 1337 | ret = sc200ai_ioctl(sd, cmd, hdrae); |
---|
| 1338 | + else |
---|
| 1339 | + ret = -EFAULT; |
---|
1169 | 1340 | kfree(hdrae); |
---|
1170 | 1341 | break; |
---|
1171 | 1342 | case RKMODULE_SET_QUICK_STREAM: |
---|
1172 | 1343 | ret = copy_from_user(&stream, up, sizeof(u32)); |
---|
1173 | 1344 | if (!ret) |
---|
1174 | 1345 | ret = sc200ai_ioctl(sd, cmd, &stream); |
---|
| 1346 | + else |
---|
| 1347 | + ret = -EFAULT; |
---|
| 1348 | + break; |
---|
| 1349 | + case RKMODULE_GET_CHANNEL_INFO: |
---|
| 1350 | + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); |
---|
| 1351 | + if (!ch_info) { |
---|
| 1352 | + ret = -ENOMEM; |
---|
| 1353 | + return ret; |
---|
| 1354 | + } |
---|
| 1355 | + |
---|
| 1356 | + ret = sc200ai_ioctl(sd, cmd, ch_info); |
---|
| 1357 | + if (!ret) { |
---|
| 1358 | + ret = copy_to_user(up, ch_info, sizeof(*ch_info)); |
---|
| 1359 | + if (ret) |
---|
| 1360 | + ret = -EFAULT; |
---|
| 1361 | + } |
---|
| 1362 | + kfree(ch_info); |
---|
1175 | 1363 | break; |
---|
1176 | 1364 | default: |
---|
1177 | 1365 | ret = -ENOIOCTLCMD; |
---|
.. | .. |
---|
1186 | 1374 | { |
---|
1187 | 1375 | int ret; |
---|
1188 | 1376 | |
---|
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"); |
---|
| 1377 | + dev_info(&sc200ai->client->dev, |
---|
| 1378 | + "%dx%d@%d, mode %d, vts 0x%x\n", |
---|
| 1379 | + sc200ai->cur_mode->width, |
---|
| 1380 | + sc200ai->cur_mode->height, |
---|
| 1381 | + sc200ai->cur_fps.denominator / sc200ai->cur_fps.numerator, |
---|
| 1382 | + sc200ai->cur_mode->hdr_mode, |
---|
| 1383 | + sc200ai->cur_vts); |
---|
| 1384 | + if (!sc200ai->is_thunderboot) { |
---|
| 1385 | + ret = sc200ai_write_array(sc200ai->client, sc200ai->cur_mode->reg_list); |
---|
| 1386 | + if (ret) |
---|
1203 | 1387 | return ret; |
---|
| 1388 | + |
---|
| 1389 | + /* In case these controls are set before streaming */ |
---|
| 1390 | + ret = __v4l2_ctrl_handler_setup(&sc200ai->ctrl_handler); |
---|
| 1391 | + if (ret) |
---|
| 1392 | + return ret; |
---|
| 1393 | + if (sc200ai->has_init_exp && sc200ai->cur_mode->hdr_mode != NO_HDR) { |
---|
| 1394 | + ret = sc200ai_ioctl(&sc200ai->subdev, PREISP_CMD_SET_HDRAE_EXP, |
---|
| 1395 | + &sc200ai->init_hdrae_exp); |
---|
| 1396 | + if (ret) { |
---|
| 1397 | + dev_err(&sc200ai->client->dev, |
---|
| 1398 | + "init exp fail in hdr mode\n"); |
---|
| 1399 | + return ret; |
---|
| 1400 | + } |
---|
1204 | 1401 | } |
---|
1205 | 1402 | } |
---|
1206 | 1403 | |
---|
.. | .. |
---|
1211 | 1408 | static int __sc200ai_stop_stream(struct sc200ai *sc200ai) |
---|
1212 | 1409 | { |
---|
1213 | 1410 | sc200ai->has_init_exp = false; |
---|
| 1411 | + if (sc200ai->is_thunderboot) { |
---|
| 1412 | + sc200ai->is_first_streamoff = true; |
---|
| 1413 | + pm_runtime_put(&sc200ai->client->dev); |
---|
| 1414 | + } |
---|
1214 | 1415 | return sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE, |
---|
1215 | 1416 | SC200AI_REG_VALUE_08BIT, SC200AI_MODE_SW_STANDBY); |
---|
1216 | 1417 | } |
---|
1217 | 1418 | |
---|
| 1419 | +static int __sc200ai_power_on(struct sc200ai *sc200ai); |
---|
1218 | 1420 | static int sc200ai_s_stream(struct v4l2_subdev *sd, int on) |
---|
1219 | 1421 | { |
---|
1220 | 1422 | struct sc200ai *sc200ai = to_sc200ai(sd); |
---|
.. | .. |
---|
1227 | 1429 | goto unlock_and_return; |
---|
1228 | 1430 | |
---|
1229 | 1431 | if (on) { |
---|
| 1432 | + if (sc200ai->is_thunderboot && rkisp_tb_get_state() == RKISP_TB_NG) { |
---|
| 1433 | + sc200ai->is_thunderboot = false; |
---|
| 1434 | + __sc200ai_power_on(sc200ai); |
---|
| 1435 | + } |
---|
1230 | 1436 | ret = pm_runtime_get_sync(&client->dev); |
---|
1231 | 1437 | if (ret < 0) { |
---|
1232 | 1438 | pm_runtime_put_noidle(&client->dev); |
---|
.. | .. |
---|
1271 | 1477 | goto unlock_and_return; |
---|
1272 | 1478 | } |
---|
1273 | 1479 | |
---|
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; |
---|
| 1480 | + if (!sc200ai->is_thunderboot) { |
---|
| 1481 | + ret = sc200ai_write_array(sc200ai->client, sc200ai_global_regs); |
---|
| 1482 | + if (ret) { |
---|
| 1483 | + v4l2_err(sd, "could not set init registers\n"); |
---|
| 1484 | + pm_runtime_put_noidle(&client->dev); |
---|
| 1485 | + goto unlock_and_return; |
---|
| 1486 | + } |
---|
1279 | 1487 | } |
---|
1280 | 1488 | |
---|
1281 | 1489 | sc200ai->power_on = true; |
---|
.. | .. |
---|
1318 | 1526 | dev_err(dev, "Failed to enable xvclk\n"); |
---|
1319 | 1527 | return ret; |
---|
1320 | 1528 | } |
---|
| 1529 | + |
---|
| 1530 | + cam_sw_regulator_bulk_init(sc200ai->cam_sw_inf, SC200AI_NUM_SUPPLIES, sc200ai->supplies); |
---|
| 1531 | + |
---|
| 1532 | + if (sc200ai->is_thunderboot) |
---|
| 1533 | + return 0; |
---|
| 1534 | + |
---|
1321 | 1535 | if (!IS_ERR(sc200ai->reset_gpio)) |
---|
1322 | 1536 | gpiod_set_value_cansleep(sc200ai->reset_gpio, 0); |
---|
1323 | 1537 | |
---|
.. | .. |
---|
1356 | 1570 | int ret; |
---|
1357 | 1571 | struct device *dev = &sc200ai->client->dev; |
---|
1358 | 1572 | |
---|
| 1573 | + clk_disable_unprepare(sc200ai->xvclk); |
---|
| 1574 | + if (sc200ai->is_thunderboot) { |
---|
| 1575 | + if (sc200ai->is_first_streamoff) { |
---|
| 1576 | + sc200ai->is_thunderboot = false; |
---|
| 1577 | + sc200ai->is_first_streamoff = false; |
---|
| 1578 | + } else { |
---|
| 1579 | + return; |
---|
| 1580 | + } |
---|
| 1581 | + } |
---|
1359 | 1582 | if (!IS_ERR(sc200ai->pwdn_gpio)) |
---|
1360 | 1583 | gpiod_set_value_cansleep(sc200ai->pwdn_gpio, 0); |
---|
1361 | 1584 | clk_disable_unprepare(sc200ai->xvclk); |
---|
.. | .. |
---|
1369 | 1592 | } |
---|
1370 | 1593 | regulator_bulk_disable(SC200AI_NUM_SUPPLIES, sc200ai->supplies); |
---|
1371 | 1594 | } |
---|
| 1595 | + |
---|
| 1596 | +#if IS_REACHABLE(CONFIG_VIDEO_CAM_SLEEP_WAKEUP) |
---|
| 1597 | +static int __maybe_unused sc200ai_resume(struct device *dev) |
---|
| 1598 | +{ |
---|
| 1599 | + int ret; |
---|
| 1600 | + struct i2c_client *client = to_i2c_client(dev); |
---|
| 1601 | + struct v4l2_subdev *sd = i2c_get_clientdata(client); |
---|
| 1602 | + struct sc200ai *sc200ai = to_sc200ai(sd); |
---|
| 1603 | + |
---|
| 1604 | + cam_sw_prepare_wakeup(sc200ai->cam_sw_inf, dev); |
---|
| 1605 | + |
---|
| 1606 | + usleep_range(4000, 5000); |
---|
| 1607 | + cam_sw_write_array(sc200ai->cam_sw_inf); |
---|
| 1608 | + |
---|
| 1609 | + if (__v4l2_ctrl_handler_setup(&sc200ai->ctrl_handler)) |
---|
| 1610 | + dev_err(dev, "__v4l2_ctrl_handler_setup fail!"); |
---|
| 1611 | + |
---|
| 1612 | + if (sc200ai->has_init_exp && sc200ai->cur_mode != NO_HDR) { // hdr mode |
---|
| 1613 | + ret = sc200ai_ioctl(&sc200ai->subdev, PREISP_CMD_SET_HDRAE_EXP, |
---|
| 1614 | + &sc200ai->cam_sw_inf->hdr_ae); |
---|
| 1615 | + if (ret) { |
---|
| 1616 | + dev_err(&sc200ai->client->dev, "set exp fail in hdr mode\n"); |
---|
| 1617 | + return ret; |
---|
| 1618 | + } |
---|
| 1619 | + } |
---|
| 1620 | + return 0; |
---|
| 1621 | +} |
---|
| 1622 | + |
---|
| 1623 | +static int __maybe_unused sc200ai_suspend(struct device *dev) |
---|
| 1624 | +{ |
---|
| 1625 | + struct i2c_client *client = to_i2c_client(dev); |
---|
| 1626 | + struct v4l2_subdev *sd = i2c_get_clientdata(client); |
---|
| 1627 | + struct sc200ai *sc200ai = to_sc200ai(sd); |
---|
| 1628 | + |
---|
| 1629 | + cam_sw_write_array_cb_init(sc200ai->cam_sw_inf, client, |
---|
| 1630 | + (void *)sc200ai->cur_mode->reg_list, |
---|
| 1631 | + (sensor_write_array)sc200ai_write_array); |
---|
| 1632 | + cam_sw_prepare_sleep(sc200ai->cam_sw_inf); |
---|
| 1633 | + |
---|
| 1634 | + return 0; |
---|
| 1635 | +} |
---|
| 1636 | +#else |
---|
| 1637 | +#define sc200ai_resume NULL |
---|
| 1638 | +#define sc200ai_suspend NULL |
---|
| 1639 | +#endif |
---|
1372 | 1640 | |
---|
1373 | 1641 | static int sc200ai_runtime_resume(struct device *dev) |
---|
1374 | 1642 | { |
---|
.. | .. |
---|
1430 | 1698 | static const struct dev_pm_ops sc200ai_pm_ops = { |
---|
1431 | 1699 | SET_RUNTIME_PM_OPS(sc200ai_runtime_suspend, |
---|
1432 | 1700 | sc200ai_runtime_resume, NULL) |
---|
| 1701 | + SET_LATE_SYSTEM_SLEEP_PM_OPS(sc200ai_suspend, sc200ai_resume) |
---|
1433 | 1702 | }; |
---|
1434 | 1703 | |
---|
1435 | 1704 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API |
---|
.. | .. |
---|
1449 | 1718 | static const struct v4l2_subdev_video_ops sc200ai_video_ops = { |
---|
1450 | 1719 | .s_stream = sc200ai_s_stream, |
---|
1451 | 1720 | .g_frame_interval = sc200ai_g_frame_interval, |
---|
1452 | | - .g_mbus_config = sc200ai_g_mbus_config, |
---|
1453 | 1721 | }; |
---|
1454 | 1722 | |
---|
1455 | 1723 | static const struct v4l2_subdev_pad_ops sc200ai_pad_ops = { |
---|
.. | .. |
---|
1458 | 1726 | .enum_frame_interval = sc200ai_enum_frame_interval, |
---|
1459 | 1727 | .get_fmt = sc200ai_get_fmt, |
---|
1460 | 1728 | .set_fmt = sc200ai_set_fmt, |
---|
| 1729 | + .get_mbus_config = sc200ai_g_mbus_config, |
---|
1461 | 1730 | }; |
---|
1462 | 1731 | |
---|
1463 | 1732 | static const struct v4l2_subdev_ops sc200ai_subdev_ops = { |
---|
.. | .. |
---|
1465 | 1734 | .video = &sc200ai_video_ops, |
---|
1466 | 1735 | .pad = &sc200ai_pad_ops, |
---|
1467 | 1736 | }; |
---|
| 1737 | + |
---|
| 1738 | +static void sc200ai_modify_fps_info(struct sc200ai *sc200ai) |
---|
| 1739 | +{ |
---|
| 1740 | + const struct sc200ai_mode *mode = sc200ai->cur_mode; |
---|
| 1741 | + |
---|
| 1742 | + sc200ai->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def/ |
---|
| 1743 | + sc200ai->cur_vts; |
---|
| 1744 | +} |
---|
1468 | 1745 | |
---|
1469 | 1746 | static int sc200ai_set_ctrl(struct v4l2_ctrl *ctrl) |
---|
1470 | 1747 | { |
---|
.. | .. |
---|
1528 | 1805 | SC200AI_REG_VALUE_08BIT, |
---|
1529 | 1806 | (ctrl->val + sc200ai->cur_mode->height) |
---|
1530 | 1807 | & 0xff); |
---|
1531 | | - sc200ai->cur_vts = ctrl->val + sc200ai->cur_mode->height; |
---|
| 1808 | + if (!ret) |
---|
| 1809 | + sc200ai->cur_vts = ctrl->val + sc200ai->cur_mode->height; |
---|
| 1810 | + sc200ai_modify_fps_info(sc200ai); |
---|
1532 | 1811 | break; |
---|
1533 | 1812 | case V4L2_CID_TEST_PATTERN: |
---|
1534 | 1813 | ret = sc200ai_enable_test_pattern(sc200ai, ctrl->val); |
---|
.. | .. |
---|
1591 | 1870 | h_blank, h_blank, 1, h_blank); |
---|
1592 | 1871 | if (sc200ai->hblank) |
---|
1593 | 1872 | sc200ai->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
---|
| 1873 | + sc200ai->cur_fps = mode->max_fps; |
---|
1594 | 1874 | vblank_def = mode->vts_def - mode->height; |
---|
| 1875 | + sc200ai->cur_vts = mode->vts_def; |
---|
1595 | 1876 | sc200ai->vblank = v4l2_ctrl_new_std(handler, &sc200ai_ctrl_ops, |
---|
1596 | 1877 | V4L2_CID_VBLANK, vblank_def, |
---|
1597 | 1878 | SC200AI_VTS_MAX - mode->height, |
---|
1598 | 1879 | 1, vblank_def); |
---|
1599 | | - exposure_max = mode->vts_def - 4; |
---|
| 1880 | + exposure_max = 2 * mode->vts_def - 8; |
---|
1600 | 1881 | sc200ai->exposure = v4l2_ctrl_new_std(handler, &sc200ai_ctrl_ops, |
---|
1601 | 1882 | V4L2_CID_EXPOSURE, SC200AI_EXPOSURE_MIN, |
---|
1602 | 1883 | exposure_max, SC200AI_EXPOSURE_STEP, |
---|
.. | .. |
---|
1641 | 1922 | u32 id = 0; |
---|
1642 | 1923 | int ret; |
---|
1643 | 1924 | |
---|
| 1925 | + if (sc200ai->is_thunderboot) { |
---|
| 1926 | + dev_info(dev, "Enable thunderboot mode, skip sensor id check\n"); |
---|
| 1927 | + return 0; |
---|
| 1928 | + } |
---|
| 1929 | + |
---|
1644 | 1930 | ret = sc200ai_read_reg(client, SC200AI_REG_CHIP_ID, |
---|
1645 | 1931 | SC200AI_REG_VALUE_16BIT, &id); |
---|
1646 | 1932 | if (id != CHIP_ID) { |
---|
.. | .. |
---|
1665 | 1951 | sc200ai->supplies); |
---|
1666 | 1952 | } |
---|
1667 | 1953 | |
---|
| 1954 | +#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP |
---|
| 1955 | +static void find_terminal_resolution(struct sc200ai *sc200ai) |
---|
| 1956 | +{ |
---|
| 1957 | + int i = 0; |
---|
| 1958 | + const struct sc200ai_mode *mode = NULL; |
---|
| 1959 | + u32 rk_cam_hdr = get_rk_cam_hdr(); |
---|
| 1960 | + u32 rk_cam_w = get_rk_cam_w(); |
---|
| 1961 | + u32 rk_cam_h = get_rk_cam_h(); |
---|
| 1962 | + |
---|
| 1963 | + if (rk_cam_w == 0 || rk_cam_h == 0) |
---|
| 1964 | + goto err_find_res; |
---|
| 1965 | + |
---|
| 1966 | + for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { |
---|
| 1967 | + mode = &supported_modes[i]; |
---|
| 1968 | + if (mode->width == rk_cam_w && mode->height == rk_cam_h && |
---|
| 1969 | + mode->hdr_mode == rk_cam_hdr) { |
---|
| 1970 | + sc200ai->cur_mode = mode; |
---|
| 1971 | + return; |
---|
| 1972 | + } |
---|
| 1973 | + } |
---|
| 1974 | +err_find_res: |
---|
| 1975 | + dev_err(&sc200ai->client->dev, "not match %dx%d mode %d\n!", |
---|
| 1976 | + rk_cam_w, rk_cam_h, rk_cam_hdr); |
---|
| 1977 | + sc200ai->cur_mode = &supported_modes[0]; |
---|
| 1978 | +} |
---|
| 1979 | +#else |
---|
| 1980 | +static void find_terminal_resolution(struct sc200ai *sc200ai) |
---|
| 1981 | +{ |
---|
| 1982 | + u32 hdr_mode = 0; |
---|
| 1983 | + struct device_node *node = sc200ai->client->dev.of_node; |
---|
| 1984 | + int i = 0; |
---|
| 1985 | + |
---|
| 1986 | + of_property_read_u32(node, OF_CAMERA_HDR_MODE, &hdr_mode); |
---|
| 1987 | + for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { |
---|
| 1988 | + if (hdr_mode == supported_modes[i].hdr_mode) { |
---|
| 1989 | + sc200ai->cur_mode = &supported_modes[i]; |
---|
| 1990 | + break; |
---|
| 1991 | + } |
---|
| 1992 | + } |
---|
| 1993 | + if (i == ARRAY_SIZE(supported_modes)) |
---|
| 1994 | + sc200ai->cur_mode = &supported_modes[0]; |
---|
| 1995 | + |
---|
| 1996 | +} |
---|
| 1997 | +#endif |
---|
| 1998 | + |
---|
1668 | 1999 | static int sc200ai_probe(struct i2c_client *client, |
---|
1669 | 2000 | const struct i2c_device_id *id) |
---|
1670 | 2001 | { |
---|
.. | .. |
---|
1674 | 2005 | struct v4l2_subdev *sd; |
---|
1675 | 2006 | char facing[2]; |
---|
1676 | 2007 | int ret; |
---|
1677 | | - u32 i, hdr_mode = 0; |
---|
1678 | 2008 | |
---|
1679 | 2009 | dev_info(dev, "driver version: %02x.%02x.%02x", |
---|
1680 | 2010 | DRIVER_VERSION >> 16, |
---|
.. | .. |
---|
1685 | 2015 | if (!sc200ai) |
---|
1686 | 2016 | return -ENOMEM; |
---|
1687 | 2017 | |
---|
1688 | | - of_property_read_u32(node, OF_CAMERA_HDR_MODE, &hdr_mode); |
---|
1689 | 2018 | ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, |
---|
1690 | 2019 | &sc200ai->module_index); |
---|
1691 | 2020 | ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING, |
---|
.. | .. |
---|
1699 | 2028 | return -EINVAL; |
---|
1700 | 2029 | } |
---|
1701 | 2030 | |
---|
| 2031 | + sc200ai->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); |
---|
1702 | 2032 | 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]; |
---|
| 2033 | + |
---|
| 2034 | + find_terminal_resolution(sc200ai); |
---|
1711 | 2035 | |
---|
1712 | 2036 | sc200ai->xvclk = devm_clk_get(dev, "xvclk"); |
---|
1713 | 2037 | if (IS_ERR(sc200ai->xvclk)) { |
---|
.. | .. |
---|
1715 | 2039 | return -EINVAL; |
---|
1716 | 2040 | } |
---|
1717 | 2041 | |
---|
1718 | | - sc200ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); |
---|
| 2042 | + sc200ai->reset_gpio = devm_gpiod_get(dev, "reset", sc200ai->is_thunderboot ? GPIOD_ASIS : GPIOD_OUT_LOW); |
---|
1719 | 2043 | if (IS_ERR(sc200ai->reset_gpio)) |
---|
1720 | 2044 | dev_warn(dev, "Failed to get reset-gpios\n"); |
---|
1721 | 2045 | |
---|
1722 | | - sc200ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); |
---|
| 2046 | + sc200ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", sc200ai->is_thunderboot ? GPIOD_ASIS : GPIOD_OUT_LOW); |
---|
1723 | 2047 | if (IS_ERR(sc200ai->pwdn_gpio)) |
---|
1724 | 2048 | dev_warn(dev, "Failed to get pwdn-gpios\n"); |
---|
1725 | 2049 | |
---|
.. | .. |
---|
1775 | 2099 | goto err_power_off; |
---|
1776 | 2100 | #endif |
---|
1777 | 2101 | |
---|
| 2102 | + if (!sc200ai->cam_sw_inf) { |
---|
| 2103 | + sc200ai->cam_sw_inf = cam_sw_init(); |
---|
| 2104 | + cam_sw_clk_init(sc200ai->cam_sw_inf, sc200ai->xvclk, SC200AI_XVCLK_FREQ); |
---|
| 2105 | + cam_sw_reset_pin_init(sc200ai->cam_sw_inf, sc200ai->reset_gpio, 0); |
---|
| 2106 | + cam_sw_pwdn_pin_init(sc200ai->cam_sw_inf, sc200ai->pwdn_gpio, 1); |
---|
| 2107 | + } |
---|
| 2108 | + |
---|
1778 | 2109 | memset(facing, 0, sizeof(facing)); |
---|
1779 | 2110 | if (strcmp(sc200ai->module_facing, "back") == 0) |
---|
1780 | 2111 | facing[0] = 'b'; |
---|
.. | .. |
---|
1792 | 2123 | |
---|
1793 | 2124 | pm_runtime_set_active(dev); |
---|
1794 | 2125 | pm_runtime_enable(dev); |
---|
1795 | | - pm_runtime_idle(dev); |
---|
| 2126 | + if (sc200ai->is_thunderboot) |
---|
| 2127 | + pm_runtime_get_sync(dev); |
---|
| 2128 | + else |
---|
| 2129 | + pm_runtime_idle(dev); |
---|
1796 | 2130 | |
---|
1797 | 2131 | return 0; |
---|
1798 | 2132 | |
---|
.. | .. |
---|
1821 | 2155 | #endif |
---|
1822 | 2156 | v4l2_ctrl_handler_free(&sc200ai->ctrl_handler); |
---|
1823 | 2157 | mutex_destroy(&sc200ai->mutex); |
---|
| 2158 | + |
---|
| 2159 | + cam_sw_deinit(sc200ai->cam_sw_inf); |
---|
1824 | 2160 | |
---|
1825 | 2161 | pm_runtime_disable(&client->dev); |
---|
1826 | 2162 | if (!pm_runtime_status_suspended(&client->dev)) |
---|
.. | .. |
---|
1864 | 2200 | i2c_del_driver(&sc200ai_i2c_driver); |
---|
1865 | 2201 | } |
---|
1866 | 2202 | |
---|
| 2203 | +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) |
---|
| 2204 | +subsys_initcall(sensor_mod_init); |
---|
| 2205 | +#else |
---|
1867 | 2206 | device_initcall_sync(sensor_mod_init); |
---|
| 2207 | +#endif |
---|
1868 | 2208 | module_exit(sensor_mod_exit); |
---|
1869 | 2209 | |
---|
1870 | 2210 | MODULE_DESCRIPTION("smartsens sc200ai sensor driver"); |
---|
1871 | | -MODULE_LICENSE("GPL v2"); |
---|
| 2211 | +MODULE_LICENSE("GPL"); |
---|