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