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