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