hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
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>
....@@ -34,12 +36,16 @@
3436 #include <media/v4l2-fwnode.h>
3537 #include "lt6911uxc.h"
3638
37
-#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x2)
39
+#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x3)
3840 #define LT6911UXC_NAME "LT6911UXC"
3941
40
-#define LT6911UXC_LINK_FREQ_HIGH 400000000
41
-#define LT6911UXC_LINK_FREQ_LOW 200000000
42
-#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
4349
4450 #define I2C_MAX_XFER_SIZE 128
4551
....@@ -54,8 +60,12 @@
5460 MODULE_PARM_DESC(debug, "debug level (0-2)");
5561
5662 static const s64 link_freq_menu_items[] = {
57
- LT6911UXC_LINK_FREQ_HIGH,
58
- 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,
5969 };
6070
6171 struct lt6911uxc {
....@@ -78,6 +88,7 @@
7888 struct v4l2_dv_timings timings;
7989 struct v4l2_fwnode_bus_mipi_csi2 bus;
8090 struct v4l2_subdev sd;
91
+ struct rkmodule_multi_dev_info multi_dev_info;
8192 const char *len_name;
8293 const char *module_facing;
8394 const char *module_name;
....@@ -100,13 +111,25 @@
100111 u32 hts_def;
101112 u32 vts_def;
102113 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},
103126 };
104127
105128 static const struct v4l2_dv_timings_cap lt6911uxc_timings_cap = {
106129 .type = V4L2_DV_BT_656_1120,
107130 /* keep this initialization for compatibility with GCC < 4.4.6 */
108131 .reserved = { 0 },
109
- V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 400000000,
132
+ V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 600000000,
110133 V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
111134 V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
112135 V4L2_DV_BT_CAP_PROGRESSIVE |
....@@ -121,10 +144,21 @@
121144 .height = 2160,
122145 .max_fps = {
123146 .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,
124157 .denominator = 300000,
125158 },
126159 .hts_def = 4400,
127160 .vts_def = 2250,
161
+ .mipi_freq_idx = 0,
128162 }, {
129163 .width = 1920,
130164 .height = 1080,
....@@ -134,6 +168,7 @@
134168 },
135169 .hts_def = 2200,
136170 .vts_def = 1125,
171
+ .mipi_freq_idx = 2,
137172 }, {
138173 .width = 1920,
139174 .height = 540,
....@@ -141,6 +176,7 @@
141176 .numerator = 10000,
142177 .denominator = 600000,
143178 },
179
+ .mipi_freq_idx = 3,
144180 }, {
145181 .width = 1440,
146182 .height = 240,
....@@ -148,6 +184,7 @@
148184 .numerator = 10000,
149185 .denominator = 600000,
150186 },
187
+ .mipi_freq_idx = 4,
151188 }, {
152189 .width = 1440,
153190 .height = 288,
....@@ -155,6 +192,7 @@
155192 .numerator = 10000,
156193 .denominator = 500000,
157194 },
195
+ .mipi_freq_idx = 4,
158196 }, {
159197 .width = 1280,
160198 .height = 720,
....@@ -164,6 +202,7 @@
164202 },
165203 .hts_def = 1650,
166204 .vts_def = 750,
205
+ .mipi_freq_idx = 3,
167206 }, {
168207 .width = 720,
169208 .height = 576,
....@@ -173,6 +212,7 @@
173212 },
174213 .hts_def = 864,
175214 .vts_def = 625,
215
+ .mipi_freq_idx = 5,
176216 }, {
177217 .width = 720,
178218 .height = 480,
....@@ -182,6 +222,7 @@
182222 },
183223 .hts_def = 858,
184224 .vts_def = 525,
225
+ .mipi_freq_idx = 5,
185226 },
186227 };
187228
....@@ -390,6 +431,7 @@
390431 u8 value, val_h, val_l;
391432 u32 fw_ver, mipi_byte_clk, mipi_bitrate;
392433 u8 fw_a, fw_b, fw_c, fw_d, lanes;
434
+ u8 video_fmt;
393435 int ret;
394436
395437 memset(timings, 0, sizeof(struct v4l2_dv_timings));
....@@ -421,13 +463,15 @@
421463
422464 i2c_rd8(sd, MIPI_LANES, &lanes);
423465 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");
424468 i2c_wr8(sd, FM1_DET_CLK_SRC_SEL, AD_LMTX_WRITE_CLK);
425469 i2c_rd8(sd, FREQ_METER_H, &clk_h);
426470 i2c_rd8(sd, FREQ_METER_M, &clk_m);
427471 i2c_rd8(sd, FREQ_METER_L, &clk_l);
428472 mipi_byte_clk = (((clk_h & 0xf) << 16) | (clk_m << 8) | clk_l);
429473 mipi_bitrate = mipi_byte_clk * 8 / 1000;
430
- 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",
431475 mipi_byte_clk, mipi_bitrate, lanes);
432476
433477 i2c_rd8(sd, HTOTAL_H, &val_h);
....@@ -457,7 +501,15 @@
457501 hbp = ((val_h << 8) | val_l) * 2;
458502 i2c_rd8(sd, VBP, &value);
459503 vbp = value;
504
+ i2c_rd8(sd, COLOR_FMT_STATUS, &video_fmt);
505
+ video_fmt = (video_fmt & GENMASK(6, 5)) >> 5;
460506 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
+ }
461513
462514 if (!lt6911uxc_rcv_supported_res(sd, hact, vact)) {
463515 lt6911uxc->nosignal = true;
....@@ -694,7 +746,6 @@
694746 }
695747
696748 lt6911uxc->timings = *timings;
697
-
698749 enable_stream(sd, false);
699750
700751 return 0;
....@@ -771,7 +822,9 @@
771822 case 4:
772823 cfg->flags |= V4L2_MBUS_CSI2_4_LANE;
773824 break;
774
-
825
+ case 8:
826
+ cfg->flags |= V4L2_MBUS_CSI2_4_LANE;
827
+ break;
775828 default:
776829 return -EINVAL;
777830 }
....@@ -836,11 +889,50 @@
836889 return 0;
837890 }
838891
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
+
839930 static int lt6911uxc_get_fmt(struct v4l2_subdev *sd,
840931 struct v4l2_subdev_pad_config *cfg,
841932 struct v4l2_subdev_format *format)
842933 {
843934 struct lt6911uxc *lt6911uxc = to_state(sd);
935
+ const struct lt6911uxc_mode *mode;
844936
845937 mutex_lock(&lt6911uxc->confctl_mutex);
846938 format->format.code = lt6911uxc->mbus_fmt_code;
....@@ -850,6 +942,14 @@
850942 lt6911uxc->timings.bt.interlaced ?
851943 V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
852944 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
+
853953 mutex_unlock(&lt6911uxc->confctl_mutex);
854954
855955 v4l2_dbg(1, debug, sd, "%s: fmt code:%d, w:%d, h:%d, field mode:%s\n",
....@@ -859,40 +959,12 @@
859959 return 0;
860960 }
861961
862
-static int lt6911uxc_get_reso_dist(const struct lt6911uxc_mode *mode,
863
- struct v4l2_mbus_framefmt *framefmt)
864
-{
865
- return abs(mode->width - framefmt->width) +
866
- abs(mode->height - framefmt->height);
867
-}
868
-
869
-static const struct lt6911uxc_mode *
870
-lt6911uxc_find_best_fit(struct v4l2_subdev_format *fmt)
871
-{
872
- struct v4l2_mbus_framefmt *framefmt = &fmt->format;
873
- int dist;
874
- int cur_best_fit = 0;
875
- int cur_best_fit_dist = -1;
876
- unsigned int i;
877
-
878
- for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
879
- dist = lt6911uxc_get_reso_dist(&supported_modes[i], framefmt);
880
- if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
881
- cur_best_fit_dist = dist;
882
- cur_best_fit = i;
883
- }
884
- }
885
-
886
- return &supported_modes[cur_best_fit];
887
-}
888
-
889962 static int lt6911uxc_set_fmt(struct v4l2_subdev *sd,
890963 struct v4l2_subdev_pad_config *cfg,
891964 struct v4l2_subdev_format *format)
892965 {
893966 struct lt6911uxc *lt6911uxc = to_state(sd);
894967 const struct lt6911uxc_mode *mode;
895
- int index;
896968
897969 /* is overwritten by get_fmt */
898970 u32 code = format->format.code;
....@@ -915,19 +987,9 @@
915987 return 0;
916988
917989 lt6911uxc->mbus_fmt_code = format->format.code;
918
- mode = lt6911uxc_find_best_fit(format);
990
+ mode = lt6911uxc_find_best_fit(lt6911uxc);
919991 lt6911uxc->cur_mode = mode;
920992 enable_stream(sd, false);
921
-
922
- if (((mode->width == 720) && (mode->height == 576)) ||
923
- ((mode->width == 720) && (mode->height == 480)))
924
- index = 1;
925
- else
926
- index = 0;
927
-
928
- __v4l2_ctrl_s_ctrl(lt6911uxc->link_freq, index);
929
- v4l2_dbg(1, debug, sd, "%s res wxh:%dx%d, link freq:%llu", __func__,
930
- mode->width, mode->height, link_freq_menu_items[index]);
931993
932994 return 0;
933995 }
....@@ -957,7 +1019,10 @@
9571019 static long lt6911uxc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
9581020 {
9591021 struct lt6911uxc *lt6911uxc = to_state(sd);
1022
+ struct device *dev = &lt6911uxc->i2c_client->dev;
9601023 long ret = 0;
1024
+ struct rkmodule_csi_dphy_param *dphy_param;
1025
+ struct rkmodule_capture_info *capture_info;
9611026
9621027 switch (cmd) {
9631028 case RKMODULE_GET_MODULE_INFO:
....@@ -965,6 +1030,29 @@
9651030 break;
9661031 case RKMODULE_GET_HDMI_MODE:
9671032 *(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
+ }
9681056 break;
9691057 default:
9701058 ret = -ENOIOCTLCMD;
....@@ -982,6 +1070,8 @@
9821070 struct rkmodule_inf *inf;
9831071 long ret;
9841072 int *seq;
1073
+ struct rkmodule_csi_dphy_param *dphy_param;
1074
+ struct rkmodule_capture_info *capture_info;
9851075
9861076 switch (cmd) {
9871077 case RKMODULE_GET_MODULE_INFO:
....@@ -1013,6 +1103,50 @@
10131103 ret = -EFAULT;
10141104 }
10151105 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);
10161150 break;
10171151 default:
10181152 ret = -ENOIOCTLCMD;
....@@ -1093,9 +1227,11 @@
10931227
10941228 static int lt6911uxc_init_v4l2_ctrls(struct lt6911uxc *lt6911uxc)
10951229 {
1230
+ const struct lt6911uxc_mode *mode;
10961231 struct v4l2_subdev *sd;
10971232 int ret;
10981233
1234
+ mode = lt6911uxc->cur_mode;
10991235 sd = &lt6911uxc->sd;
11001236 ret = v4l2_ctrl_handler_init(&lt6911uxc->hdl, 5);
11011237 if (ret)
....@@ -1105,8 +1241,9 @@
11051241 V4L2_CID_LINK_FREQ,
11061242 ARRAY_SIZE(link_freq_menu_items) - 1, 0,
11071243 link_freq_menu_items);
1108
- v4l2_ctrl_new_std(&lt6911uxc->hdl, NULL, V4L2_CID_PIXEL_RATE,
1109
- 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);
11101247
11111248 lt6911uxc->detect_tx_5v_ctrl = v4l2_ctrl_new_std(&lt6911uxc->hdl,
11121249 NULL, V4L2_CID_DV_RX_POWER_PRESENT,
....@@ -1124,6 +1261,9 @@
11241261 v4l2_err(sd, "cfg v4l2 ctrls failed! ret:%d\n", ret);
11251262 return ret;
11261263 }
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);
11271267
11281268 if (lt6911uxc_update_controls(sd)) {
11291269 ret = -ENODEV;
....@@ -1309,6 +1449,36 @@
13091449 };
13101450 ATTRIBUTE_GROUPS(lt6911);
13111451
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
+
13121482 static int lt6911uxc_probe(struct i2c_client *client,
13131483 const struct i2c_device_id *id)
13141484 {
....@@ -1340,6 +1510,10 @@
13401510 v4l2_err(sd, "lt6911uxc_parse_of failed! err:%d\n", err);
13411511 return err;
13421512 }
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");
13431517
13441518 err = lt6911uxc_check_chip_id(lt6911uxc);
13451519 if (err < 0)
....@@ -1497,9 +1671,10 @@
14971671 i2c_del_driver(&lt6911uxc_driver);
14981672 }
14991673
1500
-late_initcall(lt6911uxc_driver_init);
1674
+device_initcall_sync(lt6911uxc_driver_init);
15011675 module_exit(lt6911uxc_driver_exit);
15021676
15031677 MODULE_DESCRIPTION("Lontium LT6911UXC HDMI to MIPI CSI-2 bridge driver");
15041678 MODULE_AUTHOR("Dingxian Wen <shawn.wen@rock-chips.com>");
1679
+MODULE_AUTHOR("Jianwei Fan <jianwei.fan@rock-chips.com>");
15051680 MODULE_LICENSE("GPL v2");