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