xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_dw_hdmi_qp.c (revision 3f3f40cd59320e8b274fce3e3becf4dd08c2c8a4)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd
4  * Author: Algea Cao <algea.cao@rock-chips.com>
5  */
6 
7 #include <common.h>
8 #include <boot_rkimg.h>
9 #include <clk.h>
10 #include <fdtdec.h>
11 #include <regmap.h>
12 #include <syscon.h>
13 #include <asm/arch-rockchip/clock.h>
14 #include <asm/io.h>
15 #include <asm-generic/gpio.h>
16 #include <dm/of_access.h>
17 #include <dm/device.h>
18 #include <linux/dw_hdmi.h>
19 #include <linux/hdmi.h>
20 #include <linux/media-bus-format.h>
21 #include "rockchip_display.h"
22 #include "rockchip_crtc.h"
23 #include "rockchip_connector.h"
24 #include "rockchip_phy.h"
25 #include "dw_hdmi_qp.h"
26 #include "rockchip_dw_hdmi_qp.h"
27 
28 #define HIWORD_UPDATE(val, mask)	((val) | (mask) << 16)
29 
30 #define RK3576_IOC_MISC_CON0		0xa400
31 #define RK3576_HDMITX_HPD_INT_MSK	BIT(2)
32 #define RK3576_HDMITX_HPD_INT_CLR	BIT(1)
33 #define RK3576_IOC_HDMITX_HPD_STATUS	0xa440
34 #define RK3576_HDMITX_LOW_MORETHAN100MS	BIT(7)
35 #define RK3576_HDMITX_HPD_PORT_LEVEL	BIT(6)
36 #define RK3576_HDMITX_IHPD_PORT		BIT(5)
37 #define RK3576_HDMITX_OHPD_INT		BIT(4)
38 #define RK3576_HDMITX_LEVEL_INT		BIT(3)
39 #define RK3576_HDMITX_INTR_CHANGE_CNT	0x7
40 
41 #define RK3576_VO0_GRF_SOC_CON1		0x0004
42 #define RK3576_HDMITX_FRL_MOD		BIT(0)
43 #define RK3576_HDMI_HDCP14_MEM_EN	BIT(15)
44 
45 #define RK3576_VO0_GRF_SOC_CON8		0x0020
46 #define RK3576_COLOR_FORMAT_MASK	(0xf << 4)
47 #define RK3576_COLOR_DEPTH_MASK		(0xf << 8)
48 #define RK3576_RGB			(0 << 4)
49 #define RK3576_YUV422			(0x1 << 4)
50 #define RK3576_YUV444			(0x2 << 4)
51 #define RK3576_YUV420			(0x3 << 4)
52 #define RK3576_8BPC			(0x0 << 8)
53 #define RK3576_10BPC			(0x6 << 8)
54 #define RK3576_CECIN_MASK		BIT(3)
55 
56 #define RK3576_VO0_GRF_SOC_CON12	0x0030
57 #define RK3576_GRF_OSDA_DLYN		(0xf << 12)
58 #define RK3576_GRF_OSDA_DIV		(0x7f << 1)
59 #define RK3576_GRF_OSDA_DLY_EN		BIT(0)
60 
61 #define RK3576_VO0_GRF_SOC_CON14	0x0038
62 #define RK3576_I2S_SEL_MASK		BIT(0)
63 #define RK3576_SPDIF_SEL_MASK		BIT(1)
64 #define RK3576_SCLIN_MASK		BIT(4)
65 #define RK3576_SDAIN_MASK		BIT(5)
66 #define RK3576_HDMITX_GRANT_SEL		BIT(6)
67 
68 #define RK3588_GRF_SOC_CON2		0x0308
69 #define RK3588_HDMI1_HPD_INT_MSK	BIT(15)
70 #define RK3588_HDMI1_HPD_INT_CLR	BIT(14)
71 #define RK3588_HDMI0_HPD_INT_MSK	BIT(13)
72 #define RK3588_HDMI0_HPD_INT_CLR	BIT(12)
73 #define RK3588_GRF_SOC_CON7		0x031c
74 #define RK3588_SET_HPD_PATH_MASK	(0x3 << 12)
75 #define RK3588_GRF_SOC_STATUS1		0x0384
76 #define RK3588_HDMI0_LOW_MORETHAN100MS	BIT(20)
77 #define RK3588_HDMI0_HPD_PORT_LEVEL	BIT(19)
78 #define RK3588_HDMI0_IHPD_PORT		BIT(18)
79 #define RK3588_HDMI0_OHPD_INT		BIT(17)
80 #define RK3588_HDMI0_LEVEL_INT		BIT(16)
81 #define RK3588_HDMI0_INTR_CHANGE_CNT	(0x7 << 13)
82 #define RK3588_HDMI1_LOW_MORETHAN100MS	BIT(28)
83 #define RK3588_HDMI1_HPD_PORT_LEVEL	BIT(27)
84 #define RK3588_HDMI1_IHPD_PORT		BIT(26)
85 #define RK3588_HDMI1_OHPD_INT		BIT(25)
86 #define RK3588_HDMI1_LEVEL_INT		BIT(24)
87 #define RK3588_HDMI1_INTR_CHANGE_CNT	(0x7 << 21)
88 
89 #define RK3588_GRF_VO1_CON3		0x000c
90 #define RK3588_COLOR_FORMAT_MASK	0xf
91 #define RK3588_YUV422			0x1
92 #define RK3588_YUV444			0x2
93 #define RK3588_YUV420			0x3
94 #define RK3588_COMPRESSED_DATA		0xb
95 #define RK3588_COLOR_DEPTH_MASK		(0xf << 4)
96 #define RK3588_8BPC			0
97 #define RK3588_10BPC			(0x6 << 4)
98 #define RK3588_CECIN_MASK		BIT(8)
99 #define RK3588_SCLIN_MASK		BIT(9)
100 #define RK3588_SDAIN_MASK		BIT(10)
101 #define RK3588_MODE_MASK		BIT(11)
102 #define RK3588_COMPRESS_MODE_MASK	BIT(12)
103 #define RK3588_I2S_SEL_MASK		BIT(13)
104 #define RK3588_SPDIF_SEL_MASK		BIT(14)
105 #define RK3588_GRF_VO1_CON4		0x0010
106 #define RK3588_HDMI21_MASK		BIT(0)
107 #define RK3588_GRF_VO1_CON9		0x0024
108 #define RK3588_HDMI0_GRANT_SEL		BIT(10)
109 #define RK3588_HDMI0_GRANT_SW		BIT(11)
110 #define RK3588_HDMI1_GRANT_SEL		BIT(12)
111 #define RK3588_HDMI1_GRANT_SW		BIT(13)
112 #define RK3588_GRF_VO1_CON6		0x0018
113 #define RK3588_GRF_VO1_CON7		0x001c
114 
115 #define PPS_TABLE_LEN 8
116 
117 #define COLOR_DEPTH_10BIT		BIT(31)
118 #define HDMI_FRL_MODE			BIT(30)
119 #define HDMI_EARC_MODE			BIT(29)
120 #define DATA_RATE_MASK			0xFFFFFFF
121 
122 #define HDMI20_MAX_RATE			600000
123 #define HDMI_8K60_RATE			2376000
124 
125 struct pps_data {
126 	u32 pic_width;
127 	u32 pic_height;
128 	u32 slice_width;
129 	u32 slice_height;
130 	bool convert_rgb;
131 	u8 bpc;
132 	u8 bpp;
133 	u8 raw_pps[128];
134 };
135 
136 enum hdmi_frl_rate_per_lane {
137 	FRL_12G_PER_LANE = 12,
138 	FRL_10G_PER_LANE = 10,
139 	FRL_8G_PER_LANE = 8,
140 	FRL_6G_PER_LANE = 6,
141 	FRL_3G_PER_LANE = 3,
142 };
143 
144 struct rockchip_hdmi;
145 
146 struct rockchip_hdmi_chip_ops {
147 	void (*set_link_mode)(struct rockchip_hdmi *hdmi);
148 	void (*set_color_format)(struct rockchip_hdmi *hdmi, u64 bus_format, u32 depth);
149 	void (*get_grf_color_fmt)(struct rockchip_hdmi *hdmi, u32 *fmt, u32 *depth);
150 	void (*io_path_init)(struct rockchip_hdmi *hdmi);
151 	enum drm_connector_status (*read_hpd)(struct rockchip_hdmi *hdmi);
152 };
153 
154 struct rockchip_hdmi {
155 	struct rockchip_connector connector;
156 	int id;
157 	struct udevice *dev;
158 	struct regmap *regmap;
159 	struct regmap *vo1_regmap;
160 	void *grf;
161 	void *vo0_grf;
162 	void *vo1_grf;
163 
164 	unsigned long bus_format;
165 	unsigned long output_bus_format;
166 	unsigned long enc_out_encoding;
167 
168 	u8 max_frl_rate_per_lane;
169 	u8 max_lanes;
170 	bool allm_en;
171 	u32 bus_width;
172 	u32 sda_falling_delay_ns;
173 	struct drm_hdmi_dsc_cap dsc_cap;
174 	struct dw_hdmi_link_config link_cfg;
175 
176 	struct clk link_clk;
177 
178 	struct gpio_desc enable_gpio;
179 	const struct dw_hdmi_plat_data *plat_data;
180 	struct rockchip_hdmi_chip_ops *ops;
181 };
182 
183 /*
184  * Selected Rate Control Related Parameter Recommended Values
185  * from DSC_v1.11 spec & C Model release: DSC_model_20161212
186  */
187 static struct pps_data pps_datas[PPS_TABLE_LEN] = {
188 	{
189 		/* 7680x4320/960X96 rgb 8bpc 12bpp */
190 		7680, 4320, 960, 96, 1, 8, 192,
191 		{
192 			0x12, 0x00, 0x00, 0x8d, 0x30, 0xc0, 0x10, 0xe0,
193 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0,
194 			0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9,
195 			0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa,
196 			0x08, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00,
197 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
198 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
199 			0x7d, 0x7e, 0x00, 0x82, 0x00, 0xc0, 0x09, 0x00,
200 			0x09, 0x7e, 0x19, 0xbc, 0x19, 0xba, 0x19, 0xf8,
201 			0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76,
202 			0x2a, 0x76, 0x2a, 0x74, 0x3a, 0xb4, 0x52, 0xf4,
203 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
208 		},
209 	},
210 	{
211 		/* 7680x4320/960X96 rgb 8bpc 11bpp */
212 		7680, 4320, 960, 96, 1, 8, 176,
213 		{
214 			0x12, 0x00, 0x00, 0x8d, 0x30, 0xb0, 0x10, 0xe0,
215 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28,
216 			0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0,
217 			0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33,
218 			0x0f, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00,
219 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
220 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
221 			0x7d, 0x7e, 0x00, 0x82, 0x01, 0x00, 0x09, 0x40,
222 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
223 			0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76,
224 			0x2a, 0x76, 0x2a, 0xb4, 0x3a, 0xb4, 0x52, 0xf4,
225 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
227 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
230 		},
231 	},
232 	{
233 		/* 7680x4320/960X96 rgb 8bpc 10bpp */
234 		7680, 4320, 960, 96, 1, 8, 160,
235 		{
236 			0x12, 0x00, 0x00, 0x8d, 0x30, 0xa0, 0x10, 0xe0,
237 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0,
238 			0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0,
239 			0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb,
240 			0x16, 0x00, 0x10, 0xec, 0x03, 0x0c, 0x20, 0x00,
241 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
242 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
243 			0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40,
244 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
245 			0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6,
246 			0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x5b, 0x34,
247 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
252 		},
253 	},
254 	{
255 		/* 7680x4320/960X96 rgb 8bpc 9bpp */
256 		7680, 4320, 960, 96, 1, 8, 144,
257 		{
258 			0x12, 0x00, 0x00, 0x8d, 0x30, 0x90, 0x10, 0xe0,
259 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38,
260 			0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7,
261 			0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa,
262 			0x17, 0x00, 0x10, 0xf1, 0x03, 0x0c, 0x20, 0x00,
263 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
264 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
265 			0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40,
266 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
267 			0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6,
268 			0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x63, 0x74,
269 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
274 		},
275 	},
276 	{
277 		/* 7680x4320/960X96 rgb 10bpc 12bpp */
278 		7680, 4320, 960, 96, 1, 10, 192,
279 		{
280 			0x12, 0x00, 0x00, 0xad, 0x30, 0xc0, 0x10, 0xe0,
281 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0,
282 			0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9,
283 			0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa,
284 			0x08, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00,
285 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
286 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
287 			0x7d, 0x7e, 0x01, 0x02, 0x11, 0x80, 0x22, 0x00,
288 			0x22, 0x7e, 0x32, 0xbc, 0x32, 0xba, 0x3a, 0xf8,
289 			0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76,
290 			0x4b, 0x76, 0x4b, 0x74, 0x5b, 0xb4, 0x73, 0xf4,
291 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
296 		},
297 	},
298 	{
299 		/* 7680x4320/960X96 rgb 10bpc 11bpp */
300 		7680, 4320, 960, 96, 1, 10, 176,
301 		{
302 			0x12, 0x00, 0x00, 0xad, 0x30, 0xb0, 0x10, 0xe0,
303 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28,
304 			0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0,
305 			0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33,
306 			0x0f, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00,
307 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
308 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
309 			0x7d, 0x7e, 0x01, 0x42, 0x19, 0xc0, 0x2a, 0x40,
310 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
311 			0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76,
312 			0x4b, 0x76, 0x4b, 0xb4, 0x5b, 0xb4, 0x73, 0xf4,
313 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
318 		},
319 	},
320 	{
321 		/* 7680x4320/960X96 rgb 10bpc 10bpp */
322 		7680, 4320, 960, 96, 1, 10, 160,
323 		{
324 			0x12, 0x00, 0x00, 0xad, 0x30, 0xa0, 0x10, 0xe0,
325 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0,
326 			0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0,
327 			0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb,
328 			0x16, 0x00, 0x10, 0xec, 0x07, 0x10, 0x20, 0x00,
329 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
330 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
331 			0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40,
332 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
333 			0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6,
334 			0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x7c, 0x34,
335 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
338 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
340 		},
341 	},
342 	{
343 		/* 7680x4320/960X96 rgb 10bpc 9bpp */
344 		7680, 4320, 960, 96, 1, 10, 144,
345 		{
346 			0x12, 0x00, 0x00, 0xad, 0x30, 0x90, 0x10, 0xe0,
347 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38,
348 			0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7,
349 			0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa,
350 			0x17, 0x00, 0x10, 0xf1, 0x07, 0x10, 0x20, 0x00,
351 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
352 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
353 			0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40,
354 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
355 			0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6,
356 			0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x84, 0x74,
357 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
360 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
362 		},
363 	},
364 };
365 
366 static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
367 {
368 	switch (bus_format) {
369 	case MEDIA_BUS_FMT_RGB888_1X24:
370 	case MEDIA_BUS_FMT_RGB101010_1X30:
371 	case MEDIA_BUS_FMT_RGB121212_1X36:
372 	case MEDIA_BUS_FMT_RGB161616_1X48:
373 		return true;
374 
375 	default:
376 		return false;
377 	}
378 }
379 
380 static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
381 {
382 	switch (bus_format) {
383 	case MEDIA_BUS_FMT_YUV8_1X24:
384 	case MEDIA_BUS_FMT_YUV10_1X30:
385 	case MEDIA_BUS_FMT_YUV12_1X36:
386 	case MEDIA_BUS_FMT_YUV16_1X48:
387 		return true;
388 
389 	default:
390 		return false;
391 	}
392 }
393 
394 static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
395 {
396 	switch (bus_format) {
397 	case MEDIA_BUS_FMT_UYVY8_1X16:
398 	case MEDIA_BUS_FMT_UYVY10_1X20:
399 	case MEDIA_BUS_FMT_UYVY12_1X24:
400 	case MEDIA_BUS_FMT_YUYV8_1X16:
401 	case MEDIA_BUS_FMT_YUYV10_1X20:
402 	case MEDIA_BUS_FMT_YUYV12_1X24:
403 		return true;
404 
405 	default:
406 		return false;
407 	}
408 }
409 
410 static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
411 {
412 	switch (bus_format) {
413 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
414 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
415 	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
416 	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
417 		return true;
418 
419 	default:
420 	return false;
421 	}
422 }
423 
424 static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
425 {
426 	switch (bus_format) {
427 	case MEDIA_BUS_FMT_RGB888_1X24:
428 	case MEDIA_BUS_FMT_YUV8_1X24:
429 	case MEDIA_BUS_FMT_UYVY8_1X16:
430 	case MEDIA_BUS_FMT_YUYV8_1X16:
431 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
432 		return 8;
433 
434 	case MEDIA_BUS_FMT_RGB101010_1X30:
435 	case MEDIA_BUS_FMT_YUV10_1X30:
436 	case MEDIA_BUS_FMT_UYVY10_1X20:
437 	case MEDIA_BUS_FMT_YUYV10_1X20:
438 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
439 		return 10;
440 
441 	case MEDIA_BUS_FMT_RGB121212_1X36:
442 	case MEDIA_BUS_FMT_YUV12_1X36:
443 	case MEDIA_BUS_FMT_UYVY12_1X24:
444 	case MEDIA_BUS_FMT_YUYV12_1X24:
445 	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
446 		return 12;
447 
448 	case MEDIA_BUS_FMT_RGB161616_1X48:
449 	case MEDIA_BUS_FMT_YUV16_1X48:
450 	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
451 		return 16;
452 
453 	default:
454 		return 0;
455 	}
456 }
457 
458 static unsigned int
459 hdmi_get_tmdsclock(struct rockchip_hdmi *hdmi, unsigned long pixelclock)
460 {
461 	unsigned int tmdsclock = pixelclock;
462 	unsigned int depth =
463 		hdmi_bus_fmt_color_depth(hdmi->output_bus_format);
464 
465 	if (!hdmi_bus_fmt_is_yuv422(hdmi->output_bus_format)) {
466 		switch (depth) {
467 		case 16:
468 			tmdsclock = pixelclock * 2;
469 			break;
470 		case 12:
471 			tmdsclock = pixelclock * 3 / 2;
472 			break;
473 		case 10:
474 			tmdsclock = pixelclock * 5 / 4;
475 			break;
476 		default:
477 			break;
478 		}
479 	}
480 
481 	return tmdsclock;
482 }
483 
484 static void hdmi_select_link_config(struct rockchip_hdmi *hdmi,
485 				    struct drm_display_mode *mode,
486 				    unsigned int tmdsclk)
487 {
488 	int max_lanes, max_rate_per_lane;
489 	int max_dsc_lanes, max_dsc_rate_per_lane;
490 	unsigned long max_frl_rate;
491 
492 	max_lanes = hdmi->max_lanes;
493 	max_rate_per_lane = hdmi->max_frl_rate_per_lane;
494 	max_frl_rate = max_lanes * max_rate_per_lane * 1000000;
495 
496 	hdmi->link_cfg.dsc_mode = false;
497 	hdmi->link_cfg.frl_lanes = max_lanes;
498 	hdmi->link_cfg.rate_per_lane = max_rate_per_lane;
499 	hdmi->link_cfg.allm_en = hdmi->allm_en;
500 
501 	if (!max_frl_rate ||
502 	    (tmdsclk < HDMI20_MAX_RATE && mode->clock < HDMI20_MAX_RATE)) {
503 		printf("%s use tmds mode\n", __func__);
504 		hdmi->link_cfg.frl_mode = false;
505 		return;
506 	}
507 
508 	hdmi->link_cfg.frl_mode = true;
509 
510 	if (!hdmi->dsc_cap.v_1p2)
511 		return;
512 
513 	max_dsc_lanes = hdmi->dsc_cap.max_lanes;
514 	max_dsc_rate_per_lane =
515 		hdmi->dsc_cap.max_frl_rate_per_lane;
516 
517 	if (mode->clock >= HDMI_8K60_RATE &&
518 	    !hdmi_bus_fmt_is_yuv420(hdmi->bus_format) &&
519 	    !hdmi_bus_fmt_is_yuv422(hdmi->bus_format)) {
520 		hdmi->link_cfg.dsc_mode = true;
521 		hdmi->link_cfg.frl_lanes = max_dsc_lanes;
522 		hdmi->link_cfg.rate_per_lane = max_dsc_rate_per_lane;
523 	} else {
524 		hdmi->link_cfg.dsc_mode = false;
525 		hdmi->link_cfg.frl_lanes = max_lanes;
526 		hdmi->link_cfg.rate_per_lane = max_rate_per_lane;
527 	}
528 }
529 
530 /////////////////////////////////////////////////////////////////////////////////////
531 
532 static int hdmi_dsc_get_slice_height(int vactive)
533 {
534 	int slice_height;
535 
536 	/*
537 	 * Slice Height determination : HDMI2.1 Section 7.7.5.2
538 	 * Select smallest slice height >=96, that results in a valid PPS and
539 	 * requires minimum padding lines required for final slice.
540 	 *
541 	 * Assumption : Vactive is even.
542 	 */
543 	for (slice_height = 96; slice_height <= vactive; slice_height += 2)
544 		if (vactive % slice_height == 0)
545 			return slice_height;
546 
547 	return 0;
548 }
549 
550 static int hdmi_dsc_get_num_slices(struct rockchip_hdmi *hdmi,
551 				   struct drm_display_mode *mode,
552 				   int src_max_slices, int src_max_slice_width,
553 				   int hdmi_max_slices, int hdmi_throughput)
554 {
555 /* Pixel rates in KPixels/sec */
556 #define HDMI_DSC_PEAK_PIXEL_RATE		2720000
557 /*
558  * Rates at which the source and sink are required to process pixels in each
559  * slice, can be two levels: either at least 340000KHz or at least 40000KHz.
560  */
561 #define HDMI_DSC_MAX_ENC_THROUGHPUT_0		340000
562 #define HDMI_DSC_MAX_ENC_THROUGHPUT_1		400000
563 
564 /* Spec limits the slice width to 2720 pixels */
565 #define MAX_HDMI_SLICE_WIDTH			2720
566 	int kslice_adjust;
567 	int adjusted_clk_khz;
568 	int min_slices;
569 	int target_slices;
570 	int max_throughput; /* max clock freq. in khz per slice */
571 	int max_slice_width;
572 	int slice_width;
573 	int pixel_clock = mode->clock;
574 
575 	if (!hdmi_throughput)
576 		return 0;
577 
578 	/*
579 	 * Slice Width determination : HDMI2.1 Section 7.7.5.1
580 	 * kslice_adjust factor for 4:2:0, and 4:2:2 formats is 0.5, where as
581 	 * for 4:4:4 is 1.0. Multiplying these factors by 10 and later
582 	 * dividing adjusted clock value by 10.
583 	 */
584 	if (hdmi_bus_fmt_is_yuv444(hdmi->output_bus_format) ||
585 	    hdmi_bus_fmt_is_rgb(hdmi->output_bus_format))
586 		kslice_adjust = 10;
587 	else
588 		kslice_adjust = 5;
589 
590 	/*
591 	 * As per spec, the rate at which the source and the sink process
592 	 * the pixels per slice are at two levels: at least 340Mhz or 400Mhz.
593 	 * This depends upon the pixel clock rate and output formats
594 	 * (kslice adjust).
595 	 * If pixel clock * kslice adjust >= 2720MHz slices can be processed
596 	 * at max 340MHz, otherwise they can be processed at max 400MHz.
597 	 */
598 
599 	adjusted_clk_khz = DIV_ROUND_UP(kslice_adjust * pixel_clock, 10);
600 
601 	if (adjusted_clk_khz <= HDMI_DSC_PEAK_PIXEL_RATE)
602 		max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_0;
603 	else
604 		max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_1;
605 
606 	/*
607 	 * Taking into account the sink's capability for maximum
608 	 * clock per slice (in MHz) as read from HF-VSDB.
609 	 */
610 	max_throughput = min(max_throughput, hdmi_throughput * 1000);
611 
612 	min_slices = DIV_ROUND_UP(adjusted_clk_khz, max_throughput);
613 	max_slice_width = min(MAX_HDMI_SLICE_WIDTH, src_max_slice_width);
614 
615 	/*
616 	 * Keep on increasing the num of slices/line, starting from min_slices
617 	 * per line till we get such a number, for which the slice_width is
618 	 * just less than max_slice_width. The slices/line selected should be
619 	 * less than or equal to the max horizontal slices that the combination
620 	 * of PCON encoder and HDMI decoder can support.
621 	 */
622 	do {
623 		if (min_slices <= 1 && src_max_slices >= 1 && hdmi_max_slices >= 1)
624 			target_slices = 1;
625 		else if (min_slices <= 2 && src_max_slices >= 2 && hdmi_max_slices >= 2)
626 			target_slices = 2;
627 		else if (min_slices <= 4 && src_max_slices >= 4 && hdmi_max_slices >= 4)
628 			target_slices = 4;
629 		else if (min_slices <= 8 && src_max_slices >= 8 && hdmi_max_slices >= 8)
630 			target_slices = 8;
631 		else if (min_slices <= 12 && src_max_slices >= 12 && hdmi_max_slices >= 12)
632 			target_slices = 12;
633 		else if (min_slices <= 16 && src_max_slices >= 16 && hdmi_max_slices >= 16)
634 			target_slices = 16;
635 		else
636 			return 0;
637 
638 		slice_width = DIV_ROUND_UP(mode->hdisplay, target_slices);
639 		if (slice_width > max_slice_width)
640 			min_slices = target_slices + 1;
641 	} while (slice_width > max_slice_width);
642 
643 	return target_slices;
644 }
645 
646 static int hdmi_dsc_slices(struct rockchip_hdmi *hdmi,
647 			   struct drm_display_mode *mode)
648 {
649 	int hdmi_throughput = hdmi->dsc_cap.clk_per_slice;
650 	int hdmi_max_slices = hdmi->dsc_cap.max_slices;
651 	int rk_max_slices = 8;
652 	int rk_max_slice_width = 2048;
653 
654 	return hdmi_dsc_get_num_slices(hdmi, mode, rk_max_slices,
655 				       rk_max_slice_width,
656 				       hdmi_max_slices, hdmi_throughput);
657 }
658 
659 static int
660 hdmi_dsc_get_bpp(struct rockchip_hdmi *hdmi, int src_fractional_bpp,
661 		 int slice_width, int num_slices, bool hdmi_all_bpp,
662 		 int hdmi_max_chunk_bytes)
663 {
664 	int max_dsc_bpp, min_dsc_bpp;
665 	int target_bytes;
666 	bool bpp_found = false;
667 	int bpp_decrement_x16;
668 	int bpp_target;
669 	int bpp_target_x16;
670 
671 	/*
672 	 * Get min bpp and max bpp as per Table 7.23, in HDMI2.1 spec
673 	 * Start with the max bpp and keep on decrementing with
674 	 * fractional bpp, if supported by PCON DSC encoder
675 	 *
676 	 * for each bpp we check if no of bytes can be supported by HDMI sink
677 	 */
678 
679 	/* only 9\10\12 bpp was tested */
680 	min_dsc_bpp = 9;
681 	max_dsc_bpp = 12;
682 
683 	/*
684 	 * Taking into account if all dsc_all_bpp supported by HDMI2.1 sink
685 	 * Section 7.7.34 : Source shall not enable compressed Video
686 	 * Transport with bpp_target settings above 12 bpp unless
687 	 * DSC_all_bpp is set to 1.
688 	 */
689 	if (!hdmi_all_bpp)
690 		max_dsc_bpp = min(max_dsc_bpp, 12);
691 
692 	/*
693 	 * The Sink has a limit of compressed data in bytes for a scanline,
694 	 * as described in max_chunk_bytes field in HFVSDB block of edid.
695 	 * The no. of bytes depend on the target bits per pixel that the
696 	 * source configures. So we start with the max_bpp and calculate
697 	 * the target_chunk_bytes. We keep on decrementing the target_bpp,
698 	 * till we get the target_chunk_bytes just less than what the sink's
699 	 * max_chunk_bytes, or else till we reach the min_dsc_bpp.
700 	 *
701 	 * The decrement is according to the fractional support from PCON DSC
702 	 * encoder. For fractional BPP we use bpp_target as a multiple of 16.
703 	 *
704 	 * bpp_target_x16 = bpp_target * 16
705 	 * So we need to decrement by {1, 2, 4, 8, 16} for fractional bpps
706 	 * {1/16, 1/8, 1/4, 1/2, 1} respectively.
707 	 */
708 
709 	bpp_target = max_dsc_bpp;
710 
711 	/* src does not support fractional bpp implies decrement by 16 for bppx16 */
712 	if (!src_fractional_bpp)
713 		src_fractional_bpp = 1;
714 	bpp_decrement_x16 = DIV_ROUND_UP(16, src_fractional_bpp);
715 	bpp_target_x16 = bpp_target * 16;
716 
717 	while (bpp_target_x16 > (min_dsc_bpp * 16)) {
718 		int bpp;
719 
720 		bpp = DIV_ROUND_UP(bpp_target_x16, 16);
721 		target_bytes = DIV_ROUND_UP((num_slices * slice_width * bpp), 8);
722 		if (target_bytes <= hdmi_max_chunk_bytes) {
723 			bpp_found = true;
724 			break;
725 		}
726 		bpp_target_x16 -= bpp_decrement_x16;
727 	}
728 	if (bpp_found)
729 		return bpp_target_x16;
730 
731 	return 0;
732 }
733 
734 static int
735 dw_hdmi_dsc_bpp(struct rockchip_hdmi *hdmi,
736 		int num_slices, int slice_width)
737 {
738 	bool hdmi_all_bpp = hdmi->dsc_cap.all_bpp;
739 	int fractional_bpp = 0;
740 	int hdmi_max_chunk_bytes = hdmi->dsc_cap.total_chunk_kbytes * 1024;
741 
742 	return hdmi_dsc_get_bpp(hdmi, fractional_bpp, slice_width,
743 				num_slices, hdmi_all_bpp,
744 				hdmi_max_chunk_bytes);
745 }
746 
747 static int dw_hdmi_qp_set_link_cfg(struct rockchip_hdmi *hdmi,
748 				   u16 pic_width, u16 pic_height,
749 				   u16 slice_width, u16 slice_height,
750 				   u16 bits_per_pixel, u8 bits_per_component)
751 {
752 	int i;
753 
754 	for (i = 0; i < PPS_TABLE_LEN; i++)
755 		if (pic_width == pps_datas[i].pic_width &&
756 		    pic_height == pps_datas[i].pic_height &&
757 		    slice_width == pps_datas[i].slice_width &&
758 		    slice_height == pps_datas[i].slice_height &&
759 		    bits_per_component == pps_datas[i].bpc &&
760 		    bits_per_pixel == pps_datas[i].bpp &&
761 		    hdmi_bus_fmt_is_rgb(hdmi->output_bus_format) == pps_datas[i].convert_rgb)
762 			break;
763 
764 	if (i == PPS_TABLE_LEN) {
765 		dev_err(hdmi->dev, "can't find pps cfg!\n");
766 		return -EINVAL;
767 	}
768 
769 	memcpy(hdmi->link_cfg.pps_payload, pps_datas[i].raw_pps, 128);
770 	hdmi->link_cfg.hcactive = DIV_ROUND_UP(slice_width * (bits_per_pixel / 16), 8) *
771 		(pic_width / slice_width);
772 
773 	return 0;
774 }
775 
776 static void dw_hdmi_qp_dsc_configure(struct rockchip_hdmi *hdmi,
777 				     struct drm_display_mode *mode)
778 {
779 	int ret;
780 	int slice_height;
781 	int slice_width;
782 	int bits_per_pixel;
783 	int slice_count;
784 	bool hdmi_is_dsc_1_2;
785 	unsigned int depth = hdmi_bus_fmt_color_depth(hdmi->output_bus_format);
786 
787 	hdmi_is_dsc_1_2 = hdmi->dsc_cap.v_1p2;
788 
789 	if (!hdmi_is_dsc_1_2)
790 		return;
791 
792 	slice_height = hdmi_dsc_get_slice_height(mode->vdisplay);
793 	if (!slice_height)
794 		return;
795 
796 	slice_count = hdmi_dsc_slices(hdmi, mode);
797 	if (!slice_count)
798 		return;
799 
800 	slice_width = DIV_ROUND_UP(mode->hdisplay, slice_count);
801 
802 	bits_per_pixel = dw_hdmi_dsc_bpp(hdmi, slice_count, slice_width);
803 	if (!bits_per_pixel)
804 		return;
805 
806 	ret = dw_hdmi_qp_set_link_cfg(hdmi, mode->hdisplay,
807 				      mode->vdisplay, slice_width,
808 				      slice_height, bits_per_pixel, depth);
809 
810 	if (ret) {
811 		dev_err(hdmi->dev, "set vdsc cfg failed\n");
812 		return;
813 	}
814 	printf("dsc_enable\n");
815 }
816 
817 static unsigned int drm_rk_select_color(struct hdmi_edid_data *edid_data,
818 					struct base_screen_info *screen_info,
819 					enum dw_hdmi_devtype dev_type,
820 					bool output_bus_format_rgb)
821 {
822 	struct drm_display_info *info = &edid_data->display_info;
823 	struct drm_display_mode *mode = edid_data->preferred_mode;
824 	struct drm_hdmi_info *hdmi_info = &edid_data->display_info.hdmi;
825 	int max_tmds_clock = info->max_tmds_clock;
826 	bool support_dc = false;
827 	bool mode_420 = drm_mode_is_420(info, mode);
828 	unsigned int color_depth = 8;
829 	unsigned int base_color = DRM_HDMI_OUTPUT_YCBCR444;
830 	unsigned int color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
831 	unsigned long tmdsclock, pixclock = mode->clock;
832 
833 	if (screen_info)
834 		base_color = screen_info->format;
835 
836 	switch (base_color) {
837 	case DRM_HDMI_OUTPUT_YCBCR_HQ:
838 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
839 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
840 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
841 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
842 		else if (mode_420 && pixclock >= 340000)
843 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
844 		break;
845 	case DRM_HDMI_OUTPUT_YCBCR_LQ:
846 		if (mode_420 && pixclock >= 340000)
847 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
848 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
849 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
850 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
851 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
852 		break;
853 	case DRM_HDMI_OUTPUT_YCBCR420:
854 		if (mode_420 && pixclock >= 340000)
855 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
856 		break;
857 	case DRM_HDMI_OUTPUT_YCBCR422:
858 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
859 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
860 		break;
861 	case DRM_HDMI_OUTPUT_YCBCR444:
862 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
863 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
864 		break;
865 	case DRM_HDMI_OUTPUT_DEFAULT_RGB:
866 	default:
867 		break;
868 	}
869 
870 	if (output_bus_format_rgb)
871 		color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
872 
873 	if (color_format == DRM_HDMI_OUTPUT_DEFAULT_RGB &&
874 	    info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)
875 		support_dc = true;
876 	if (color_format == DRM_HDMI_OUTPUT_YCBCR444 &&
877 	    (info->edid_hdmi_dc_modes &
878 	     (DRM_EDID_HDMI_DC_Y444 | DRM_EDID_HDMI_DC_30)))
879 		support_dc = true;
880 	if (color_format == DRM_HDMI_OUTPUT_YCBCR422)
881 		support_dc = true;
882 	if (color_format == DRM_HDMI_OUTPUT_YCBCR420 &&
883 	    info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
884 		support_dc = true;
885 
886 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
887 		pixclock *= 2;
888 
889 	if (screen_info && screen_info->depth == 10)
890 		color_depth = screen_info->depth;
891 
892 	if (mode->clock > 1188000)
893 		color_format = DRM_HDMI_OUTPUT_YCBCR420;
894 
895 	if (color_format == DRM_HDMI_OUTPUT_YCBCR422 || color_depth == 8)
896 		tmdsclock = pixclock;
897 	else
898 		tmdsclock = pixclock * color_depth / 8;
899 
900 	if (color_format == DRM_HDMI_OUTPUT_YCBCR420)
901 		tmdsclock /= 2;
902 
903 	if (!max_tmds_clock)
904 		max_tmds_clock = 340000;
905 
906 	if (hdmi_info->max_frl_rate_per_lane && mode->clock > 600000)
907 		max_tmds_clock =
908 			hdmi_info->max_lanes * hdmi_info->max_frl_rate_per_lane *
909 				1000000;
910 
911 	if (tmdsclock > max_tmds_clock) {
912 		if (max_tmds_clock >= 594000) {
913 			color_depth = 8;
914 		} else if (max_tmds_clock > 340000) {
915 			if (drm_mode_is_420(info, mode) || tmdsclock >= 594000)
916 				color_format = DRM_HDMI_OUTPUT_YCBCR420;
917 		} else {
918 			color_depth = 8;
919 			if (drm_mode_is_420(info, mode) || tmdsclock >= 594000)
920 				color_format = DRM_HDMI_OUTPUT_YCBCR420;
921 		}
922 	}
923 
924 	printf("color_format:%x\n", color_format);
925 	if (color_depth > 8 && support_dc) {
926 		switch (color_format) {
927 		case DRM_HDMI_OUTPUT_YCBCR444:
928 			return MEDIA_BUS_FMT_YUV10_1X30;
929 		case DRM_HDMI_OUTPUT_YCBCR422:
930 			return MEDIA_BUS_FMT_YUYV10_1X20;
931 		case DRM_HDMI_OUTPUT_YCBCR420:
932 			return MEDIA_BUS_FMT_UYYVYY10_0_5X30;
933 		default:
934 			return MEDIA_BUS_FMT_RGB101010_1X30;
935 		}
936 	} else {
937 		switch (color_format) {
938 		case DRM_HDMI_OUTPUT_YCBCR444:
939 			return MEDIA_BUS_FMT_YUV8_1X24;
940 		case DRM_HDMI_OUTPUT_YCBCR422:
941 			return MEDIA_BUS_FMT_YUYV8_1X16;
942 		case DRM_HDMI_OUTPUT_YCBCR420:
943 			return MEDIA_BUS_FMT_UYYVYY8_0_5X24;
944 		default:
945 			return MEDIA_BUS_FMT_RGB888_1X24;
946 		}
947 	}
948 }
949 
950 #define SUPPORT_HDMI_ALLM	BIT(1)
951 
952 void dw_hdmi_qp_select_output(struct hdmi_edid_data *edid_data,
953 			      struct rockchip_connector *conn,
954 			      unsigned int *bus_format,
955 			      struct overscan *overscan,
956 			      enum dw_hdmi_devtype dev_type,
957 			      bool output_bus_format_rgb,
958 			      void *data, struct display_state *state)
959 {
960 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
961 	struct drm_hdmi_info *hdmi_info = &edid_data->display_info.hdmi;
962 	int ret, i, screen_size;
963 	struct base_disp_info base_parameter;
964 	struct base2_disp_info *base2_parameter = state->conn_state.disp_info;
965 	const struct base_overscan *scan;
966 	struct base_screen_info *screen_info = NULL;
967 	struct base2_screen_info *screen_info2 = NULL;
968 	int max_scan = 100;
969 	int min_scan = 51;
970 	int offset = 0;
971 	int color_depth;
972 	unsigned int tmdsclk;
973 	unsigned int pixel_clk;
974 	bool found = false;
975 	struct blk_desc *dev_desc;
976 	disk_partition_t part_info;
977 	char baseparameter_buf[8 * RK_BLK_SIZE] __aligned(ARCH_DMA_MINALIGN);
978 
979 	overscan->left_margin = max_scan;
980 	overscan->right_margin = max_scan;
981 	overscan->top_margin = max_scan;
982 	overscan->bottom_margin = max_scan;
983 
984 	hdmi->max_frl_rate_per_lane = hdmi_info->max_frl_rate_per_lane;
985 	hdmi->max_lanes = hdmi_info->max_lanes;
986 	memcpy(&hdmi->dsc_cap, &hdmi_info->dsc_cap, sizeof(struct drm_hdmi_dsc_cap));
987 
988 	if (output_bus_format_rgb)
989 		*bus_format = MEDIA_BUS_FMT_RGB888_1X24;
990 	else
991 		*bus_format = MEDIA_BUS_FMT_YUV8_1X24;
992 
993 	if (!base2_parameter) {
994 		dev_desc = rockchip_get_bootdev();
995 		if (!dev_desc) {
996 			printf("%s: Could not find device\n", __func__);
997 			goto null_basep;
998 		}
999 
1000 		ret = part_get_info_by_name(dev_desc, "baseparameter",
1001 					    &part_info);
1002 		if (ret < 0) {
1003 			printf("Could not find baseparameter partition\n");
1004 			goto null_basep;
1005 		}
1006 
1007 read_aux:
1008 		ret = blk_dread(dev_desc, part_info.start + offset, 1,
1009 				(void *)baseparameter_buf);
1010 		if (ret < 0) {
1011 			printf("read baseparameter failed\n");
1012 			goto null_basep;
1013 		}
1014 
1015 		memcpy(&base_parameter, baseparameter_buf,
1016 		       sizeof(base_parameter));
1017 		scan = &base_parameter.scan;
1018 
1019 		screen_size = sizeof(base_parameter.screen_list) /
1020 			sizeof(base_parameter.screen_list[0]);
1021 
1022 		for (i = 0; i < screen_size; i++) {
1023 			if (base_parameter.screen_list[i].type ==
1024 			    DRM_MODE_CONNECTOR_HDMIA) {
1025 				found = true;
1026 				screen_info = &base_parameter.screen_list[i];
1027 				break;
1028 			}
1029 		}
1030 
1031 		if (!found && !offset) {
1032 			printf("hdmi info isn't saved in main block\n");
1033 			offset += 16;
1034 			goto read_aux;
1035 		}
1036 	} else {
1037 		bool allm_en = false;
1038 
1039 		scan = &base2_parameter->overscan_info;
1040 		screen_size = sizeof(base2_parameter->screen_info) /
1041 			sizeof(base2_parameter->screen_info[0]);
1042 
1043 		for (i = 0; i < screen_size; i++) {
1044 			if (base2_parameter->screen_info[i].type ==
1045 			    DRM_MODE_CONNECTOR_HDMIA) {
1046 				screen_info2 =
1047 					&base2_parameter->screen_info[i];
1048 				break;
1049 			}
1050 		}
1051 		screen_info = malloc(sizeof(*screen_info));
1052 
1053 		screen_info->type = screen_info2->type;
1054 		screen_info->mode = screen_info2->resolution;
1055 		screen_info->format = screen_info2->format;
1056 		screen_info->depth = screen_info2->depthc;
1057 		screen_info->feature = screen_info2->feature;
1058 
1059 		/* check if allm is enabled */
1060 		allm_en = base2_parameter->reserved[0] & BIT(0);
1061 		if (allm_en && (hdmi_info->add_func & SUPPORT_HDMI_ALLM))
1062 			hdmi->allm_en = true;
1063 		else
1064 			hdmi->allm_en = false;
1065 	}
1066 
1067 	if (scan->leftscale < min_scan && scan->leftscale > 0)
1068 		overscan->left_margin = min_scan;
1069 	else if (scan->leftscale < max_scan && scan->leftscale > 0)
1070 		overscan->left_margin = scan->leftscale;
1071 
1072 	if (scan->rightscale < min_scan && scan->rightscale > 0)
1073 		overscan->right_margin = min_scan;
1074 	else if (scan->rightscale < max_scan && scan->rightscale > 0)
1075 		overscan->right_margin = scan->rightscale;
1076 
1077 	if (scan->topscale < min_scan && scan->topscale > 0)
1078 		overscan->top_margin = min_scan;
1079 	else if (scan->topscale < max_scan && scan->topscale > 0)
1080 		overscan->top_margin = scan->topscale;
1081 
1082 	if (scan->bottomscale < min_scan && scan->bottomscale > 0)
1083 		overscan->bottom_margin = min_scan;
1084 	else if (scan->bottomscale < max_scan && scan->bottomscale > 0)
1085 		overscan->bottom_margin = scan->bottomscale;
1086 
1087 null_basep:
1088 
1089 	if (screen_info)
1090 		printf("base_parameter.mode:%dx%d\n",
1091 		       screen_info->mode.hdisplay,
1092 		       screen_info->mode.vdisplay);
1093 	drm_rk_select_mode(edid_data, screen_info);
1094 
1095 	*bus_format = drm_rk_select_color(edid_data, screen_info,
1096 					  dev_type, output_bus_format_rgb);
1097 
1098 	if (state->force_output) {
1099 		memcpy(edid_data->preferred_mode, &state->force_mode,
1100 		       sizeof(struct drm_display_mode));
1101 		if (state->force_bus_format)
1102 			*bus_format = state->force_bus_format;
1103 	}
1104 
1105 	hdmi->bus_format = *bus_format;
1106 	color_depth = hdmi_bus_fmt_color_depth(*bus_format);
1107 	pixel_clk = edid_data->preferred_mode->clock;
1108 	tmdsclk = hdmi_get_tmdsclock(hdmi, pixel_clk);
1109 	if (hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format))
1110 		tmdsclk /= 2;
1111 	hdmi_select_link_config(hdmi, edid_data->preferred_mode, tmdsclk);
1112 	dw_hdmi_qp_dsc_configure(hdmi, edid_data->preferred_mode);
1113 	if (hdmi->link_cfg.frl_mode) {
1114 		if (dm_gpio_is_valid(&hdmi->enable_gpio))
1115 			dm_gpio_set_value(&hdmi->enable_gpio, 0);
1116 		/* in the current version, support max 40G frl */
1117 		if (hdmi->link_cfg.rate_per_lane >= 10) {
1118 			hdmi->link_cfg.frl_lanes = 4;
1119 			hdmi->link_cfg.rate_per_lane = 10;
1120 		}
1121 		hdmi->bus_width = hdmi->link_cfg.frl_lanes *
1122 			hdmi->link_cfg.rate_per_lane * 1000000;
1123 		/* 10 bit color depth and frl mode */
1124 		if (color_depth == 10)
1125 			hdmi->bus_width |=
1126 				COLOR_DEPTH_10BIT | HDMI_FRL_MODE;
1127 		else
1128 			hdmi->bus_width |= HDMI_FRL_MODE;
1129 	} else {
1130 		if (dm_gpio_is_valid(&hdmi->enable_gpio))
1131 			dm_gpio_set_value(&hdmi->enable_gpio, 1);
1132 		hdmi->bus_width =
1133 			hdmi_get_tmdsclock(hdmi, pixel_clk * 10);
1134 		if (hdmi_bus_fmt_is_yuv420(*bus_format))
1135 			hdmi->bus_width /= 2;
1136 
1137 		if (color_depth == 10 && !hdmi_bus_fmt_is_yuv422(*bus_format))
1138 			hdmi->bus_width |= COLOR_DEPTH_10BIT;
1139 	}
1140 
1141 	rockchip_phy_set_bus_width(conn->phy, hdmi->bus_width);
1142 }
1143 
1144 bool dw_hdmi_qp_check_enable_gpio(void *data)
1145 {
1146 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1147 
1148 	if (!hdmi->enable_gpio.dev)
1149 		return false;
1150 	else
1151 		return true;
1152 }
1153 
1154 static void rk3576_set_link_mode(struct rockchip_hdmi *hdmi)
1155 {
1156 	int val;
1157 
1158 	if (!hdmi->link_cfg.frl_mode)
1159 		val = HIWORD_UPDATE(0, RK3576_HDMITX_FRL_MOD);
1160 	else
1161 		val = HIWORD_UPDATE(RK3576_HDMITX_FRL_MOD, RK3576_HDMITX_FRL_MOD);
1162 	writel(val, hdmi->vo0_grf + RK3576_VO0_GRF_SOC_CON1);
1163 }
1164 
1165 static void rk3588_set_link_mode(struct rockchip_hdmi *hdmi)
1166 {
1167 	int val;
1168 	bool is_hdmi0;
1169 
1170 	if (!hdmi->id)
1171 		is_hdmi0 = true;
1172 	else
1173 		is_hdmi0 = false;
1174 
1175 	if (!hdmi->link_cfg.frl_mode) {
1176 		val = HIWORD_UPDATE(0, RK3588_HDMI21_MASK);
1177 		if (is_hdmi0)
1178 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON4);
1179 		else
1180 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON7);
1181 
1182 		val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
1183 		if (is_hdmi0)
1184 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
1185 		else
1186 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
1187 
1188 		return;
1189 	}
1190 
1191 	val = HIWORD_UPDATE(RK3588_HDMI21_MASK, RK3588_HDMI21_MASK);
1192 	if (is_hdmi0)
1193 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON4);
1194 	else
1195 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON7);
1196 
1197 	if (hdmi->link_cfg.dsc_mode) {
1198 		val = HIWORD_UPDATE(RK3588_COMPRESS_MODE_MASK | RK3588_COMPRESSED_DATA,
1199 				    RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
1200 		if (is_hdmi0)
1201 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
1202 		else
1203 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
1204 	} else {
1205 		val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
1206 		if (is_hdmi0)
1207 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
1208 		else
1209 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
1210 	}
1211 }
1212 
1213 static void rk3576_set_color_format(struct rockchip_hdmi *hdmi, u64 bus_format,
1214 				    u32 depth)
1215 {
1216 	u32 val = 0;
1217 
1218 	switch (bus_format) {
1219 	case MEDIA_BUS_FMT_RGB888_1X24:
1220 	case MEDIA_BUS_FMT_RGB101010_1X30:
1221 		val = HIWORD_UPDATE(0, RK3576_COLOR_FORMAT_MASK);
1222 		break;
1223 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1224 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1225 		val = HIWORD_UPDATE(RK3576_YUV420, RK3576_COLOR_FORMAT_MASK);
1226 		break;
1227 	case MEDIA_BUS_FMT_YUV8_1X24:
1228 	case MEDIA_BUS_FMT_YUV10_1X30:
1229 		val = HIWORD_UPDATE(RK3576_YUV444, RK3576_COLOR_FORMAT_MASK);
1230 		break;
1231 	case MEDIA_BUS_FMT_YUYV10_1X20:
1232 	case MEDIA_BUS_FMT_YUYV8_1X16:
1233 		val = HIWORD_UPDATE(RK3576_YUV422, RK3576_COLOR_FORMAT_MASK);
1234 		break;
1235 	default:
1236 		printf("can't set correct color format\n");
1237 		return;
1238 	}
1239 
1240 	if (depth == 8 || bus_format == MEDIA_BUS_FMT_YUYV10_1X20)
1241 		val |= HIWORD_UPDATE(RK3576_8BPC, RK3576_COLOR_DEPTH_MASK);
1242 	else
1243 		val |= HIWORD_UPDATE(RK3576_10BPC, RK3576_COLOR_DEPTH_MASK);
1244 
1245 	writel(val, hdmi->vo0_grf + RK3576_VO0_GRF_SOC_CON8);
1246 }
1247 
1248 static void rk3588_set_color_format(struct rockchip_hdmi *hdmi, u64 bus_format,
1249 				    u32 depth)
1250 {
1251 	u32 val = 0;
1252 
1253 	switch (bus_format) {
1254 	case MEDIA_BUS_FMT_RGB888_1X24:
1255 	case MEDIA_BUS_FMT_RGB101010_1X30:
1256 		val = HIWORD_UPDATE(0, RK3588_COLOR_FORMAT_MASK);
1257 		break;
1258 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1259 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1260 		val = HIWORD_UPDATE(RK3588_YUV420, RK3588_COLOR_FORMAT_MASK);
1261 		break;
1262 	case MEDIA_BUS_FMT_YUV8_1X24:
1263 	case MEDIA_BUS_FMT_YUV10_1X30:
1264 		val = HIWORD_UPDATE(RK3588_YUV444, RK3588_COLOR_FORMAT_MASK);
1265 		break;
1266 	case MEDIA_BUS_FMT_YUYV10_1X20:
1267 	case MEDIA_BUS_FMT_YUYV8_1X16:
1268 		val = HIWORD_UPDATE(RK3588_YUV422, RK3588_COLOR_FORMAT_MASK);
1269 		break;
1270 	default:
1271 		dev_err(hdmi->dev, "can't set correct color format\n");
1272 		return;
1273 	}
1274 
1275 	if (hdmi->link_cfg.dsc_mode)
1276 		val = HIWORD_UPDATE(RK3588_COMPRESSED_DATA, RK3588_COLOR_FORMAT_MASK);
1277 
1278 	if (depth == 8 || bus_format == MEDIA_BUS_FMT_YUYV10_1X20)
1279 		val |= HIWORD_UPDATE(RK3588_8BPC, RK3588_COLOR_DEPTH_MASK);
1280 	else
1281 		val |= HIWORD_UPDATE(RK3588_10BPC, RK3588_COLOR_DEPTH_MASK);
1282 
1283 	if (!hdmi->id)
1284 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
1285 	else
1286 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
1287 }
1288 
1289 void dw_hdmi_qp_set_grf_cfg(void *data)
1290 {
1291 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1292 	int color_depth;
1293 
1294 	hdmi->ops->set_link_mode(hdmi);
1295 	color_depth = hdmi_bus_fmt_color_depth(hdmi->bus_format);
1296 	hdmi->ops->set_color_format(hdmi, hdmi->bus_format, color_depth);
1297 }
1298 
1299 static
1300 void dw_hdmi_qp_rockchip_sda_delay_cal(struct rockchip_hdmi *hdmi, u8 *sda_dlyn, u8 *sda_div)
1301 {
1302 	u8 i;
1303 	u32 val;
1304 
1305 	for (i = 0; i <= 127; i++) {
1306 		val = DIV_ROUND_UP(hdmi->sda_falling_delay_ns, (i + 1) * 40);
1307 
1308 		if (val <= 15)
1309 			break;
1310 	}
1311 
1312 	if (i > 127) {
1313 		dev_err(hdmi->dev, "delay %d ns,can't calculate correct sda falling delay cfg\n",
1314 			hdmi->sda_falling_delay_ns);
1315 		return;
1316 	}
1317 
1318 	*sda_div = i;
1319 	*sda_dlyn = val;
1320 }
1321 
1322 static void rk3576_io_path_init(struct rockchip_hdmi *hdmi)
1323 {
1324 	u32 val;
1325 	u8 sda_dlyn = 0, sda_div = 0;
1326 
1327 	val = HIWORD_UPDATE(RK3576_SCLIN_MASK, RK3576_SCLIN_MASK) |
1328 	      HIWORD_UPDATE(RK3576_SDAIN_MASK, RK3576_SDAIN_MASK) |
1329 	      HIWORD_UPDATE(RK3576_HDMITX_GRANT_SEL, RK3576_HDMITX_GRANT_SEL) |
1330 	      HIWORD_UPDATE(RK3576_I2S_SEL_MASK, RK3576_I2S_SEL_MASK);
1331 	writel(val, hdmi->vo0_grf + RK3576_VO0_GRF_SOC_CON14);
1332 
1333 	val = HIWORD_UPDATE(0, RK3576_HDMITX_HPD_INT_MSK);
1334 	writel(val, hdmi->grf + RK3576_IOC_MISC_CON0);
1335 
1336 	if (hdmi->sda_falling_delay_ns) {
1337 		dw_hdmi_qp_rockchip_sda_delay_cal(hdmi, &sda_dlyn, &sda_div);
1338 		if (sda_dlyn) {
1339 			val = HIWORD_UPDATE(sda_dlyn << 12, RK3576_GRF_OSDA_DLYN) |
1340 			      HIWORD_UPDATE(sda_div << 1, RK3576_GRF_OSDA_DIV) |
1341 			      HIWORD_UPDATE(1, RK3576_GRF_OSDA_DLY_EN);
1342 
1343 			writel(val, hdmi->vo0_grf + RK3576_VO0_GRF_SOC_CON12);
1344 		}
1345 	}
1346 }
1347 
1348 static void rk3588_io_path_init(struct rockchip_hdmi *hdmi)
1349 {
1350 	u32 val;
1351 
1352 	if (!hdmi->id) {
1353 		val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
1354 		      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
1355 		      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
1356 		      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
1357 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
1358 
1359 		val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
1360 				    RK3588_SET_HPD_PATH_MASK);
1361 		writel(val, hdmi->grf + RK3588_GRF_SOC_CON7);
1362 
1363 		val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
1364 				    RK3588_HDMI0_GRANT_SEL);
1365 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON9);
1366 	} else {
1367 		val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
1368 		      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
1369 		      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
1370 		      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
1371 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
1372 
1373 		val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
1374 				    RK3588_SET_HPD_PATH_MASK);
1375 		writel(val, hdmi->grf + RK3588_GRF_SOC_CON7);
1376 
1377 		val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL,
1378 				    RK3588_HDMI1_GRANT_SEL);
1379 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON9);
1380 	}
1381 }
1382 
1383 void dw_hdmi_qp_io_path_init(void *data)
1384 {
1385 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1386 
1387 	hdmi->ops->io_path_init(hdmi);
1388 }
1389 
1390 struct dw_hdmi_link_config *dw_hdmi_rockchip_get_link_cfg(void *data)
1391 {
1392 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1393 
1394 	return &hdmi->link_cfg;
1395 }
1396 
1397 static void dw_hdmi_qp_rockchip_phy_disable(struct rockchip_connector *conn, void *data,
1398 					    void *state)
1399 {
1400 	rockchip_phy_power_off(conn->phy);
1401 }
1402 
1403 static int dw_hdmi_qp_rockchip_genphy_init(struct rockchip_connector *conn, void *data, void *state)
1404 {
1405 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1406 
1407 	dw_hdmi_qp_rockchip_phy_disable(conn, data, state);
1408 
1409 	rockchip_phy_set_bus_width(conn->phy, hdmi->bus_width);
1410 
1411 	return rockchip_phy_power_on(conn->phy);
1412 }
1413 
1414 static enum drm_connector_status rk3576_read_hpd(struct rockchip_hdmi *hdmi)
1415 {
1416 	u32 val;
1417 	int ret;
1418 
1419 	val = readl(hdmi->grf + RK3576_IOC_HDMITX_HPD_STATUS);
1420 
1421 	if (val & RK3576_HDMITX_LEVEL_INT)
1422 		ret = connector_status_connected;
1423 	else
1424 		ret = connector_status_disconnected;
1425 
1426 	return ret;
1427 }
1428 
1429 static enum drm_connector_status rk3588_read_hpd(struct rockchip_hdmi *hdmi)
1430 {
1431 	u32 val;
1432 	int ret;
1433 
1434 	val = readl(hdmi->grf + RK3588_GRF_SOC_STATUS1);
1435 
1436 	if (!hdmi->id) {
1437 		if (val & RK3588_HDMI0_LEVEL_INT)
1438 			ret = connector_status_connected;
1439 		else
1440 			ret = connector_status_disconnected;
1441 	} else {
1442 		if (val & RK3588_HDMI1_LEVEL_INT)
1443 			ret = connector_status_connected;
1444 		else
1445 			ret = connector_status_disconnected;
1446 	}
1447 
1448 	return ret;
1449 }
1450 
1451 static enum drm_connector_status rockchip_hdmi_qp_read_hpd(void *data)
1452 {
1453 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1454 
1455 	return hdmi->ops->read_hpd(hdmi);
1456 }
1457 
1458 static void rockchip_hdmi_qp_set_pll(struct rockchip_connector *conn, void *data, void *state)
1459 {
1460 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1461 	u32 rate = (hdmi->bus_width & DATA_RATE_MASK) * 100;
1462 
1463 	clk_set_rate(&hdmi->link_clk, rate);
1464 }
1465 
1466 static const struct dw_hdmi_qp_phy_ops rockchip_hdmi_qp_phy_ops = {
1467 	.init = dw_hdmi_qp_rockchip_genphy_init,
1468 	.disable = dw_hdmi_qp_rockchip_phy_disable,
1469 	.read_hpd = rockchip_hdmi_qp_read_hpd,
1470 	.set_pll = rockchip_hdmi_qp_set_pll,
1471 };
1472 
1473 static const struct rockchip_connector_funcs rockchip_dw_hdmi_qp_funcs = {
1474 	.init = rockchip_dw_hdmi_qp_init,
1475 	.deinit = rockchip_dw_hdmi_qp_deinit,
1476 	.prepare = rockchip_dw_hdmi_qp_prepare,
1477 	.check = rockchip_dw_hdmi_qp_check,
1478 	.enable = rockchip_dw_hdmi_qp_enable,
1479 	.disable = rockchip_dw_hdmi_qp_disable,
1480 	.get_timing = rockchip_dw_hdmi_qp_get_timing,
1481 	.detect = rockchip_dw_hdmi_qp_detect,
1482 	.get_edid = rockchip_dw_hdmi_qp_get_edid,
1483 };
1484 
1485 static const struct rockchip_hdmi_chip_ops rk3576_chip_ops = {
1486 	.set_link_mode = rk3576_set_link_mode,
1487 	.set_color_format = rk3576_set_color_format,
1488 	.io_path_init = rk3576_io_path_init,
1489 	.read_hpd = rk3576_read_hpd,
1490 };
1491 
1492 const struct dw_hdmi_plat_data rk3576_hdmi_drv_data = {
1493 	.qp_phy_ops    = &rockchip_hdmi_qp_phy_ops,
1494 	.phy_name   = "samsung_hdptx_phy",
1495 	.chip_ops   = (void *)&rk3576_chip_ops,
1496 	.dev_type   = RK3576_HDMI,
1497 };
1498 
1499 static const struct rockchip_hdmi_chip_ops rk3588_chip_ops = {
1500 	.set_link_mode = rk3588_set_link_mode,
1501 	.set_color_format = rk3588_set_color_format,
1502 	.io_path_init = rk3588_io_path_init,
1503 	.read_hpd = rk3588_read_hpd,
1504 };
1505 
1506 const struct dw_hdmi_plat_data rk3588_hdmi_drv_data = {
1507 	.qp_phy_ops    = &rockchip_hdmi_qp_phy_ops,
1508 	.phy_name   = "samsung_hdptx_phy",
1509 	.chip_ops   = (void *)&rk3588_chip_ops,
1510 	.dev_type   = RK3588_HDMI,
1511 };
1512 
1513 static int rockchip_dw_hdmi_qp_probe(struct udevice *dev)
1514 {
1515 	int ret;
1516 	struct regmap *map;
1517 	struct rockchip_hdmi *hdmi = dev_get_priv(dev);
1518 	ofnode hdmi_node = dev->node;
1519 
1520 	hdmi->dev = dev;
1521 	hdmi->plat_data = (const struct dw_hdmi_plat_data *)dev_get_driver_data(dev);
1522 
1523 	hdmi->id = of_alias_get_id(ofnode_to_np(dev->node), "hdmi");
1524 	if (hdmi->id < 0)
1525 		hdmi->id = 0;
1526 
1527 	map = syscon_regmap_lookup_by_phandle(dev, "rockchip,grf");
1528 	hdmi->grf = regmap_get_range(map, 0);
1529 
1530 	if (hdmi->grf <= 0) {
1531 		dev_err(dev, "%s: Get syscon grf failed (ret=%p)\n",
1532 			__func__, hdmi->grf);
1533 		return -ENXIO;
1534 	}
1535 
1536 	if (hdmi->plat_data->dev_type == RK3588_HDMI) {
1537 		map = syscon_regmap_lookup_by_phandle(dev, "rockchip,vo1_grf");
1538 		hdmi->vo1_grf = regmap_get_range(map, 0);
1539 
1540 		if (hdmi->vo1_grf <= 0) {
1541 			dev_err(dev, "%s: Get syscon vo1 grf failed (ret=%p)\n",
1542 				__func__, hdmi->vo1_grf);
1543 			return -ENXIO;
1544 		}
1545 	} else if (hdmi->plat_data->dev_type == RK3576_HDMI) {
1546 		map = syscon_regmap_lookup_by_phandle(dev, "rockchip,vo0_grf");
1547 		hdmi->vo0_grf = regmap_get_range(map, 0);
1548 
1549 		if (hdmi->vo0_grf <= 0) {
1550 			dev_err(dev, "%s: Get syscon vo0 grf failed (ret=%p)\n",
1551 				__func__, hdmi->vo0_grf);
1552 			return -ENXIO;
1553 		}
1554 	}
1555 
1556 	hdmi->sda_falling_delay_ns =
1557 		ofnode_read_u32_default(hdmi_node, "rockchip,sda-falling-delay-ns", 0);
1558 
1559 	ret = gpio_request_by_name(dev, "enable-gpios", 0,
1560 				   &hdmi->enable_gpio, GPIOD_IS_OUT);
1561 	if (ret && ret != -ENOENT) {
1562 		dev_err(dev, "Cannot get enable GPIO: %d\n", ret);
1563 		return ret;
1564 	}
1565 
1566 	ret = clk_get_by_name(dev, "link_clk", &hdmi->link_clk);
1567 	if (ret) {
1568 		printf("%s: can't get link_clk\n", __func__);
1569 		return ret;
1570 	}
1571 
1572 	hdmi->ops = (struct rockchip_hdmi_chip_ops *)hdmi->plat_data->chip_ops;
1573 
1574 	rockchip_connector_bind(&hdmi->connector, dev, hdmi->id, &rockchip_dw_hdmi_qp_funcs,
1575 				NULL, DRM_MODE_CONNECTOR_HDMIA);
1576 
1577 	return 0;
1578 }
1579 
1580 static const struct udevice_id rockchip_dw_hdmi_qp_ids[] = {
1581 	{
1582 	 .compatible = "rockchip,rk3588-dw-hdmi",
1583 	 .data = (ulong)&rk3588_hdmi_drv_data,
1584 	},
1585 	{
1586 	 .compatible = "rockchip,rk3576-dw-hdmi",
1587 	 .data = (ulong)&rk3576_hdmi_drv_data,
1588 	}, {}
1589 };
1590 
1591 U_BOOT_DRIVER(rockchip_dw_hdmi_qp) = {
1592 	.name = "rockchip_dw_hdmi_qp",
1593 	.id = UCLASS_DISPLAY,
1594 	.of_match = rockchip_dw_hdmi_qp_ids,
1595 	.probe	= rockchip_dw_hdmi_qp_probe,
1596 	.priv_auto_alloc_size = sizeof(struct rockchip_hdmi),
1597 };
1598