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