forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/media/i2c/sc230ai.c
....@@ -61,9 +61,6 @@
6161 #define SC230AI_REG_SEXPOSURE_L 0x3e05
6262 #define SC230AI_EXPOSURE_MIN 1
6363 #define SC230AI_EXPOSURE_STEP 1
64
-#define SC230AI_EXPOSURE_LIN_MAX (2 * 0x465 - 9)
65
-#define SC230AI_EXPOSURE_HDR_MAX_S (2 * 0x465 - 9)
66
-#define SC230AI_EXPOSURE_HDR_MAX_L (2 * 0x465 - 9)
6764 #define SC230AI_VTS_MAX 0x7fff
6865
6966 #define SC230AI_REG_DIG_GAIN 0x3e06
....@@ -74,7 +71,7 @@
7471 #define SC230AI_REG_SANA_GAIN 0x3e12
7572 #define SC230AI_REG_SANA_FINE_GAIN 0x3e13
7673 #define SC230AI_GAIN_MIN 1000
77
-#define SC230AI_GAIN_MAX 1722628 //108.512*15.875*1000
74
+#define SC230AI_GAIN_MAX 1574800 // 99.2*15.875*1000
7875 #define SC230AI_GAIN_STEP 1
7976 #define SC230AI_GAIN_DEFAULT 1000
8077 #define SC230AI_LGAIN 0
....@@ -176,6 +173,7 @@
176173 const char *module_facing;
177174 const char *module_name;
178175 const char *len_name;
176
+ enum rkmodule_sync_mode sync_mode;
179177 u32 cur_vts;
180178 bool has_init_exp;
181179 bool is_thunderboot;
....@@ -537,6 +535,28 @@
537535 {REG_NULL, 0x00},
538536 };
539537
538
+static __maybe_unused const struct regval sc230ai_interal_sync_master_start_regs[] = {
539
+ {0x300a, 0x24}, //sync as output PAD
540
+ {0x3032, 0xa0},
541
+ {0x3222, 0x00}, //master mode
542
+ {REG_NULL, 0x00},
543
+};
544
+
545
+static __maybe_unused const struct regval sc230ai_interal_sync_master_stop_regs[] = {
546
+ {REG_NULL, 0x00},
547
+};
548
+
549
+static __maybe_unused const struct regval sc230ai_interal_sync_slaver_start_regs[] = {
550
+ {0x300a, 0x20}, //sync as input PAD
551
+ {0x3222, 0x01}, //slave mode
552
+ {0x3224, 0x92}, //fsync trigger
553
+ {0x3614, 0x01},
554
+ {REG_NULL, 0x00},
555
+};
556
+
557
+static __maybe_unused const struct regval sc230ai_interal_sync_slaver_stop_regs[] = {
558
+ {REG_NULL, 0x00},
559
+};
540560
541561 static const struct sc230ai_mode supported_modes[] = {
542562 {
....@@ -678,46 +698,46 @@
678698 *again = 0x00;
679699 *dgain = 0x00;
680700 *dgain_fine = total_gain * 128 / 1000;
681
- } else if (total_gain < 3391) { /* 2 ~ 3.391 gain*/
701
+ } else if (total_gain < 3100) { /* 2 ~ 3.1 gain*/
682702 *again = 0x01;
683703 *dgain = 0x00;
684704 *dgain_fine = total_gain * 128 / 1000 / 2;
685
- } else if (total_gain < 3391 * 2) { /* 3.391 ~ 6.782 gain*/
705
+ } else if (total_gain < 3100 * 2) { /* 3.100 ~ 6.200 gain*/
686706 *again = 0x40;
687707 *dgain = 0x00;
688
- *dgain_fine = total_gain * 128 / 3391;
689
- } else if (total_gain < 3391 * 4) { /* 6.782 ~ 13.564 gain*/
708
+ *dgain_fine = total_gain * 128 / 3100;
709
+ } else if (total_gain < 3100 * 4) { /* 6.200 ~ 12.400 gain*/
690710 *again = 0x48;
691711 *dgain = 0x00;
692
- *dgain_fine = total_gain * 128 / 3391 / 2;
693
- } else if (total_gain < 3391 * 8) { /* 13.564 ~ 27.128 gain*/
712
+ *dgain_fine = total_gain * 128 / 3100 / 2;
713
+ } else if (total_gain < 3100 * 8) { /* 12.400 ~ 24.800 gain*/
694714 *again = 0x49;
695715 *dgain = 0x00;
696
- *dgain_fine = total_gain * 128 / 3391 / 4;
697
- } else if (total_gain < 3391 * 16) { /* 27.128 ~ 54.256 gain*/
716
+ *dgain_fine = total_gain * 128 / 3100 / 4;
717
+ } else if (total_gain < 3100 * 16) { /* 24.800 ~ 49.600 gain*/
698718 *again = 0x4b;
699719 *dgain = 0x00;
700
- *dgain_fine = total_gain * 128 / 3391 / 8;
701
- } else if (total_gain < 3391 * 32) { /* 54.256 ~ 108.512 gain*/
720
+ *dgain_fine = total_gain * 128 / 3100 / 8;
721
+ } else if (total_gain < 3100 * 32) { /* 49.600 ~ 99.200 gain*/
702722 *again = 0x4f;
703723 *dgain = 0x00;
704
- *dgain_fine = total_gain * 128 / 3391 / 16;
705
- } else if (total_gain < 3391 * 64) { /* 108.512 ~ 217.024 gain*/
724
+ *dgain_fine = total_gain * 128 / 3100 / 16;
725
+ } else if (total_gain < 3100 * 64) { /* 99.200 ~ 198.400 gain*/
706726 *again = 0x5f;
707727 *dgain = 0x00;
708
- *dgain_fine = total_gain * 128 / 3391 / 32;
709
- } else if (total_gain < 3391 * 128) { /* 217.024 ~ 434.048 gain*/
728
+ *dgain_fine = total_gain * 128 / 3100 / 32;
729
+ } else if (total_gain < 3100 * 128) { /* 198.400 ~ 396.800 gain*/
710730 *again = 0x5f;
711731 *dgain = 0x01;
712
- *dgain_fine = total_gain * 128 / 3391 / 64;
713
- } else if (total_gain < 3391 * 256) { /* 434.048 ~ 868.096 gain*/
732
+ *dgain_fine = total_gain * 128 / 3100 / 64;
733
+ } else if (total_gain < 3100 * 256) { /* 396.800 ~ 793.600 gain*/
714734 *again = 0x5f;
715735 *dgain = 0x03;
716
- *dgain_fine = total_gain * 128 / 3391 / 128;
717
- } else if (total_gain < 3391 * 512) { /* 868.096 ~ 1736.192 gain*/
736
+ *dgain_fine = total_gain * 128 / 3100 / 128;
737
+ } else { /* 793.600 ~ 1587.200 gain*/
718738 *again = 0x5f;
719739 *dgain = 0x07;
720
- *dgain_fine = total_gain * 128 / 3391 / 128;
740
+ *dgain_fine = total_gain * 128 / 3100 / 128;
721741 }
722742
723743 return ret;
....@@ -933,6 +953,7 @@
933953 u32 i, h, w;
934954 long ret = 0;
935955 u32 stream = 0;
956
+ u32 *sync_mode = NULL;
936957
937958 switch (cmd) {
938959 case RKMODULE_GET_MODULE_INFO:
....@@ -983,6 +1004,14 @@
9831004 ret = sc230ai_write_reg(sc230ai->client, SC230AI_REG_CTRL_MODE,
9841005 SC230AI_REG_VALUE_08BIT, SC230AI_MODE_SW_STANDBY);
9851006 break;
1007
+ case RKMODULE_GET_SYNC_MODE:
1008
+ sync_mode = (u32 *)arg;
1009
+ *sync_mode = sc230ai->sync_mode;
1010
+ break;
1011
+ case RKMODULE_SET_SYNC_MODE:
1012
+ sync_mode = (u32 *)arg;
1013
+ sc230ai->sync_mode = *sync_mode;
1014
+ break;
9861015 default:
9871016 ret = -ENOIOCTLCMD;
9881017 break;
....@@ -1001,6 +1030,7 @@
10011030 struct preisp_hdrae_exp_s *hdrae;
10021031 long ret;
10031032 u32 stream = 0;
1033
+ u32 sync_mode;
10041034
10051035 switch (cmd) {
10061036 case RKMODULE_GET_MODULE_INFO:
....@@ -1069,6 +1099,21 @@
10691099
10701100 ret = sc230ai_ioctl(sd, cmd, &stream);
10711101 break;
1102
+ case RKMODULE_GET_SYNC_MODE:
1103
+ ret = sc230ai_ioctl(sd, cmd, &sync_mode);
1104
+ if (!ret) {
1105
+ ret = copy_to_user(up, &sync_mode, sizeof(u32));
1106
+ if (ret)
1107
+ ret = -EFAULT;
1108
+ }
1109
+ break;
1110
+ case RKMODULE_SET_SYNC_MODE:
1111
+ ret = copy_from_user(&sync_mode, up, sizeof(u32));
1112
+ if (!ret)
1113
+ ret = sc230ai_ioctl(sd, cmd, &sync_mode);
1114
+ else
1115
+ ret = -EFAULT;
1116
+ break;
10721117 default:
10731118 ret = -ENOIOCTLCMD;
10741119 break;
....@@ -1080,7 +1125,7 @@
10801125
10811126 static int __sc230ai_start_stream(struct sc230ai *sc230ai)
10821127 {
1083
- int ret;
1128
+ int ret = 0;
10841129
10851130 if (!sc230ai->is_thunderboot) {
10861131 ret = sc230ai_write_array(sc230ai->client, sc230ai->cur_mode->reg_list);
....@@ -1099,20 +1144,36 @@
10991144 return ret;
11001145 }
11011146 }
1147
+ if (sc230ai->sync_mode == INTERNAL_MASTER_MODE)
1148
+ ret |= sc230ai_write_array(sc230ai->client,
1149
+ sc230ai_interal_sync_master_start_regs);
1150
+ else if (sc230ai->sync_mode == SLAVE_MODE)
1151
+ ret |= sc230ai_write_array(sc230ai->client,
1152
+ sc230ai_interal_sync_slaver_start_regs);
11021153 }
1103
- return sc230ai_write_reg(sc230ai->client, SC230AI_REG_CTRL_MODE,
1154
+ ret |= sc230ai_write_reg(sc230ai->client, SC230AI_REG_CTRL_MODE,
11041155 SC230AI_REG_VALUE_08BIT, SC230AI_MODE_STREAMING);
1156
+ return ret;
11051157 }
11061158
11071159 static int __sc230ai_stop_stream(struct sc230ai *sc230ai)
11081160 {
1161
+ int ret = 0;
11091162 sc230ai->has_init_exp = false;
11101163 if (sc230ai->is_thunderboot) {
11111164 sc230ai->is_first_streamoff = true;
11121165 pm_runtime_put(&sc230ai->client->dev);
1166
+ } else {
1167
+ if (sc230ai->sync_mode == INTERNAL_MASTER_MODE)
1168
+ ret |= sc230ai_write_array(sc230ai->client,
1169
+ sc230ai_interal_sync_master_stop_regs);
1170
+ else if (sc230ai->sync_mode == SLAVE_MODE)
1171
+ ret |= sc230ai_write_array(sc230ai->client,
1172
+ sc230ai_interal_sync_slaver_stop_regs);
11131173 }
1114
- return sc230ai_write_reg(sc230ai->client, SC230AI_REG_CTRL_MODE,
1174
+ ret |= sc230ai_write_reg(sc230ai->client, SC230AI_REG_CTRL_MODE,
11151175 SC230AI_REG_VALUE_08BIT, SC230AI_MODE_SW_STANDBY);
1176
+ return ret;
11161177 }
11171178
11181179 static int __sc230ai_power_on(struct sc230ai *sc230ai);
....@@ -1406,7 +1467,7 @@
14061467 switch (ctrl->id) {
14071468 case V4L2_CID_VBLANK:
14081469 /* Update max exposure while meeting expected vblanking */
1409
- max = sc230ai->cur_mode->height + ctrl->val - 4;
1470
+ max = sc230ai->cur_mode->height + ctrl->val - 5;
14101471 __v4l2_ctrl_modify_range(sc230ai->exposure,
14111472 sc230ai->exposure->minimum, max,
14121473 sc230ai->exposure->step,
....@@ -1469,8 +1530,7 @@
14691530 (ctrl->val + sc230ai->cur_mode->height)
14701531 & 0xff);
14711532 sc230ai->cur_vts = ctrl->val + sc230ai->cur_mode->height;
1472
- if (sc230ai->cur_vts != sc230ai->cur_mode->vts_def)
1473
- sc230ai_modify_fps_info(sc230ai);
1533
+ sc230ai_modify_fps_info(sc230ai);
14741534 break;
14751535 case V4L2_CID_TEST_PATTERN:
14761536 ret = sc230ai_enable_test_pattern(sc230ai, ctrl->val);
....@@ -1546,7 +1606,7 @@
15461606 V4L2_CID_VBLANK, vblank_def,
15471607 SC230AI_VTS_MAX - mode->height,
15481608 1, vblank_def);
1549
- exposure_max = SC230AI_EXPOSURE_LIN_MAX;
1609
+ exposure_max = mode->vts_def - 5;
15501610 sc230ai->exposure = v4l2_ctrl_new_std(handler, &sc230ai_ctrl_ops,
15511611 V4L2_CID_EXPOSURE, SC230AI_EXPOSURE_MIN,
15521612 exposure_max, SC230AI_EXPOSURE_STEP,
....@@ -1629,6 +1689,7 @@
16291689 char facing[2];
16301690 int ret;
16311691 u32 i, hdr_mode = 0;
1692
+ const char *sync_mode_name = NULL;
16321693
16331694 dev_info(dev, "driver version: %02x.%02x.%02x",
16341695 DRIVER_VERSION >> 16,
....@@ -1652,6 +1713,25 @@
16521713 dev_err(dev, "could not get module information!\n");
16531714 return -EINVAL;
16541715 }
1716
+
1717
+ ret = of_property_read_string(node, RKMODULE_CAMERA_SYNC_MODE,
1718
+ &sync_mode_name);
1719
+ if (ret) {
1720
+ sc230ai->sync_mode = NO_SYNC_MODE;
1721
+ dev_err(dev, "could not get sync mode!\n");
1722
+ } else {
1723
+ if (strcmp(sync_mode_name, RKMODULE_EXTERNAL_MASTER_MODE) == 0) {
1724
+ sc230ai->sync_mode = EXTERNAL_MASTER_MODE;
1725
+ dev_info(dev, "external master mode\n");
1726
+ } else if (strcmp(sync_mode_name, RKMODULE_INTERNAL_MASTER_MODE) == 0) {
1727
+ sc230ai->sync_mode = INTERNAL_MASTER_MODE;
1728
+ dev_info(dev, "internal master mode\n");
1729
+ } else if (strcmp(sync_mode_name, RKMODULE_SLAVE_MODE) == 0) {
1730
+ sc230ai->sync_mode = SLAVE_MODE;
1731
+ dev_info(dev, "slave mode\n");
1732
+ }
1733
+ }
1734
+
16551735 sc230ai->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP);
16561736 sc230ai->client = client;
16571737 for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {