.. | .. |
---|
5 | 5 | * Copyright (C) 2020 Rockchip Electronics Co., Ltd. |
---|
6 | 6 | * |
---|
7 | 7 | * V0.0X01.0X01 first version |
---|
| 8 | + * V0.0X01.0X02 support fastboot |
---|
8 | 9 | */ |
---|
9 | 10 | |
---|
10 | 11 | //#define DEBUG |
---|
.. | .. |
---|
26 | 27 | #include <media/v4l2-ctrls.h> |
---|
27 | 28 | #include <media/v4l2-subdev.h> |
---|
28 | 29 | #include <linux/pinctrl/consumer.h> |
---|
| 30 | +#include "../platform/rockchip/isp/rkisp_tb_helper.h" |
---|
29 | 31 | |
---|
30 | 32 | #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01) |
---|
31 | 33 | |
---|
.. | .. |
---|
110 | 112 | u8 val; |
---|
111 | 113 | }; |
---|
112 | 114 | |
---|
113 | | -enum sc4336_max_pad { |
---|
114 | | - PAD0, /* link to isp */ |
---|
115 | | - PAD1, /* link to csi wr0 | hdr x2:L x3:M */ |
---|
116 | | - PAD2, /* link to csi wr1 | hdr x3:L */ |
---|
117 | | - PAD3, /* link to csi wr2 | hdr x2:M x3:S */ |
---|
118 | | - PAD_MAX, |
---|
119 | | -}; |
---|
120 | | - |
---|
121 | 115 | struct sc4336_mode { |
---|
122 | 116 | u32 bus_fmt; |
---|
123 | 117 | u32 width; |
---|
.. | .. |
---|
155 | 149 | bool streaming; |
---|
156 | 150 | bool power_on; |
---|
157 | 151 | const struct sc4336_mode *cur_mode; |
---|
| 152 | + struct v4l2_fract cur_fps; |
---|
158 | 153 | u32 module_index; |
---|
159 | 154 | const char *module_facing; |
---|
160 | 155 | const char *module_name; |
---|
161 | 156 | const char *len_name; |
---|
162 | 157 | u32 cur_vts; |
---|
| 158 | + bool is_thunderboot; |
---|
| 159 | + bool is_first_streamoff; |
---|
163 | 160 | }; |
---|
164 | 161 | |
---|
165 | 162 | #define to_sc4336(sd) container_of(sd, struct sc4336, subdev) |
---|
.. | .. |
---|
314 | 311 | {0x5aed, 0x2c}, |
---|
315 | 312 | {0x36e9, 0x53}, |
---|
316 | 313 | {0x37f9, 0x23}, |
---|
| 314 | + {0x320e, 0x07}, |
---|
| 315 | + {0x320f, 0x08}, |
---|
317 | 316 | {REG_NULL, 0x00}, |
---|
318 | 317 | }; |
---|
319 | 318 | |
---|
.. | .. |
---|
323 | 322 | .height = 1440, |
---|
324 | 323 | .max_fps = { |
---|
325 | 324 | .numerator = 10000, |
---|
326 | | - .denominator = 300000, |
---|
| 325 | + .denominator = 250000, |
---|
327 | 326 | }, |
---|
328 | 327 | .exp_def = 0x0080, |
---|
329 | 328 | .hts_def = 0x0578 * 2, |
---|
330 | | - .vts_def = 0x05dc, |
---|
| 329 | + .vts_def = 0x0708, |
---|
331 | 330 | .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, |
---|
332 | 331 | .reg_list = sc4336_linear_10_2560x1440_regs, |
---|
333 | 332 | .hdr_mode = NO_HDR, |
---|
.. | .. |
---|
552 | 551 | __v4l2_ctrl_modify_range(sc4336->vblank, vblank_def, |
---|
553 | 552 | SC4336_VTS_MAX - mode->height, |
---|
554 | 553 | 1, vblank_def); |
---|
| 554 | + sc4336->cur_fps = mode->max_fps; |
---|
555 | 555 | } |
---|
556 | 556 | |
---|
557 | 557 | mutex_unlock(&sc4336->mutex); |
---|
.. | .. |
---|
644 | 644 | struct sc4336 *sc4336 = to_sc4336(sd); |
---|
645 | 645 | const struct sc4336_mode *mode = sc4336->cur_mode; |
---|
646 | 646 | |
---|
647 | | - mutex_lock(&sc4336->mutex); |
---|
648 | | - fi->interval = mode->max_fps; |
---|
649 | | - mutex_unlock(&sc4336->mutex); |
---|
| 647 | + if (sc4336->streaming) |
---|
| 648 | + fi->interval = sc4336->cur_fps; |
---|
| 649 | + else |
---|
| 650 | + fi->interval = mode->max_fps; |
---|
650 | 651 | |
---|
651 | 652 | return 0; |
---|
652 | 653 | } |
---|
653 | 654 | |
---|
654 | 655 | static int sc4336_g_mbus_config(struct v4l2_subdev *sd, |
---|
| 656 | + unsigned int pad_id, |
---|
655 | 657 | struct v4l2_mbus_config *config) |
---|
656 | 658 | { |
---|
657 | 659 | struct sc4336 *sc4336 = to_sc4336(sd); |
---|
.. | .. |
---|
665 | 667 | if (mode->hdr_mode == HDR_X3) |
---|
666 | 668 | val |= V4L2_MBUS_CSI2_CHANNEL_2; |
---|
667 | 669 | |
---|
668 | | - config->type = V4L2_MBUS_CSI2; |
---|
| 670 | + config->type = V4L2_MBUS_CSI2_DPHY; |
---|
669 | 671 | config->flags = val; |
---|
670 | 672 | |
---|
671 | 673 | return 0; |
---|
.. | .. |
---|
831 | 833 | static int __sc4336_start_stream(struct sc4336 *sc4336) |
---|
832 | 834 | { |
---|
833 | 835 | int ret; |
---|
| 836 | + if (!sc4336->is_thunderboot) { |
---|
| 837 | + ret = sc4336_write_array(sc4336->client, sc4336->cur_mode->reg_list); |
---|
| 838 | + if (ret) |
---|
| 839 | + return ret; |
---|
834 | 840 | |
---|
835 | | - ret = sc4336_write_array(sc4336->client, sc4336->cur_mode->reg_list); |
---|
836 | | - if (ret) |
---|
837 | | - return ret; |
---|
838 | | - |
---|
839 | | - /* In case these controls are set before streaming */ |
---|
840 | | - ret = __v4l2_ctrl_handler_setup(&sc4336->ctrl_handler); |
---|
841 | | - if (ret) |
---|
842 | | - return ret; |
---|
| 841 | + /* In case these controls are set before streaming */ |
---|
| 842 | + ret = __v4l2_ctrl_handler_setup(&sc4336->ctrl_handler); |
---|
| 843 | + if (ret) |
---|
| 844 | + return ret; |
---|
| 845 | + } |
---|
843 | 846 | |
---|
844 | 847 | return sc4336_write_reg(sc4336->client, SC4336_REG_CTRL_MODE, |
---|
845 | 848 | SC4336_REG_VALUE_08BIT, SC4336_MODE_STREAMING); |
---|
.. | .. |
---|
847 | 850 | |
---|
848 | 851 | static int __sc4336_stop_stream(struct sc4336 *sc4336) |
---|
849 | 852 | { |
---|
| 853 | + if (sc4336->is_thunderboot) { |
---|
| 854 | + sc4336->is_first_streamoff = true; |
---|
| 855 | + pm_runtime_put(&sc4336->client->dev); |
---|
| 856 | + } |
---|
850 | 857 | return sc4336_write_reg(sc4336->client, SC4336_REG_CTRL_MODE, |
---|
851 | 858 | SC4336_REG_VALUE_08BIT, SC4336_MODE_SW_STANDBY); |
---|
852 | 859 | } |
---|
853 | 860 | |
---|
| 861 | +static int __sc4336_power_on(struct sc4336 *sc4336); |
---|
854 | 862 | static int sc4336_s_stream(struct v4l2_subdev *sd, int on) |
---|
855 | 863 | { |
---|
856 | 864 | struct sc4336 *sc4336 = to_sc4336(sd); |
---|
.. | .. |
---|
863 | 871 | goto unlock_and_return; |
---|
864 | 872 | |
---|
865 | 873 | if (on) { |
---|
| 874 | + if (sc4336->is_thunderboot && rkisp_tb_get_state() == RKISP_TB_NG) { |
---|
| 875 | + sc4336->is_thunderboot = false; |
---|
| 876 | + __sc4336_power_on(sc4336); |
---|
| 877 | + } |
---|
| 878 | + |
---|
866 | 879 | ret = pm_runtime_get_sync(&client->dev); |
---|
867 | 880 | if (ret < 0) { |
---|
868 | 881 | pm_runtime_put_noidle(&client->dev); |
---|
.. | .. |
---|
907 | 920 | goto unlock_and_return; |
---|
908 | 921 | } |
---|
909 | 922 | |
---|
910 | | - ret = sc4336_write_array(sc4336->client, sc4336_global_regs); |
---|
911 | | - if (ret) { |
---|
912 | | - v4l2_err(sd, "could not set init registers\n"); |
---|
913 | | - pm_runtime_put_noidle(&client->dev); |
---|
914 | | - goto unlock_and_return; |
---|
| 923 | + if (!sc4336->is_thunderboot) { |
---|
| 924 | + ret = sc4336_write_array(sc4336->client, sc4336_global_regs); |
---|
| 925 | + if (ret) { |
---|
| 926 | + v4l2_err(sd, "could not set init registers\n"); |
---|
| 927 | + pm_runtime_put_noidle(&client->dev); |
---|
| 928 | + goto unlock_and_return; |
---|
| 929 | + } |
---|
915 | 930 | } |
---|
916 | 931 | |
---|
917 | 932 | sc4336->power_on = true; |
---|
.. | .. |
---|
954 | 969 | dev_err(dev, "Failed to enable xvclk\n"); |
---|
955 | 970 | return ret; |
---|
956 | 971 | } |
---|
| 972 | + if (sc4336->is_thunderboot) |
---|
| 973 | + return 0; |
---|
| 974 | + |
---|
957 | 975 | if (!IS_ERR(sc4336->reset_gpio)) |
---|
958 | 976 | gpiod_set_value_cansleep(sc4336->reset_gpio, 0); |
---|
959 | 977 | |
---|
.. | .. |
---|
992 | 1010 | int ret; |
---|
993 | 1011 | struct device *dev = &sc4336->client->dev; |
---|
994 | 1012 | |
---|
| 1013 | + clk_disable_unprepare(sc4336->xvclk); |
---|
| 1014 | + if (sc4336->is_thunderboot) { |
---|
| 1015 | + if (sc4336->is_first_streamoff) { |
---|
| 1016 | + sc4336->is_thunderboot = false; |
---|
| 1017 | + sc4336->is_first_streamoff = false; |
---|
| 1018 | + } else { |
---|
| 1019 | + return; |
---|
| 1020 | + } |
---|
| 1021 | + } |
---|
| 1022 | + |
---|
995 | 1023 | if (!IS_ERR(sc4336->pwdn_gpio)) |
---|
996 | 1024 | gpiod_set_value_cansleep(sc4336->pwdn_gpio, 0); |
---|
997 | | - clk_disable_unprepare(sc4336->xvclk); |
---|
998 | 1025 | if (!IS_ERR(sc4336->reset_gpio)) |
---|
999 | 1026 | gpiod_set_value_cansleep(sc4336->reset_gpio, 0); |
---|
1000 | 1027 | if (!IS_ERR_OR_NULL(sc4336->pins_sleep)) { |
---|
.. | .. |
---|
1006 | 1033 | regulator_bulk_disable(SC4336_NUM_SUPPLIES, sc4336->supplies); |
---|
1007 | 1034 | } |
---|
1008 | 1035 | |
---|
1009 | | -static int sc4336_runtime_resume(struct device *dev) |
---|
| 1036 | +static int __maybe_unused sc4336_runtime_resume(struct device *dev) |
---|
1010 | 1037 | { |
---|
1011 | 1038 | struct i2c_client *client = to_i2c_client(dev); |
---|
1012 | 1039 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
---|
.. | .. |
---|
1015 | 1042 | return __sc4336_power_on(sc4336); |
---|
1016 | 1043 | } |
---|
1017 | 1044 | |
---|
1018 | | -static int sc4336_runtime_suspend(struct device *dev) |
---|
| 1045 | +static int __maybe_unused sc4336_runtime_suspend(struct device *dev) |
---|
1019 | 1046 | { |
---|
1020 | 1047 | struct i2c_client *client = to_i2c_client(dev); |
---|
1021 | 1048 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
---|
.. | .. |
---|
1085 | 1112 | static const struct v4l2_subdev_video_ops sc4336_video_ops = { |
---|
1086 | 1113 | .s_stream = sc4336_s_stream, |
---|
1087 | 1114 | .g_frame_interval = sc4336_g_frame_interval, |
---|
1088 | | - .g_mbus_config = sc4336_g_mbus_config, |
---|
1089 | 1115 | }; |
---|
1090 | 1116 | |
---|
1091 | 1117 | static const struct v4l2_subdev_pad_ops sc4336_pad_ops = { |
---|
.. | .. |
---|
1094 | 1120 | .enum_frame_interval = sc4336_enum_frame_interval, |
---|
1095 | 1121 | .get_fmt = sc4336_get_fmt, |
---|
1096 | 1122 | .set_fmt = sc4336_set_fmt, |
---|
| 1123 | + .get_mbus_config = sc4336_g_mbus_config, |
---|
1097 | 1124 | }; |
---|
1098 | 1125 | |
---|
1099 | 1126 | static const struct v4l2_subdev_ops sc4336_subdev_ops = { |
---|
.. | .. |
---|
1101 | 1128 | .video = &sc4336_video_ops, |
---|
1102 | 1129 | .pad = &sc4336_pad_ops, |
---|
1103 | 1130 | }; |
---|
| 1131 | + |
---|
| 1132 | +static void sc4336_modify_fps_info(struct sc4336 *sc4336) |
---|
| 1133 | +{ |
---|
| 1134 | + const struct sc4336_mode *mode = sc4336->cur_mode; |
---|
| 1135 | + |
---|
| 1136 | + sc4336->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / |
---|
| 1137 | + sc4336->cur_vts; |
---|
| 1138 | +} |
---|
1104 | 1139 | |
---|
1105 | 1140 | static int sc4336_set_ctrl(struct v4l2_ctrl *ctrl) |
---|
1106 | 1141 | { |
---|
.. | .. |
---|
1164 | 1199 | (ctrl->val + sc4336->cur_mode->height) |
---|
1165 | 1200 | & 0xff); |
---|
1166 | 1201 | sc4336->cur_vts = ctrl->val + sc4336->cur_mode->height; |
---|
| 1202 | + sc4336_modify_fps_info(sc4336); |
---|
1167 | 1203 | break; |
---|
1168 | 1204 | case V4L2_CID_TEST_PATTERN: |
---|
1169 | 1205 | ret = sc4336_enable_test_pattern(sc4336, ctrl->val); |
---|
.. | .. |
---|
1231 | 1267 | V4L2_CID_VBLANK, vblank_def, |
---|
1232 | 1268 | SC4336_VTS_MAX - mode->height, |
---|
1233 | 1269 | 1, vblank_def); |
---|
| 1270 | + sc4336->cur_fps = mode->max_fps; |
---|
1234 | 1271 | exposure_max = mode->vts_def - 8; |
---|
1235 | 1272 | sc4336->exposure = v4l2_ctrl_new_std(handler, &sc4336_ctrl_ops, |
---|
1236 | 1273 | V4L2_CID_EXPOSURE, SC4336_EXPOSURE_MIN, |
---|
.. | .. |
---|
1272 | 1309 | struct device *dev = &sc4336->client->dev; |
---|
1273 | 1310 | u32 id = 0; |
---|
1274 | 1311 | int ret; |
---|
| 1312 | + |
---|
| 1313 | + if (sc4336->is_thunderboot) { |
---|
| 1314 | + dev_info(dev, "Enable thunderboot mode, skip sensor id check\n"); |
---|
| 1315 | + return 0; |
---|
| 1316 | + } |
---|
1275 | 1317 | |
---|
1276 | 1318 | ret = sc4336_read_reg(client, SC4336_REG_CHIP_ID, |
---|
1277 | 1319 | SC4336_REG_VALUE_16BIT, &id); |
---|
.. | .. |
---|
1329 | 1371 | return -EINVAL; |
---|
1330 | 1372 | } |
---|
1331 | 1373 | |
---|
| 1374 | + sc4336->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); |
---|
1332 | 1375 | sc4336->client = client; |
---|
1333 | 1376 | sc4336->cur_mode = &supported_modes[0]; |
---|
1334 | 1377 | |
---|
.. | .. |
---|
1338 | 1381 | return -EINVAL; |
---|
1339 | 1382 | } |
---|
1340 | 1383 | |
---|
1341 | | - sc4336->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); |
---|
1342 | | - if (IS_ERR(sc4336->reset_gpio)) |
---|
1343 | | - dev_warn(dev, "Failed to get reset-gpios\n"); |
---|
| 1384 | + if (sc4336->is_thunderboot) { |
---|
| 1385 | + sc4336->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS); |
---|
| 1386 | + if (IS_ERR(sc4336->reset_gpio)) |
---|
| 1387 | + dev_warn(dev, "Failed to get reset-gpios\n"); |
---|
1344 | 1388 | |
---|
1345 | | - sc4336->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); |
---|
1346 | | - if (IS_ERR(sc4336->pwdn_gpio)) |
---|
1347 | | - dev_warn(dev, "Failed to get pwdn-gpios\n"); |
---|
| 1389 | + sc4336->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_ASIS); |
---|
| 1390 | + if (IS_ERR(sc4336->pwdn_gpio)) |
---|
| 1391 | + dev_warn(dev, "Failed to get pwdn-gpios\n"); |
---|
| 1392 | + } else { |
---|
| 1393 | + sc4336->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); |
---|
| 1394 | + if (IS_ERR(sc4336->reset_gpio)) |
---|
| 1395 | + dev_warn(dev, "Failed to get reset-gpios\n"); |
---|
1348 | 1396 | |
---|
| 1397 | + sc4336->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); |
---|
| 1398 | + if (IS_ERR(sc4336->pwdn_gpio)) |
---|
| 1399 | + dev_warn(dev, "Failed to get pwdn-gpios\n"); |
---|
| 1400 | + } |
---|
1349 | 1401 | sc4336->pinctrl = devm_pinctrl_get(dev); |
---|
1350 | 1402 | if (!IS_ERR(sc4336->pinctrl)) { |
---|
1351 | 1403 | sc4336->pins_default = |
---|
.. | .. |
---|
1415 | 1467 | |
---|
1416 | 1468 | pm_runtime_set_active(dev); |
---|
1417 | 1469 | pm_runtime_enable(dev); |
---|
1418 | | - pm_runtime_idle(dev); |
---|
| 1470 | + if (sc4336->is_thunderboot) |
---|
| 1471 | + pm_runtime_get_sync(dev); |
---|
| 1472 | + else |
---|
| 1473 | + pm_runtime_idle(dev); |
---|
1419 | 1474 | |
---|
1420 | 1475 | return 0; |
---|
1421 | 1476 | |
---|
.. | .. |
---|
1487 | 1542 | i2c_del_driver(&sc4336_i2c_driver); |
---|
1488 | 1543 | } |
---|
1489 | 1544 | |
---|
| 1545 | +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) |
---|
| 1546 | +subsys_initcall(sensor_mod_init); |
---|
| 1547 | +#else |
---|
1490 | 1548 | device_initcall_sync(sensor_mod_init); |
---|
| 1549 | +#endif |
---|
1491 | 1550 | module_exit(sensor_mod_exit); |
---|
1492 | 1551 | |
---|
1493 | 1552 | MODULE_DESCRIPTION("smartsens sc4336 sensor driver"); |
---|