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