forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/media/i2c/lt6911uxc.c
....@@ -6,6 +6,8 @@
66 * V0.0X01.0X00 first version.
77 * V0.0X01.0X01 fix if plugin_gpio was not used.
88 * V0.0X01.0X02 modify driver init level to late_initcall.
9
+ * V0.0X01.0X03 add 4K60 dual mipi support
10
+ *
911 */
1012
1113 #include <linux/clk.h>
....@@ -18,6 +20,7 @@
1820 #include <linux/module.h>
1921 #include <linux/of_graph.h>
2022 #include <linux/rk-camera-module.h>
23
+#include <linux/rk_hdmirx_class.h>
2124 #include <linux/slab.h>
2225 #include <linux/timer.h>
2326 #include <linux/v4l2-dv-timings.h>
....@@ -33,12 +36,16 @@
3336 #include <media/v4l2-fwnode.h>
3437 #include "lt6911uxc.h"
3538
36
-#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x2)
39
+#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x3)
3740 #define LT6911UXC_NAME "LT6911UXC"
3841
39
-#define LT6911UXC_LINK_FREQ_HIGH 400000000
40
-#define LT6911UXC_LINK_FREQ_LOW 200000000
41
-#define LT6911UXC_PIXEL_RATE 400000000
42
+#define LT6911UXC_LINK_FREQ_650M 650000000
43
+#define LT6911UXC_LINK_FREQ_400M 400000000
44
+#define LT6911UXC_LINK_FREQ_300M 300000000
45
+#define LT6911UXC_LINK_FREQ_200M 200000000
46
+#define LT6911UXC_LINK_FREQ_100M 100000000
47
+#define LT6911UXC_LINK_FREQ_60M 60000000
48
+#define LT6911UXC_PIXEL_RATE 600000000
4249
4350 #define I2C_MAX_XFER_SIZE 128
4451
....@@ -53,8 +60,12 @@
5360 MODULE_PARM_DESC(debug, "debug level (0-2)");
5461
5562 static const s64 link_freq_menu_items[] = {
56
- LT6911UXC_LINK_FREQ_HIGH,
57
- LT6911UXC_LINK_FREQ_LOW,
63
+ LT6911UXC_LINK_FREQ_650M,
64
+ LT6911UXC_LINK_FREQ_400M,
65
+ LT6911UXC_LINK_FREQ_300M,
66
+ LT6911UXC_LINK_FREQ_200M,
67
+ LT6911UXC_LINK_FREQ_100M,
68
+ LT6911UXC_LINK_FREQ_60M,
5869 };
5970
6071 struct lt6911uxc {
....@@ -77,6 +88,7 @@
7788 struct v4l2_dv_timings timings;
7889 struct v4l2_fwnode_bus_mipi_csi2 bus;
7990 struct v4l2_subdev sd;
91
+ struct rkmodule_multi_dev_info multi_dev_info;
8092 const char *len_name;
8193 const char *module_facing;
8294 const char *module_name;
....@@ -89,6 +101,7 @@
89101 u32 module_index;
90102 u32 csi_lanes_in_use;
91103 u32 audio_sampling_rate;
104
+ struct device *classdev;
92105 };
93106
94107 struct lt6911uxc_mode {
....@@ -98,13 +111,25 @@
98111 u32 hts_def;
99112 u32 vts_def;
100113 u32 exp_def;
114
+ u32 mipi_freq_idx;
115
+};
116
+
117
+static struct rkmodule_csi_dphy_param rk3588_dcphy_param = {
118
+ .vendor = PHY_VENDOR_SAMSUNG,
119
+ .lp_vol_ref = 3,
120
+ .lp_hys_sw = {3, 0, 3, 0},
121
+ .lp_escclk_pol_sel = {1, 1, 0, 0},
122
+ .skew_data_cal_clk = {0, 0, 0, 0},
123
+ .clk_hs_term_sel = 2,
124
+ .data_hs_term_sel = {2, 2, 2, 2},
125
+ .reserved = {0},
101126 };
102127
103128 static const struct v4l2_dv_timings_cap lt6911uxc_timings_cap = {
104129 .type = V4L2_DV_BT_656_1120,
105130 /* keep this initialization for compatibility with GCC < 4.4.6 */
106131 .reserved = { 0 },
107
- V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 400000000,
132
+ V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 600000000,
108133 V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
109134 V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
110135 V4L2_DV_BT_CAP_PROGRESSIVE |
....@@ -119,10 +144,21 @@
119144 .height = 2160,
120145 .max_fps = {
121146 .numerator = 10000,
147
+ .denominator = 600000,
148
+ },
149
+ .hts_def = 4400,
150
+ .vts_def = 2250,
151
+ .mipi_freq_idx = 0,
152
+ }, {
153
+ .width = 3840,
154
+ .height = 2160,
155
+ .max_fps = {
156
+ .numerator = 10000,
122157 .denominator = 300000,
123158 },
124159 .hts_def = 4400,
125160 .vts_def = 2250,
161
+ .mipi_freq_idx = 0,
126162 }, {
127163 .width = 1920,
128164 .height = 1080,
....@@ -132,6 +168,7 @@
132168 },
133169 .hts_def = 2200,
134170 .vts_def = 1125,
171
+ .mipi_freq_idx = 2,
135172 }, {
136173 .width = 1920,
137174 .height = 540,
....@@ -139,6 +176,7 @@
139176 .numerator = 10000,
140177 .denominator = 600000,
141178 },
179
+ .mipi_freq_idx = 3,
142180 }, {
143181 .width = 1440,
144182 .height = 240,
....@@ -146,6 +184,7 @@
146184 .numerator = 10000,
147185 .denominator = 600000,
148186 },
187
+ .mipi_freq_idx = 4,
149188 }, {
150189 .width = 1440,
151190 .height = 288,
....@@ -153,6 +192,7 @@
153192 .numerator = 10000,
154193 .denominator = 500000,
155194 },
195
+ .mipi_freq_idx = 4,
156196 }, {
157197 .width = 1280,
158198 .height = 720,
....@@ -162,6 +202,7 @@
162202 },
163203 .hts_def = 1650,
164204 .vts_def = 750,
205
+ .mipi_freq_idx = 3,
165206 }, {
166207 .width = 720,
167208 .height = 576,
....@@ -171,6 +212,7 @@
171212 },
172213 .hts_def = 864,
173214 .vts_def = 625,
215
+ .mipi_freq_idx = 5,
174216 }, {
175217 .width = 720,
176218 .height = 480,
....@@ -180,6 +222,7 @@
180222 },
181223 .hts_def = 858,
182224 .vts_def = 525,
225
+ .mipi_freq_idx = 5,
183226 },
184227 };
185228
....@@ -388,6 +431,7 @@
388431 u8 value, val_h, val_l;
389432 u32 fw_ver, mipi_byte_clk, mipi_bitrate;
390433 u8 fw_a, fw_b, fw_c, fw_d, lanes;
434
+ u8 video_fmt;
391435 int ret;
392436
393437 memset(timings, 0, sizeof(struct v4l2_dv_timings));
....@@ -419,13 +463,15 @@
419463
420464 i2c_rd8(sd, MIPI_LANES, &lanes);
421465 lt6911uxc->csi_lanes_in_use = lanes;
466
+ if (lt6911uxc->csi_lanes_in_use == 8)
467
+ v4l2_info(sd, "get 8 lane in use, set dual mipi mode\n");
422468 i2c_wr8(sd, FM1_DET_CLK_SRC_SEL, AD_LMTX_WRITE_CLK);
423469 i2c_rd8(sd, FREQ_METER_H, &clk_h);
424470 i2c_rd8(sd, FREQ_METER_M, &clk_m);
425471 i2c_rd8(sd, FREQ_METER_L, &clk_l);
426472 mipi_byte_clk = (((clk_h & 0xf) << 16) | (clk_m << 8) | clk_l);
427473 mipi_bitrate = mipi_byte_clk * 8 / 1000;
428
- v4l2_info(sd, "MIPI Byte clk: %dKHz, MIPI bitrate: %dMbps, lanes:%d\n",
474
+ v4l2_info(sd, "MIPI Byte clk: %uKHz, MIPI bitrate: %uMbps, lanes:%d\n",
429475 mipi_byte_clk, mipi_bitrate, lanes);
430476
431477 i2c_rd8(sd, HTOTAL_H, &val_h);
....@@ -455,7 +501,15 @@
455501 hbp = ((val_h << 8) | val_l) * 2;
456502 i2c_rd8(sd, VBP, &value);
457503 vbp = value;
504
+ i2c_rd8(sd, COLOR_FMT_STATUS, &video_fmt);
505
+ video_fmt = (video_fmt & GENMASK(6, 5)) >> 5;
458506 lt6911uxc_i2c_disable(sd);
507
+
508
+ if (video_fmt == 0x3) {
509
+ lt6911uxc->nosignal = true;
510
+ v4l2_err(sd, "%s ERROR: HDMI input YUV420, don't support YUV420!\n", __func__);
511
+ return -EINVAL;
512
+ }
459513
460514 if (!lt6911uxc_rcv_supported_res(sd, hact, vact)) {
461515 lt6911uxc->nosignal = true;
....@@ -692,7 +746,6 @@
692746 }
693747
694748 lt6911uxc->timings = *timings;
695
-
696749 enable_stream(sd, false);
697750
698751 return 0;
....@@ -769,7 +822,9 @@
769822 case 4:
770823 cfg->flags |= V4L2_MBUS_CSI2_4_LANE;
771824 break;
772
-
825
+ case 8:
826
+ cfg->flags |= V4L2_MBUS_CSI2_4_LANE;
827
+ break;
773828 default:
774829 return -EINVAL;
775830 }
....@@ -834,11 +889,50 @@
834889 return 0;
835890 }
836891
892
+static int lt6911uxc_get_reso_dist(const struct lt6911uxc_mode *mode,
893
+ struct v4l2_dv_timings *timings)
894
+{
895
+ struct v4l2_bt_timings *bt = &timings->bt;
896
+ u32 cur_fps, dist_fps;
897
+
898
+ cur_fps = fps_calc(bt);
899
+ dist_fps = DIV_ROUND_CLOSEST(mode->max_fps.denominator, mode->max_fps.numerator);
900
+
901
+ return abs(mode->width - bt->width) +
902
+ abs(mode->height - bt->height) + abs(dist_fps - cur_fps);
903
+}
904
+
905
+static const struct lt6911uxc_mode *
906
+lt6911uxc_find_best_fit(struct lt6911uxc *lt6911uxc)
907
+{
908
+ int dist;
909
+ int cur_best_fit = 0;
910
+ int cur_best_fit_dist = -1;
911
+ unsigned int i;
912
+
913
+ for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
914
+ dist = lt6911uxc_get_reso_dist(&supported_modes[i], &lt6911uxc->timings);
915
+ if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
916
+ cur_best_fit_dist = dist;
917
+ cur_best_fit = i;
918
+ }
919
+ }
920
+ dev_info(&lt6911uxc->i2c_client->dev,
921
+ "find current mode: support_mode[%d], %dx%d@%dfps\n",
922
+ cur_best_fit, supported_modes[cur_best_fit].width,
923
+ supported_modes[cur_best_fit].height,
924
+ DIV_ROUND_CLOSEST(supported_modes[cur_best_fit].max_fps.denominator,
925
+ supported_modes[cur_best_fit].max_fps.numerator));
926
+
927
+ return &supported_modes[cur_best_fit];
928
+}
929
+
837930 static int lt6911uxc_get_fmt(struct v4l2_subdev *sd,
838931 struct v4l2_subdev_pad_config *cfg,
839932 struct v4l2_subdev_format *format)
840933 {
841934 struct lt6911uxc *lt6911uxc = to_state(sd);
935
+ const struct lt6911uxc_mode *mode;
842936
843937 mutex_lock(&lt6911uxc->confctl_mutex);
844938 format->format.code = lt6911uxc->mbus_fmt_code;
....@@ -848,6 +942,14 @@
848942 lt6911uxc->timings.bt.interlaced ?
849943 V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
850944 format->format.colorspace = V4L2_COLORSPACE_SRGB;
945
+
946
+ mode = lt6911uxc_find_best_fit(lt6911uxc);
947
+ lt6911uxc->cur_mode = mode;
948
+ __v4l2_ctrl_s_ctrl_int64(lt6911uxc->pixel_rate,
949
+ LT6911UXC_PIXEL_RATE);
950
+ __v4l2_ctrl_s_ctrl(lt6911uxc->link_freq,
951
+ mode->mipi_freq_idx);
952
+
851953 mutex_unlock(&lt6911uxc->confctl_mutex);
852954
853955 v4l2_dbg(1, debug, sd, "%s: fmt code:%d, w:%d, h:%d, field mode:%s\n",
....@@ -857,40 +959,12 @@
857959 return 0;
858960 }
859961
860
-static int lt6911uxc_get_reso_dist(const struct lt6911uxc_mode *mode,
861
- struct v4l2_mbus_framefmt *framefmt)
862
-{
863
- return abs(mode->width - framefmt->width) +
864
- abs(mode->height - framefmt->height);
865
-}
866
-
867
-static const struct lt6911uxc_mode *
868
-lt6911uxc_find_best_fit(struct v4l2_subdev_format *fmt)
869
-{
870
- struct v4l2_mbus_framefmt *framefmt = &fmt->format;
871
- int dist;
872
- int cur_best_fit = 0;
873
- int cur_best_fit_dist = -1;
874
- unsigned int i;
875
-
876
- for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
877
- dist = lt6911uxc_get_reso_dist(&supported_modes[i], framefmt);
878
- if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
879
- cur_best_fit_dist = dist;
880
- cur_best_fit = i;
881
- }
882
- }
883
-
884
- return &supported_modes[cur_best_fit];
885
-}
886
-
887962 static int lt6911uxc_set_fmt(struct v4l2_subdev *sd,
888963 struct v4l2_subdev_pad_config *cfg,
889964 struct v4l2_subdev_format *format)
890965 {
891966 struct lt6911uxc *lt6911uxc = to_state(sd);
892967 const struct lt6911uxc_mode *mode;
893
- int index;
894968
895969 /* is overwritten by get_fmt */
896970 u32 code = format->format.code;
....@@ -913,19 +987,9 @@
913987 return 0;
914988
915989 lt6911uxc->mbus_fmt_code = format->format.code;
916
- mode = lt6911uxc_find_best_fit(format);
990
+ mode = lt6911uxc_find_best_fit(lt6911uxc);
917991 lt6911uxc->cur_mode = mode;
918992 enable_stream(sd, false);
919
-
920
- if (((mode->width == 720) && (mode->height == 576)) ||
921
- ((mode->width == 720) && (mode->height == 480)))
922
- index = 1;
923
- else
924
- index = 0;
925
-
926
- __v4l2_ctrl_s_ctrl(lt6911uxc->link_freq, index);
927
- v4l2_dbg(1, debug, sd, "%s res wxh:%dx%d, link freq:%llu", __func__,
928
- mode->width, mode->height, link_freq_menu_items[index]);
929993
930994 return 0;
931995 }
....@@ -955,7 +1019,10 @@
9551019 static long lt6911uxc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
9561020 {
9571021 struct lt6911uxc *lt6911uxc = to_state(sd);
1022
+ struct device *dev = &lt6911uxc->i2c_client->dev;
9581023 long ret = 0;
1024
+ struct rkmodule_csi_dphy_param *dphy_param;
1025
+ struct rkmodule_capture_info *capture_info;
9591026
9601027 switch (cmd) {
9611028 case RKMODULE_GET_MODULE_INFO:
....@@ -963,6 +1030,29 @@
9631030 break;
9641031 case RKMODULE_GET_HDMI_MODE:
9651032 *(int *)arg = RKMODULE_HDMIIN_MODE;
1033
+ break;
1034
+ case RKMODULE_SET_CSI_DPHY_PARAM:
1035
+ dphy_param = (struct rkmodule_csi_dphy_param *)arg;
1036
+ if (dphy_param->vendor == PHY_VENDOR_SAMSUNG)
1037
+ rk3588_dcphy_param = *dphy_param;
1038
+ dev_dbg(&lt6911uxc->i2c_client->dev,
1039
+ "sensor set dphy param\n");
1040
+ break;
1041
+ case RKMODULE_GET_CSI_DPHY_PARAM:
1042
+ dphy_param = (struct rkmodule_csi_dphy_param *)arg;
1043
+ *dphy_param = rk3588_dcphy_param;
1044
+ dev_dbg(&lt6911uxc->i2c_client->dev,
1045
+ "sensor get dphy param\n");
1046
+ break;
1047
+ case RKMODULE_GET_CAPTURE_MODE:
1048
+ capture_info = (struct rkmodule_capture_info *)arg;
1049
+ if (lt6911uxc->csi_lanes_in_use == 8) {
1050
+ dev_info(dev, "8 lanes in use, set dual mipi mode\n");
1051
+ capture_info->mode = RKMODULE_MULTI_DEV_COMBINE_ONE;
1052
+ capture_info->multi_dev = lt6911uxc->multi_dev_info;
1053
+ } else {
1054
+ capture_info->mode = 0;
1055
+ }
9661056 break;
9671057 default:
9681058 ret = -ENOIOCTLCMD;
....@@ -980,6 +1070,8 @@
9801070 struct rkmodule_inf *inf;
9811071 long ret;
9821072 int *seq;
1073
+ struct rkmodule_csi_dphy_param *dphy_param;
1074
+ struct rkmodule_capture_info *capture_info;
9831075
9841076 switch (cmd) {
9851077 case RKMODULE_GET_MODULE_INFO:
....@@ -1011,6 +1103,50 @@
10111103 ret = -EFAULT;
10121104 }
10131105 kfree(seq);
1106
+ break;
1107
+ case RKMODULE_SET_CSI_DPHY_PARAM:
1108
+ dphy_param = kzalloc(sizeof(*dphy_param), GFP_KERNEL);
1109
+ if (!dphy_param) {
1110
+ ret = -ENOMEM;
1111
+ return ret;
1112
+ }
1113
+
1114
+ ret = copy_from_user(dphy_param, up, sizeof(*dphy_param));
1115
+ if (!ret)
1116
+ ret = lt6911uxc_ioctl(sd, cmd, dphy_param);
1117
+ else
1118
+ ret = -EFAULT;
1119
+ kfree(dphy_param);
1120
+ break;
1121
+ case RKMODULE_GET_CSI_DPHY_PARAM:
1122
+ dphy_param = kzalloc(sizeof(*dphy_param), GFP_KERNEL);
1123
+ if (!dphy_param) {
1124
+ ret = -ENOMEM;
1125
+ return ret;
1126
+ }
1127
+
1128
+ ret = lt6911uxc_ioctl(sd, cmd, dphy_param);
1129
+ if (!ret) {
1130
+ ret = copy_to_user(up, dphy_param, sizeof(*dphy_param));
1131
+ if (ret)
1132
+ ret = -EFAULT;
1133
+ }
1134
+ kfree(dphy_param);
1135
+ break;
1136
+ case RKMODULE_GET_CAPTURE_MODE:
1137
+ capture_info = kzalloc(sizeof(*capture_info), GFP_KERNEL);
1138
+ if (!capture_info) {
1139
+ ret = -ENOMEM;
1140
+ return ret;
1141
+ }
1142
+
1143
+ ret = lt6911uxc_ioctl(sd, cmd, capture_info);
1144
+ if (!ret) {
1145
+ ret = copy_to_user(up, capture_info, sizeof(*capture_info));
1146
+ if (ret)
1147
+ ret = -EFAULT;
1148
+ }
1149
+ kfree(capture_info);
10141150 break;
10151151 default:
10161152 ret = -ENOIOCTLCMD;
....@@ -1091,9 +1227,11 @@
10911227
10921228 static int lt6911uxc_init_v4l2_ctrls(struct lt6911uxc *lt6911uxc)
10931229 {
1230
+ const struct lt6911uxc_mode *mode;
10941231 struct v4l2_subdev *sd;
10951232 int ret;
10961233
1234
+ mode = lt6911uxc->cur_mode;
10971235 sd = &lt6911uxc->sd;
10981236 ret = v4l2_ctrl_handler_init(&lt6911uxc->hdl, 5);
10991237 if (ret)
....@@ -1103,8 +1241,9 @@
11031241 V4L2_CID_LINK_FREQ,
11041242 ARRAY_SIZE(link_freq_menu_items) - 1, 0,
11051243 link_freq_menu_items);
1106
- v4l2_ctrl_new_std(&lt6911uxc->hdl, NULL, V4L2_CID_PIXEL_RATE,
1107
- 0, LT6911UXC_PIXEL_RATE, 1, LT6911UXC_PIXEL_RATE);
1244
+ lt6911uxc->pixel_rate = v4l2_ctrl_new_std(&lt6911uxc->hdl, NULL,
1245
+ V4L2_CID_PIXEL_RATE,
1246
+ 0, LT6911UXC_PIXEL_RATE, 1, LT6911UXC_PIXEL_RATE);
11081247
11091248 lt6911uxc->detect_tx_5v_ctrl = v4l2_ctrl_new_std(&lt6911uxc->hdl,
11101249 NULL, V4L2_CID_DV_RX_POWER_PRESENT,
....@@ -1122,6 +1261,9 @@
11221261 v4l2_err(sd, "cfg v4l2 ctrls failed! ret:%d\n", ret);
11231262 return ret;
11241263 }
1264
+
1265
+ __v4l2_ctrl_s_ctrl(lt6911uxc->link_freq, mode->mipi_freq_idx);
1266
+ __v4l2_ctrl_s_ctrl_int64(lt6911uxc->pixel_rate, LT6911UXC_PIXEL_RATE);
11251267
11261268 if (lt6911uxc_update_controls(sd)) {
11271269 ret = -ENODEV;
....@@ -1279,6 +1421,64 @@
12791421 }
12801422 #endif
12811423
1424
+static ssize_t audio_rate_show(struct device *dev,
1425
+ struct device_attribute *attr, char *buf)
1426
+{
1427
+ struct lt6911uxc *lt6911uxc = dev_get_drvdata(dev);
1428
+
1429
+ return snprintf(buf, PAGE_SIZE, "%d", lt6911uxc->audio_sampling_rate);
1430
+}
1431
+
1432
+static ssize_t audio_present_show(struct device *dev,
1433
+ struct device_attribute *attr, char *buf)
1434
+{
1435
+ struct lt6911uxc *lt6911uxc = dev_get_drvdata(dev);
1436
+
1437
+ return snprintf(buf, PAGE_SIZE, "%d",
1438
+ tx_5v_power_present(&lt6911uxc->sd) ?
1439
+ lt6911uxc->is_audio_present : 0);
1440
+}
1441
+
1442
+static DEVICE_ATTR_RO(audio_rate);
1443
+static DEVICE_ATTR_RO(audio_present);
1444
+
1445
+static struct attribute *lt6911_attrs[] = {
1446
+ &dev_attr_audio_rate.attr,
1447
+ &dev_attr_audio_present.attr,
1448
+ NULL
1449
+};
1450
+ATTRIBUTE_GROUPS(lt6911);
1451
+
1452
+static int lt6911uxc_get_multi_dev_info(struct lt6911uxc *lt6911uxc)
1453
+{
1454
+ struct device *dev = &lt6911uxc->i2c_client->dev;
1455
+ struct device_node *node = dev->of_node;
1456
+ struct device_node *multi_info_np;
1457
+
1458
+ multi_info_np = of_get_child_by_name(node, "multi-dev-info");
1459
+ if (!multi_info_np) {
1460
+ dev_info(dev, "failed to get multi dev info\n");
1461
+ return -EINVAL;
1462
+ }
1463
+
1464
+ of_property_read_u32(multi_info_np, "dev-idx-l",
1465
+ &lt6911uxc->multi_dev_info.dev_idx[0]);
1466
+ of_property_read_u32(multi_info_np, "dev-idx-r",
1467
+ &lt6911uxc->multi_dev_info.dev_idx[1]);
1468
+ of_property_read_u32(multi_info_np, "combine-idx",
1469
+ &lt6911uxc->multi_dev_info.combine_idx[0]);
1470
+ of_property_read_u32(multi_info_np, "pixel-offset",
1471
+ &lt6911uxc->multi_dev_info.pixel_offset);
1472
+ of_property_read_u32(multi_info_np, "dev-num",
1473
+ &lt6911uxc->multi_dev_info.dev_num);
1474
+ dev_info(dev,
1475
+ "multi dev left: mipi%d, multi dev right: mipi%d, combile mipi%d, dev num: %d\n",
1476
+ lt6911uxc->multi_dev_info.dev_idx[0], lt6911uxc->multi_dev_info.dev_idx[1],
1477
+ lt6911uxc->multi_dev_info.combine_idx[0], lt6911uxc->multi_dev_info.dev_num);
1478
+
1479
+ return 0;
1480
+}
1481
+
12821482 static int lt6911uxc_probe(struct i2c_client *client,
12831483 const struct i2c_device_id *id)
12841484 {
....@@ -1310,6 +1510,10 @@
13101510 v4l2_err(sd, "lt6911uxc_parse_of failed! err:%d\n", err);
13111511 return err;
13121512 }
1513
+
1514
+ err = lt6911uxc_get_multi_dev_info(lt6911uxc);
1515
+ if (err)
1516
+ v4l2_info(sd, "get multi dev info failed, not use dual mipi mode\n");
13131517
13141518 err = lt6911uxc_check_chip_id(lt6911uxc);
13151519 if (err < 0)
....@@ -1354,6 +1558,14 @@
13541558 v4l2_err(sd, "v4l2 register subdev failed! err:%d\n", err);
13551559 goto err_clean_entity;
13561560 }
1561
+
1562
+ lt6911uxc->classdev = device_create_with_groups(rk_hdmirx_class(),
1563
+ dev, MKDEV(0, 0),
1564
+ lt6911uxc,
1565
+ lt6911_groups,
1566
+ "lt6911");
1567
+ if (IS_ERR(lt6911uxc->classdev))
1568
+ goto err_clean_entity;
13571569
13581570 INIT_DELAYED_WORK(&lt6911uxc->delayed_work_enable_hotplug,
13591571 lt6911uxc_delayed_work_enable_hotplug);
....@@ -1459,9 +1671,10 @@
14591671 i2c_del_driver(&lt6911uxc_driver);
14601672 }
14611673
1462
-late_initcall(lt6911uxc_driver_init);
1674
+device_initcall_sync(lt6911uxc_driver_init);
14631675 module_exit(lt6911uxc_driver_exit);
14641676
14651677 MODULE_DESCRIPTION("Lontium LT6911UXC HDMI to MIPI CSI-2 bridge driver");
14661678 MODULE_AUTHOR("Dingxian Wen <shawn.wen@rock-chips.com>");
1679
+MODULE_AUTHOR("Jianwei Fan <jianwei.fan@rock-chips.com>");
14671680 MODULE_LICENSE("GPL v2");