forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/media/i2c/lt6911uxc.c
....@@ -3,6 +3,11 @@
33 * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
44 *
55 * Author: Dingxian Wen <shawn.wen@rock-chips.com>
6
+ * V0.0X01.0X00 first version.
7
+ * V0.0X01.0X01 fix if plugin_gpio was not used.
8
+ * V0.0X01.0X02 modify driver init level to late_initcall.
9
+ * V0.0X01.0X03 add 4K60 dual mipi support
10
+ *
611 */
712
813 #include <linux/clk.h>
....@@ -15,12 +20,14 @@
1520 #include <linux/module.h>
1621 #include <linux/of_graph.h>
1722 #include <linux/rk-camera-module.h>
23
+#include <linux/rk_hdmirx_class.h>
1824 #include <linux/slab.h>
1925 #include <linux/timer.h>
2026 #include <linux/v4l2-dv-timings.h>
2127 #include <linux/version.h>
2228 #include <linux/videodev2.h>
2329 #include <linux/workqueue.h>
30
+#include <linux/compat.h>
2431 #include <media/v4l2-controls_rockchip.h>
2532 #include <media/v4l2-ctrls.h>
2633 #include <media/v4l2-device.h>
....@@ -29,22 +36,36 @@
2936 #include <media/v4l2-fwnode.h>
3037 #include "lt6911uxc.h"
3138
32
-#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0)
39
+#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x3)
3340 #define LT6911UXC_NAME "LT6911UXC"
3441
35
-#define LT6911UXC_LINK_FREQ_HIGH 400000000
36
-#define LT6911UXC_LINK_FREQ_LOW 200000000
37
-#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
3849
3950 #define I2C_MAX_XFER_SIZE 128
51
+
52
+#ifdef LT6911UXC_OUT_RGB
53
+#define LT6911UXC_MEDIA_BUS_FMT MEDIA_BUS_FMT_BGR888_1X24
54
+#else
55
+#define LT6911UXC_MEDIA_BUS_FMT MEDIA_BUS_FMT_UYVY8_2X8
56
+#endif
4057
4158 static int debug;
4259 module_param(debug, int, 0644);
4360 MODULE_PARM_DESC(debug, "debug level (0-2)");
4461
4562 static const s64 link_freq_menu_items[] = {
46
- LT6911UXC_LINK_FREQ_HIGH,
47
- 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,
4869 };
4970
5071 struct lt6911uxc {
....@@ -67,6 +88,7 @@
6788 struct v4l2_dv_timings timings;
6889 struct v4l2_fwnode_bus_mipi_csi2 bus;
6990 struct v4l2_subdev sd;
91
+ struct rkmodule_multi_dev_info multi_dev_info;
7092 const char *len_name;
7193 const char *module_facing;
7294 const char *module_name;
....@@ -79,6 +101,7 @@
79101 u32 module_index;
80102 u32 csi_lanes_in_use;
81103 u32 audio_sampling_rate;
104
+ struct device *classdev;
82105 };
83106
84107 struct lt6911uxc_mode {
....@@ -88,13 +111,25 @@
88111 u32 hts_def;
89112 u32 vts_def;
90113 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},
91126 };
92127
93128 static const struct v4l2_dv_timings_cap lt6911uxc_timings_cap = {
94129 .type = V4L2_DV_BT_656_1120,
95130 /* keep this initialization for compatibility with GCC < 4.4.6 */
96131 .reserved = { 0 },
97
- V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 400000000,
132
+ V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 600000000,
98133 V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
99134 V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
100135 V4L2_DV_BT_CAP_PROGRESSIVE |
....@@ -109,10 +144,21 @@
109144 .height = 2160,
110145 .max_fps = {
111146 .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,
112157 .denominator = 300000,
113158 },
114159 .hts_def = 4400,
115160 .vts_def = 2250,
161
+ .mipi_freq_idx = 0,
116162 }, {
117163 .width = 1920,
118164 .height = 1080,
....@@ -122,6 +168,7 @@
122168 },
123169 .hts_def = 2200,
124170 .vts_def = 1125,
171
+ .mipi_freq_idx = 2,
125172 }, {
126173 .width = 1920,
127174 .height = 540,
....@@ -129,6 +176,7 @@
129176 .numerator = 10000,
130177 .denominator = 600000,
131178 },
179
+ .mipi_freq_idx = 3,
132180 }, {
133181 .width = 1440,
134182 .height = 240,
....@@ -136,6 +184,7 @@
136184 .numerator = 10000,
137185 .denominator = 600000,
138186 },
187
+ .mipi_freq_idx = 4,
139188 }, {
140189 .width = 1440,
141190 .height = 288,
....@@ -143,6 +192,7 @@
143192 .numerator = 10000,
144193 .denominator = 500000,
145194 },
195
+ .mipi_freq_idx = 4,
146196 }, {
147197 .width = 1280,
148198 .height = 720,
....@@ -152,6 +202,7 @@
152202 },
153203 .hts_def = 1650,
154204 .vts_def = 750,
205
+ .mipi_freq_idx = 3,
155206 }, {
156207 .width = 720,
157208 .height = 576,
....@@ -161,6 +212,7 @@
161212 },
162213 .hts_def = 864,
163214 .vts_def = 625,
215
+ .mipi_freq_idx = 5,
164216 }, {
165217 .width = 720,
166218 .height = 480,
....@@ -170,6 +222,7 @@
170222 },
171223 .hts_def = 858,
172224 .vts_def = 525,
225
+ .mipi_freq_idx = 5,
173226 },
174227 };
175228
....@@ -286,14 +339,27 @@
286339
287340 static inline bool tx_5v_power_present(struct v4l2_subdev *sd)
288341 {
289
- int val;
342
+ bool ret;
343
+ int val, i, cnt;
290344 struct lt6911uxc *lt6911uxc = to_state(sd);
291345
292
- val = gpiod_get_value(lt6911uxc->plugin_det_gpio);
293
- v4l2_dbg(1, debug, sd, "%s plug det: %s!\n", __func__,
294
- (val > 0) ? "int" : "out");
346
+ /* if not use plugin det gpio */
347
+ if (!lt6911uxc->plugin_det_gpio)
348
+ return true;
295349
296
- return (val > 0);
350
+ cnt = 0;
351
+ for (i = 0; i < 5; i++) {
352
+ val = gpiod_get_value(lt6911uxc->plugin_det_gpio);
353
+
354
+ if (val > 0)
355
+ cnt++;
356
+ usleep_range(500, 600);
357
+ }
358
+
359
+ ret = (cnt >= 3) ? true : false;
360
+ v4l2_dbg(1, debug, sd, "%s: %d\n", __func__, ret);
361
+
362
+ return ret;
297363 }
298364
299365 static inline bool no_signal(struct v4l2_subdev *sd)
....@@ -365,6 +431,7 @@
365431 u8 value, val_h, val_l;
366432 u32 fw_ver, mipi_byte_clk, mipi_bitrate;
367433 u8 fw_a, fw_b, fw_c, fw_d, lanes;
434
+ u8 video_fmt;
368435 int ret;
369436
370437 memset(timings, 0, sizeof(struct v4l2_dv_timings));
....@@ -396,13 +463,15 @@
396463
397464 i2c_rd8(sd, MIPI_LANES, &lanes);
398465 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");
399468 i2c_wr8(sd, FM1_DET_CLK_SRC_SEL, AD_LMTX_WRITE_CLK);
400469 i2c_rd8(sd, FREQ_METER_H, &clk_h);
401470 i2c_rd8(sd, FREQ_METER_M, &clk_m);
402471 i2c_rd8(sd, FREQ_METER_L, &clk_l);
403472 mipi_byte_clk = (((clk_h & 0xf) << 16) | (clk_m << 8) | clk_l);
404473 mipi_bitrate = mipi_byte_clk * 8 / 1000;
405
- 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",
406475 mipi_byte_clk, mipi_bitrate, lanes);
407476
408477 i2c_rd8(sd, HTOTAL_H, &val_h);
....@@ -432,7 +501,15 @@
432501 hbp = ((val_h << 8) | val_l) * 2;
433502 i2c_rd8(sd, VBP, &value);
434503 vbp = value;
504
+ i2c_rd8(sd, COLOR_FMT_STATUS, &video_fmt);
505
+ video_fmt = (video_fmt & GENMASK(6, 5)) >> 5;
435506 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
+ }
436513
437514 if (!lt6911uxc_rcv_supported_res(sd, hact, vact)) {
438515 lt6911uxc->nosignal = true;
....@@ -505,6 +582,8 @@
505582 struct v4l2_subdev *sd = &lt6911uxc->sd;
506583
507584 v4l2_dbg(2, debug, sd, "%s:\n", __func__);
585
+
586
+ v4l2_ctrl_s_ctrl(lt6911uxc->detect_tx_5v_ctrl, tx_5v_power_present(sd));
508587 lt6911uxc_config_hpd(sd);
509588 }
510589
....@@ -589,21 +668,6 @@
589668 v4l2_subdev_notify_event(sd, &lt6911uxc_ev_fmt);
590669 }
591670
592
-static int lt6911uxc_get_ctrl(struct v4l2_ctrl *ctrl)
593
-{
594
- int ret = -1;
595
- struct lt6911uxc *lt6911uxc = container_of(ctrl->handler,
596
- struct lt6911uxc, hdl);
597
- struct v4l2_subdev *sd = &(lt6911uxc->sd);
598
-
599
- if (ctrl->id == V4L2_CID_DV_RX_POWER_PRESENT) {
600
- ret = tx_5v_power_present(sd);
601
- *ctrl->p_new.p_s32 = ret;
602
- }
603
-
604
- return ret;
605
-}
606
-
607671 static int lt6911uxc_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
608672 {
609673 struct lt6911uxc *lt6911uxc = to_state(sd);
....@@ -682,7 +746,6 @@
682746 }
683747
684748 lt6911uxc->timings = *timings;
685
-
686749 enable_stream(sd, false);
687750
688751 return 0;
....@@ -738,12 +801,12 @@
738801 return 0;
739802 }
740803
741
-static int lt6911uxc_g_mbus_config(struct v4l2_subdev *sd,
804
+static int lt6911uxc_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
742805 struct v4l2_mbus_config *cfg)
743806 {
744807 struct lt6911uxc *lt6911uxc = to_state(sd);
745808
746
- cfg->type = V4L2_MBUS_CSI2;
809
+ cfg->type = V4L2_MBUS_CSI2_DPHY;
747810 cfg->flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | V4L2_MBUS_CSI2_CHANNEL_0;
748811
749812 switch (lt6911uxc->csi_lanes_in_use) {
....@@ -759,7 +822,9 @@
759822 case 4:
760823 cfg->flags |= V4L2_MBUS_CSI2_4_LANE;
761824 break;
762
-
825
+ case 8:
826
+ cfg->flags |= V4L2_MBUS_CSI2_4_LANE;
827
+ break;
763828 default:
764829 return -EINVAL;
765830 }
....@@ -780,7 +845,7 @@
780845 {
781846 switch (code->index) {
782847 case 0:
783
- code->code = MEDIA_BUS_FMT_UYVY8_2X8;
848
+ code->code = LT6911UXC_MEDIA_BUS_FMT;
784849 break;
785850
786851 default:
....@@ -797,7 +862,7 @@
797862 if (fse->index >= ARRAY_SIZE(supported_modes))
798863 return -EINVAL;
799864
800
- if (fse->code != MEDIA_BUS_FMT_UYVY8_2X8)
865
+ if (fse->code != LT6911UXC_MEDIA_BUS_FMT)
801866 return -EINVAL;
802867
803868 fse->min_width = supported_modes[fse->index].width;
....@@ -815,8 +880,7 @@
815880 if (fie->index >= ARRAY_SIZE(supported_modes))
816881 return -EINVAL;
817882
818
- if (fie->code != MEDIA_BUS_FMT_UYVY8_2X8)
819
- return -EINVAL;
883
+ fie->code = LT6911UXC_MEDIA_BUS_FMT;
820884
821885 fie->width = supported_modes[fie->index].width;
822886 fie->height = supported_modes[fie->index].height;
....@@ -825,11 +889,50 @@
825889 return 0;
826890 }
827891
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
+
828930 static int lt6911uxc_get_fmt(struct v4l2_subdev *sd,
829931 struct v4l2_subdev_pad_config *cfg,
830932 struct v4l2_subdev_format *format)
831933 {
832934 struct lt6911uxc *lt6911uxc = to_state(sd);
935
+ const struct lt6911uxc_mode *mode;
833936
834937 mutex_lock(&lt6911uxc->confctl_mutex);
835938 format->format.code = lt6911uxc->mbus_fmt_code;
....@@ -839,6 +942,14 @@
839942 lt6911uxc->timings.bt.interlaced ?
840943 V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
841944 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
+
842953 mutex_unlock(&lt6911uxc->confctl_mutex);
843954
844955 v4l2_dbg(1, debug, sd, "%s: fmt code:%d, w:%d, h:%d, field mode:%s\n",
....@@ -848,40 +959,12 @@
848959 return 0;
849960 }
850961
851
-static int lt6911uxc_get_reso_dist(const struct lt6911uxc_mode *mode,
852
- struct v4l2_mbus_framefmt *framefmt)
853
-{
854
- return abs(mode->width - framefmt->width) +
855
- abs(mode->height - framefmt->height);
856
-}
857
-
858
-static const struct lt6911uxc_mode *
859
-lt6911uxc_find_best_fit(struct v4l2_subdev_format *fmt)
860
-{
861
- struct v4l2_mbus_framefmt *framefmt = &fmt->format;
862
- int dist;
863
- int cur_best_fit = 0;
864
- int cur_best_fit_dist = -1;
865
- unsigned int i;
866
-
867
- for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
868
- dist = lt6911uxc_get_reso_dist(&supported_modes[i], framefmt);
869
- if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
870
- cur_best_fit_dist = dist;
871
- cur_best_fit = i;
872
- }
873
- }
874
-
875
- return &supported_modes[cur_best_fit];
876
-}
877
-
878962 static int lt6911uxc_set_fmt(struct v4l2_subdev *sd,
879963 struct v4l2_subdev_pad_config *cfg,
880964 struct v4l2_subdev_format *format)
881965 {
882966 struct lt6911uxc *lt6911uxc = to_state(sd);
883967 const struct lt6911uxc_mode *mode;
884
- int index;
885968
886969 /* is overwritten by get_fmt */
887970 u32 code = format->format.code;
....@@ -893,7 +976,7 @@
893976 return ret;
894977
895978 switch (code) {
896
- case MEDIA_BUS_FMT_UYVY8_2X8:
979
+ case LT6911UXC_MEDIA_BUS_FMT:
897980 break;
898981
899982 default:
....@@ -904,19 +987,9 @@
904987 return 0;
905988
906989 lt6911uxc->mbus_fmt_code = format->format.code;
907
- mode = lt6911uxc_find_best_fit(format);
990
+ mode = lt6911uxc_find_best_fit(lt6911uxc);
908991 lt6911uxc->cur_mode = mode;
909992 enable_stream(sd, false);
910
-
911
- if (((mode->width == 720) && (mode->height == 576)) ||
912
- ((mode->width == 720) && (mode->height == 480)))
913
- index = 1;
914
- else
915
- index = 0;
916
-
917
- __v4l2_ctrl_s_ctrl(lt6911uxc->link_freq, index);
918
- v4l2_dbg(1, debug, sd, "%s res wxh:%dx%d, link freq:%llu", __func__,
919
- mode->width, mode->height, link_freq_menu_items[index]);
920993
921994 return 0;
922995 }
....@@ -946,11 +1019,40 @@
9461019 static long lt6911uxc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
9471020 {
9481021 struct lt6911uxc *lt6911uxc = to_state(sd);
1022
+ struct device *dev = &lt6911uxc->i2c_client->dev;
9491023 long ret = 0;
1024
+ struct rkmodule_csi_dphy_param *dphy_param;
1025
+ struct rkmodule_capture_info *capture_info;
9501026
9511027 switch (cmd) {
9521028 case RKMODULE_GET_MODULE_INFO:
9531029 lt6911uxc_get_module_inf(lt6911uxc, (struct rkmodule_inf *)arg);
1030
+ break;
1031
+ case RKMODULE_GET_HDMI_MODE:
1032
+ *(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
+ }
9541056 break;
9551057 default:
9561058 ret = -ENOIOCTLCMD;
....@@ -967,6 +1069,9 @@
9671069 void __user *up = compat_ptr(arg);
9681070 struct rkmodule_inf *inf;
9691071 long ret;
1072
+ int *seq;
1073
+ struct rkmodule_csi_dphy_param *dphy_param;
1074
+ struct rkmodule_capture_info *capture_info;
9701075
9711076 switch (cmd) {
9721077 case RKMODULE_GET_MODULE_INFO:
....@@ -984,7 +1089,65 @@
9841089 }
9851090 kfree(inf);
9861091 break;
1092
+ case RKMODULE_GET_HDMI_MODE:
1093
+ seq = kzalloc(sizeof(*seq), GFP_KERNEL);
1094
+ if (!seq) {
1095
+ ret = -ENOMEM;
1096
+ return ret;
1097
+ }
9871098
1099
+ ret = lt6911uxc_ioctl(sd, cmd, seq);
1100
+ if (!ret) {
1101
+ ret = copy_to_user(up, seq, sizeof(*seq));
1102
+ if (ret)
1103
+ ret = -EFAULT;
1104
+ }
1105
+ 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);
1150
+ break;
9881151 default:
9891152 ret = -ENOIOCTLCMD;
9901153 break;
....@@ -993,10 +1156,6 @@
9931156 return ret;
9941157 }
9951158 #endif
996
-
997
-static const struct v4l2_ctrl_ops lt6911uxc_ctrl_ops = {
998
- .g_volatile_ctrl = lt6911uxc_get_ctrl,
999
-};
10001159
10011160 static const struct v4l2_subdev_core_ops lt6911uxc_core_ops = {
10021161 .interrupt_service_routine = lt6911uxc_isr,
....@@ -1013,7 +1172,6 @@
10131172 .s_dv_timings = lt6911uxc_s_dv_timings,
10141173 .g_dv_timings = lt6911uxc_g_dv_timings,
10151174 .query_dv_timings = lt6911uxc_query_dv_timings,
1016
- .g_mbus_config = lt6911uxc_g_mbus_config,
10171175 .s_stream = lt6911uxc_s_stream,
10181176 .g_frame_interval = lt6911uxc_g_frame_interval,
10191177 };
....@@ -1026,6 +1184,7 @@
10261184 .get_fmt = lt6911uxc_get_fmt,
10271185 .enum_dv_timings = lt6911uxc_enum_dv_timings,
10281186 .dv_timings_cap = lt6911uxc_dv_timings_cap,
1187
+ .get_mbus_config = lt6911uxc_g_mbus_config,
10291188 };
10301189
10311190 static const struct v4l2_subdev_ops lt6911uxc_ops = {
....@@ -1068,9 +1227,11 @@
10681227
10691228 static int lt6911uxc_init_v4l2_ctrls(struct lt6911uxc *lt6911uxc)
10701229 {
1230
+ const struct lt6911uxc_mode *mode;
10711231 struct v4l2_subdev *sd;
10721232 int ret;
10731233
1234
+ mode = lt6911uxc->cur_mode;
10741235 sd = &lt6911uxc->sd;
10751236 ret = v4l2_ctrl_handler_init(&lt6911uxc->hdl, 5);
10761237 if (ret)
....@@ -1080,14 +1241,13 @@
10801241 V4L2_CID_LINK_FREQ,
10811242 ARRAY_SIZE(link_freq_menu_items) - 1, 0,
10821243 link_freq_menu_items);
1083
- v4l2_ctrl_new_std(&lt6911uxc->hdl, NULL, V4L2_CID_PIXEL_RATE,
1084
- 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);
10851247
10861248 lt6911uxc->detect_tx_5v_ctrl = v4l2_ctrl_new_std(&lt6911uxc->hdl,
1087
- &lt6911uxc_ctrl_ops, V4L2_CID_DV_RX_POWER_PRESENT,
1249
+ NULL, V4L2_CID_DV_RX_POWER_PRESENT,
10881250 0, 1, 0, 0);
1089
- if (lt6911uxc->detect_tx_5v_ctrl)
1090
- lt6911uxc->detect_tx_5v_ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
10911251
10921252 lt6911uxc->audio_sampling_rate_ctrl =
10931253 v4l2_ctrl_new_custom(&lt6911uxc->hdl,
....@@ -1101,6 +1261,9 @@
11011261 v4l2_err(sd, "cfg v4l2 ctrls failed! ret:%d\n", ret);
11021262 return ret;
11031263 }
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);
11041267
11051268 if (lt6911uxc_update_controls(sd)) {
11061269 ret = -ENODEV;
....@@ -1153,7 +1316,7 @@
11531316 {
11541317 struct device *dev = &lt6911uxc->i2c_client->dev;
11551318 struct device_node *node = dev->of_node;
1156
- struct v4l2_fwnode_endpoint *endpoint;
1319
+ struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
11571320 struct device_node *ep;
11581321 int ret;
11591322
....@@ -1209,15 +1372,14 @@
12091372 return ret;
12101373 }
12111374
1212
- endpoint = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep));
1213
- if (IS_ERR(endpoint)) {
1375
+ ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep), &endpoint);
1376
+ if (ret) {
12141377 dev_err(dev, "failed to parse endpoint\n");
1215
- ret = PTR_ERR(endpoint);
1216
- return ret;
1378
+ goto put_node;
12171379 }
12181380
1219
- if (endpoint->bus_type != V4L2_MBUS_CSI2 ||
1220
- endpoint->bus.mipi_csi2.num_data_lanes == 0) {
1381
+ if (endpoint.bus_type != V4L2_MBUS_CSI2_DPHY ||
1382
+ endpoint.bus.mipi_csi2.num_data_lanes == 0) {
12211383 dev_err(dev, "missing CSI-2 properties in endpoint\n");
12221384 ret = -EINVAL;
12231385 goto free_endpoint;
....@@ -1236,8 +1398,8 @@
12361398 goto free_endpoint;
12371399 }
12381400
1239
- lt6911uxc->csi_lanes_in_use = endpoint->bus.mipi_csi2.num_data_lanes;
1240
- lt6911uxc->bus = endpoint->bus.mipi_csi2;
1401
+ lt6911uxc->csi_lanes_in_use = endpoint.bus.mipi_csi2.num_data_lanes;
1402
+ lt6911uxc->bus = endpoint.bus.mipi_csi2;
12411403 lt6911uxc->enable_hdcp = false;
12421404
12431405 gpiod_set_value(lt6911uxc->hpd_ctl_gpio, 0);
....@@ -1247,7 +1409,9 @@
12471409 ret = 0;
12481410
12491411 free_endpoint:
1250
- v4l2_fwnode_endpoint_free(endpoint);
1412
+ v4l2_fwnode_endpoint_free(&endpoint);
1413
+put_node:
1414
+ of_node_put(ep);
12511415 return ret;
12521416 }
12531417 #else
....@@ -1257,9 +1421,69 @@
12571421 }
12581422 #endif
12591423
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
+
12601482 static int lt6911uxc_probe(struct i2c_client *client,
12611483 const struct i2c_device_id *id)
12621484 {
1485
+ struct v4l2_dv_timings default_timing =
1486
+ V4L2_DV_BT_CEA_640X480P59_94;
12631487 struct lt6911uxc *lt6911uxc;
12641488 struct v4l2_subdev *sd;
12651489 struct device *dev = &client->dev;
....@@ -1277,14 +1501,19 @@
12771501
12781502 sd = &lt6911uxc->sd;
12791503 lt6911uxc->i2c_client = client;
1504
+ lt6911uxc->timings = default_timing;
12801505 lt6911uxc->cur_mode = &supported_modes[0];
1281
- lt6911uxc->mbus_fmt_code = MEDIA_BUS_FMT_UYVY8_2X8;
1506
+ lt6911uxc->mbus_fmt_code = LT6911UXC_MEDIA_BUS_FMT;
12821507
12831508 err = lt6911uxc_parse_of(lt6911uxc);
12841509 if (err) {
12851510 v4l2_err(sd, "lt6911uxc_parse_of failed! err:%d\n", err);
12861511 return err;
12871512 }
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");
12881517
12891518 err = lt6911uxc_check_chip_id(lt6911uxc);
12901519 if (err < 0)
....@@ -1330,6 +1559,14 @@
13301559 goto err_clean_entity;
13311560 }
13321561
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;
1569
+
13331570 INIT_DELAYED_WORK(&lt6911uxc->delayed_work_enable_hotplug,
13341571 lt6911uxc_delayed_work_enable_hotplug);
13351572 INIT_DELAYED_WORK(&lt6911uxc->delayed_work_res_change,
....@@ -1353,20 +1590,15 @@
13531590 }
13541591
13551592 lt6911uxc->plugin_irq = gpiod_to_irq(lt6911uxc->plugin_det_gpio);
1356
- if (lt6911uxc->plugin_irq < 0) {
1357
- dev_err(dev, "failed to get plugin det irq\n");
1358
- err = lt6911uxc->plugin_irq;
1359
- goto err_work_queues;
1360
- }
1593
+ if (lt6911uxc->plugin_irq < 0)
1594
+ dev_err(dev, "failed to get plugin det irq, maybe no use\n");
13611595
13621596 err = devm_request_threaded_irq(dev, lt6911uxc->plugin_irq, NULL,
13631597 plugin_detect_irq_handler, IRQF_TRIGGER_FALLING |
13641598 IRQF_TRIGGER_RISING | IRQF_ONESHOT, "lt6911uxc",
13651599 lt6911uxc);
1366
- if (err) {
1367
- dev_err(dev, "failed to register plugin det irq (%d)\n", err);
1368
- goto err_work_queues;
1369
- }
1600
+ if (err)
1601
+ dev_err(dev, "failed to register plugin det irq (%d), maybe no use\n", err);
13701602
13711603 err = v4l2_ctrl_handler_setup(sd->ctrl_handler);
13721604 if (err) {
....@@ -1444,4 +1676,5 @@
14441676
14451677 MODULE_DESCRIPTION("Lontium LT6911UXC HDMI to MIPI CSI-2 bridge driver");
14461678 MODULE_AUTHOR("Dingxian Wen <shawn.wen@rock-chips.com>");
1679
+MODULE_AUTHOR("Jianwei Fan <jianwei.fan@rock-chips.com>");
14471680 MODULE_LICENSE("GPL v2");