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