xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_dw_hdmi.c (revision 87e4c6020eff05133e40ab8b7b0e37e6a2be37e4)
1 /*
2  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <boot_rkimg.h>
9 #include <asm/io.h>
10 #include <dm/device.h>
11 #include <linux/dw_hdmi.h>
12 #include <linux/hdmi.h>
13 #include <linux/media-bus-format.h>
14 #include "rockchip_display.h"
15 #include "rockchip_crtc.h"
16 #include "rockchip_connector.h"
17 #include "dw_hdmi.h"
18 #include "rockchip_dw_hdmi.h"
19 
20 #define HDMI_SEL_LCDC(x, bit)  ((((x) & 1) << bit) | (1 << (16 + bit)))
21 #define RK3288_GRF_SOC_CON6		0x025C
22 #define RK3288_HDMI_LCDC_SEL		BIT(4)
23 #define RK3399_GRF_SOC_CON20		0x6250
24 #define RK3399_HDMI_LCDC_SEL		BIT(6)
25 
26 #define RK3228_IO_3V_DOMAIN              ((7 << 4) | (7 << (4 + 16)))
27 #define RK3328_IO_3V_DOMAIN              (7 << (9 + 16))
28 #define RK3328_IO_5V_DOMAIN              ((7 << 9) | (3 << (9 + 16)))
29 #define RK3328_IO_CTRL_BY_HDMI           ((1 << 13) | (1 << (13 + 16)))
30 #define RK3328_IO_DDC_IN_MSK             ((3 << 10) | (3 << (10 + 16)))
31 #define RK3228_IO_DDC_IN_MSK             ((3 << 13) | (3 << (13 + 16)))
32 #define RK3228_GRF_SOC_CON2              0x0408
33 #define RK3228_GRF_SOC_CON6              0x0418
34 #define RK3328_GRF_SOC_CON2              0x0408
35 #define RK3328_GRF_SOC_CON3              0x040c
36 #define RK3328_GRF_SOC_CON4              0x0410
37 
38 #define DRM_BASE_MODE(c, hd, hss, hse, ht, vd, vss, vse, vt, vs, f) \
39 	.clock = (c), \
40 	.hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \
41 	.htotal = (ht), .vdisplay = (vd), \
42 	.vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \
43 	.vscan = (vs), .flags = (f)
44 
45 static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = {
46 	{
47 		30666000, {
48 			{ 0x00b3, 0x0000 },
49 			{ 0x2153, 0x0000 },
50 			{ 0x40f3, 0x0000 },
51 		},
52 	},  {
53 		36800000, {
54 			{ 0x00b3, 0x0000 },
55 			{ 0x2153, 0x0000 },
56 			{ 0x40a2, 0x0001 },
57 		},
58 	},  {
59 		46000000, {
60 			{ 0x00b3, 0x0000 },
61 			{ 0x2142, 0x0001 },
62 			{ 0x40a2, 0x0001 },
63 		},
64 	},  {
65 		61333000, {
66 			{ 0x0072, 0x0001 },
67 			{ 0x2142, 0x0001 },
68 			{ 0x40a2, 0x0001 },
69 		},
70 	},  {
71 		73600000, {
72 			{ 0x0072, 0x0001 },
73 			{ 0x2142, 0x0001 },
74 			{ 0x4061, 0x0002 },
75 		},
76 	},  {
77 		92000000, {
78 			{ 0x0072, 0x0001 },
79 			{ 0x2145, 0x0002 },
80 			{ 0x4061, 0x0002 },
81 		},
82 	},  {
83 		122666000, {
84 			{ 0x0051, 0x0002 },
85 			{ 0x2145, 0x0002 },
86 			{ 0x4061, 0x0002 },
87 		},
88 	},  {
89 		147200000, {
90 			{ 0x0051, 0x0002 },
91 			{ 0x2145, 0x0002 },
92 			{ 0x4064, 0x0003 },
93 		},
94 	},  {
95 		184000000, {
96 			{ 0x0051, 0x0002 },
97 			{ 0x214c, 0x0003 },
98 			{ 0x4064, 0x0003 },
99 		},
100 	},  {
101 		226666000, {
102 			{ 0x0040, 0x0003 },
103 			{ 0x214c, 0x0003 },
104 			{ 0x4064, 0x0003 },
105 		},
106 	},  {
107 		272000000, {
108 			{ 0x0040, 0x0003 },
109 			{ 0x214c, 0x0003 },
110 			{ 0x5a64, 0x0003 },
111 		},
112 	},  {
113 		340000000, {
114 			{ 0x0040, 0x0003 },
115 			{ 0x3b4c, 0x0003 },
116 			{ 0x5a64, 0x0003 },
117 		},
118 	},  {
119 		600000000, {
120 			{ 0x1a40, 0x0003 },
121 			{ 0x3b4c, 0x0003 },
122 			{ 0x5a64, 0x0003 },
123 		},
124 	},  {
125 		~0UL, {
126 			{ 0x0000, 0x0000 },
127 			{ 0x0000, 0x0000 },
128 			{ 0x0000, 0x0000 },
129 		},
130 	}
131 };
132 
133 static const struct dw_hdmi_mpll_config rockchip_mpll_cfg_420[] = {
134 	{
135 		30666000, {
136 			{ 0x00b7, 0x0000 },
137 			{ 0x2157, 0x0000 },
138 			{ 0x40f7, 0x0000 },
139 		},
140 	},  {
141 		92000000, {
142 			{ 0x00b7, 0x0000 },
143 			{ 0x2143, 0x0001 },
144 			{ 0x40a3, 0x0001 },
145 		},
146 	},  {
147 		184000000, {
148 			{ 0x0073, 0x0001 },
149 			{ 0x2146, 0x0002 },
150 			{ 0x4062, 0x0002 },
151 		},
152 	},  {
153 		340000000, {
154 			{ 0x0052, 0x0003 },
155 			{ 0x214d, 0x0003 },
156 			{ 0x4065, 0x0003 },
157 		},
158 	},  {
159 		600000000, {
160 			{ 0x0041, 0x0003 },
161 			{ 0x3b4d, 0x0003 },
162 			{ 0x5a65, 0x0003 },
163 		},
164 	},  {
165 		~0UL, {
166 			{ 0x0000, 0x0000 },
167 			{ 0x0000, 0x0000 },
168 			{ 0x0000, 0x0000 },
169 		},
170 	}
171 };
172 
173 static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = {
174 	/*      pixelclk    bpp8    bpp10   bpp12 */
175 	{
176 		600000000, { 0x0000, 0x0000, 0x0000 },
177 	},  {
178 		~0UL,      { 0x0000, 0x0000, 0x0000},
179 	}
180 };
181 
182 static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
183 	/*pixelclk   symbol   term   vlev*/
184 	{ 74250000,  0x8009, 0x0004, 0x0272},
185 	{ 165000000, 0x802b, 0x0004, 0x0209},
186 	{ 297000000, 0x8039, 0x0005, 0x028d},
187 	{ 594000000, 0x8039, 0x0000, 0x019d},
188 	{ ~0UL,	     0x0000, 0x0000, 0x0000}
189 };
190 
191 static const struct base_drm_display_mode resolution_white[] = {
192 	/* 0. vic:2 - 720x480@60Hz */
193 	{ DRM_BASE_MODE(27000, 720, 736,
194 			798, 858, 480, 489, 495, 525, 0,
195 			DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
196 	  .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
197 	/* 1. vic:3 - 720x480@60Hz */
198 	{ DRM_BASE_MODE(27000, 720, 736,
199 			798, 858, 480, 489, 495, 525, 0,
200 			DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
201 	  .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
202 	/* 2. vic:4 - 1280x720@60Hz */
203 	{ DRM_BASE_MODE(74250, 1280, 1390,
204 			1430, 1650, 720, 725, 730, 750, 0,
205 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
206 	  .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
207 	/* 3. vic:5 - 1920x1080i@60Hz */
208 	{ DRM_BASE_MODE(74250, 1920, 2008,
209 			2052, 2200, 1080, 1084, 1094, 1125, 0,
210 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
211 			DRM_MODE_FLAG_INTERLACE),
212 	  .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
213 	/* 4. vic:6 - 720(1440)x480i@60Hz */
214 	{ DRM_BASE_MODE(13500, 720, 739,
215 			801, 858, 480, 488, 494, 525, 0,
216 			DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
217 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
218 	  .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
219 	/* 5. vic:16 - 1920x1080@60Hz */
220 	{ DRM_BASE_MODE(148500, 1920, 2008,
221 			2052, 2200, 1080, 1084, 1089, 1125, 0,
222 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
223 	  .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
224 	/* 6. vic:17 - 720x576@50Hz */
225 	{ DRM_BASE_MODE(27000, 720, 732,
226 			796, 864, 576, 581, 586, 625, 0,
227 			DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
228 	  .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
229 	/* 7. vic:18 - 720x576@50Hz */
230 	{ DRM_BASE_MODE(27000, 720, 732,
231 			796, 864, 576, 581, 586, 625, 0,
232 			DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
233 	  .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
234 	/* 8. vic:19 - 1280x720@50Hz */
235 	{ DRM_BASE_MODE(74250, 1280, 1720,
236 			1760, 1980, 720, 725, 730, 750, 0,
237 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
238 	  .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
239 	/* 9. vic:20 - 1920x1080i@50Hz */
240 	{ DRM_BASE_MODE(74250, 1920, 2448,
241 			2492, 2640, 1080, 1084, 1094, 1125, 0,
242 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
243 			DRM_MODE_FLAG_INTERLACE),
244 	  .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
245 	/* 10. vic:21 - 720(1440)x576i@50Hz */
246 	{ DRM_BASE_MODE(13500, 720, 732,
247 			795, 864, 576, 580, 586, 625, 0,
248 			DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
249 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
250 	  .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
251 	/* 11. vic:31 - 1920x1080@50Hz */
252 	{ DRM_BASE_MODE(148500, 1920, 2448,
253 			2492, 2640, 1080, 1084, 1089, 1125, 0,
254 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
255 	  .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
256 	/* 12. vic:32 - 1920x1080@24Hz */
257 	{ DRM_BASE_MODE(74250, 1920, 2558,
258 			2602, 2750, 1080, 1084, 1089, 1125, 0,
259 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
260 	  .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
261 	/* 13. vic:33 - 1920x1080@25Hz */
262 	{ DRM_BASE_MODE(74250, 1920, 2448,
263 			2492, 2640, 1080, 1084, 1089, 1125, 0,
264 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
265 	  .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
266 	/* 14. vic:34 - 1920x1080@30Hz */
267 	{ DRM_BASE_MODE(74250, 1920, 2008,
268 			2052, 2200, 1080, 1084, 1089, 1125, 0,
269 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
270 	  .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
271 	/* 15. vic:39 - 1920x1080i@50Hz */
272 	{ DRM_BASE_MODE(72000, 1920, 1952,
273 			2120, 2304, 1080, 1126, 1136, 1250, 0,
274 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC |
275 			DRM_MODE_FLAG_INTERLACE),
276 	  .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
277 	/* 16. vic:60 - 1280x720@24Hz */
278 	{ DRM_BASE_MODE(59400, 1280, 3040,
279 			3080, 3300, 720, 725, 730, 750, 0,
280 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
281 	  .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
282 	/* 17. vic:61 - 1280x720@25Hz */
283 	{ DRM_BASE_MODE(74250, 1280, 3700,
284 			3740, 3960, 720, 725, 730, 750, 0,
285 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
286 	  .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
287 	/* 18. vic:62 - 1280x720@30Hz */
288 	{ DRM_BASE_MODE(74250, 1280, 3040,
289 			3080, 3300, 720, 725, 730, 750, 0,
290 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
291 	  .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
292 	/* 19. vic:93 - 3840x2160p@24Hz 16:9 */
293 	{ DRM_BASE_MODE(297000, 3840, 5116,
294 			5204, 5500, 2160, 2168, 2178, 2250, 0,
295 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
296 	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
297 	/* 20. vic:94 - 3840x2160p@25Hz 16:9 */
298 	{ DRM_BASE_MODE(297000, 3840, 4896,
299 			4984, 5280, 2160, 2168, 2178, 2250, 0,
300 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
301 	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
302 	/* 21. vic:95 - 3840x2160p@30Hz 16:9 */
303 	{ DRM_BASE_MODE(297000, 3840, 4016,
304 			4104, 4400, 2160, 2168, 2178, 2250, 0,
305 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
306 	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
307 	/* 22. vic:96 - 3840x2160p@50Hz 16:9 */
308 	{ DRM_BASE_MODE(594000, 3840, 4896,
309 			4984, 5280, 2160, 2168, 2178, 2250, 0,
310 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
311 	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
312 	/* 23. vic:97 - 3840x2160p@60Hz 16:9 */
313 	{ DRM_BASE_MODE(594000, 3840, 4016,
314 			4104, 4400, 2160, 2168, 2178, 2250, 0,
315 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
316 	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
317 	/* 24. vic:98 - 4096x2160p@24Hz 256:135 */
318 	{ DRM_BASE_MODE(297000, 4096, 5116,
319 			5204, 5500, 2160, 2168, 2178, 2250, 0,
320 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
321 	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
322 	/* 25. vic:99 - 4096x2160p@25Hz 256:135 */
323 	{ DRM_BASE_MODE(297000, 4096, 5064,
324 			5152, 5280, 2160, 2168, 2178, 2250, 0,
325 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
326 	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
327 	/* 26. vic:100 - 4096x2160p@30Hz 256:135 */
328 	{ DRM_BASE_MODE(297000, 4096, 4184,
329 			4272, 4400, 2160, 2168, 2178, 2250, 0,
330 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
331 	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
332 	/* 27. vic:101 - 4096x2160p@50Hz 256:135 */
333 	{ DRM_BASE_MODE(594000, 4096, 5064,
334 			5152, 5280, 2160, 2168, 2178, 2250, 0,
335 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
336 	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
337 	/* 28. vic:102 - 4096x2160p@60Hz 256:135 */
338 	{ DRM_BASE_MODE(594000, 4096, 4184,
339 			4272, 4400, 2160, 2168, 2178, 2250, 0,
340 			DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
341 	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
342 };
343 
344 static bool drm_mode_equal(const struct base_drm_display_mode *mode1,
345 			   const struct drm_display_mode *mode2)
346 {
347 	unsigned int flags_mask =
348 		DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_PHSYNC |
349 		DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC |
350 		DRM_MODE_FLAG_NVSYNC;
351 
352 	if (mode1->clock == mode2->clock &&
353 	    mode1->hdisplay == mode2->hdisplay &&
354 	    mode1->hsync_start == mode2->hsync_start &&
355 	    mode1->hsync_end == mode2->hsync_end &&
356 	    mode1->htotal == mode2->htotal &&
357 	    mode1->vdisplay == mode2->vdisplay &&
358 	    mode1->vsync_start == mode2->vsync_start &&
359 	    mode1->vsync_end == mode2->vsync_end &&
360 	    mode1->vtotal == mode2->vtotal &&
361 	    (mode1->flags & flags_mask) == (mode2->flags & flags_mask)) {
362 		return true;
363 	}
364 
365 	return false;
366 }
367 
368 /**
369  * drm_mode_sort - sort mode list
370  * @edid_data: modes structures to sort
371  *
372  * Sort @edid_data by favorability, moving good modes to the head of the list.
373  */
374 void drm_mode_sort(struct hdmi_edid_data *edid_data)
375 {
376 	struct drm_display_mode *a, *b;
377 	struct drm_display_mode c;
378 	int diff, i, j;
379 
380 	for (i = 0; i < (edid_data->modes - 1); i++) {
381 		a = &edid_data->mode_buf[i];
382 		for (j = i + 1; j < edid_data->modes; j++) {
383 			b = &edid_data->mode_buf[j];
384 			diff = ((b->type & DRM_MODE_TYPE_PREFERRED) != 0) -
385 				((a->type & DRM_MODE_TYPE_PREFERRED) != 0);
386 			if (diff) {
387 				if (diff > 0) {
388 					c = *a;
389 					*a = *b;
390 					*b = c;
391 				}
392 				continue;
393 			}
394 
395 			diff = b->hdisplay * b->vdisplay
396 				- a->hdisplay * a->vdisplay;
397 			if (diff) {
398 				if (diff > 0) {
399 					c = *a;
400 					*a = *b;
401 					*b = c;
402 				}
403 				continue;
404 			}
405 
406 			diff = b->vrefresh - a->vrefresh;
407 			if (diff) {
408 				if (diff > 0) {
409 					c = *a;
410 					*a = *b;
411 					*b = c;
412 				}
413 				continue;
414 			}
415 
416 			diff = b->clock - a->clock;
417 			if (diff > 0) {
418 				c = *a;
419 				*a = *b;
420 				*b = c;
421 			}
422 		}
423 	}
424 	edid_data->preferred_mode = &edid_data->mode_buf[0];
425 }
426 
427 /**
428  * drm_mode_prune_invalid - remove invalid modes from mode list
429  * @edid_data: structure store mode list
430  * Returns:
431  * Number of valid modes.
432  */
433 int drm_mode_prune_invalid(struct hdmi_edid_data *edid_data)
434 {
435 	int i, j;
436 	int num = edid_data->modes;
437 	int len = sizeof(struct drm_display_mode);
438 	struct drm_display_mode *mode_buf = edid_data->mode_buf;
439 
440 	for (i = 0; i < num; i++) {
441 		if (mode_buf[i].invalid) {
442 			/* If mode is invalid, delete it. */
443 			for (j = i; j < num - 1; j++)
444 				memcpy(&mode_buf[j], &mode_buf[j + 1], len);
445 
446 			num--;
447 			i--;
448 		}
449 	}
450 	/* Clear redundant modes of mode_buf. */
451 	memset(&mode_buf[num], 0, len * (edid_data->modes - num));
452 
453 	edid_data->modes = num;
454 	return num;
455 }
456 
457 /**
458  * drm_rk_filter_whitelist - mark modes out of white list from mode list
459  * @edid_data: structure store mode list
460  */
461 void drm_rk_filter_whitelist(struct hdmi_edid_data *edid_data)
462 {
463 	int i, j, white_len;
464 
465 	if (sizeof(resolution_white)) {
466 		white_len = sizeof(resolution_white) /
467 			sizeof(resolution_white[0]);
468 		for (i = 0; i < edid_data->modes; i++) {
469 			for (j = 0; j < white_len; j++) {
470 				if (drm_mode_equal(&resolution_white[j],
471 						   &edid_data->mode_buf[i]))
472 					break;
473 			}
474 
475 			if (j == white_len)
476 				edid_data->mode_buf[i].invalid = true;
477 		}
478 	}
479 }
480 
481 void drm_rk_select_mode(struct hdmi_edid_data *edid_data,
482 			struct base_screen_info *screen_info)
483 {
484 	int i;
485 	const struct base_drm_display_mode *base_mode;
486 
487 	if (!screen_info) {
488 		/* define init resolution here */
489 	} else {
490 		base_mode = &screen_info->mode;
491 		for (i = 0; i < edid_data->modes; i++) {
492 			if (drm_mode_equal(base_mode,
493 					   &edid_data->mode_buf[i])) {
494 				edid_data->preferred_mode =
495 					&edid_data->mode_buf[i];
496 				break;
497 			}
498 		}
499 	}
500 }
501 
502 static unsigned int drm_rk_select_color(struct hdmi_edid_data *edid_data,
503 					struct base_screen_info *screen_info,
504 					enum dw_hdmi_devtype dev_type)
505 {
506 	struct drm_display_info *info = &edid_data->display_info;
507 	struct drm_display_mode *mode = edid_data->preferred_mode;
508 	int max_tmds_clock = info->max_tmds_clock;
509 	bool support_dc = false;
510 	bool mode_420 = drm_mode_is_420(info, mode);
511 	unsigned int color_depth = 8;
512 	unsigned int base_color = DRM_HDMI_OUTPUT_YCBCR444;
513 	unsigned int color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
514 	unsigned long tmdsclock, pixclock = mode->clock;
515 
516 	if (screen_info)
517 		base_color = screen_info->format;
518 
519 	switch (base_color) {
520 	case DRM_HDMI_OUTPUT_YCBCR_HQ:
521 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
522 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
523 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
524 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
525 		else if (mode_420)
526 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
527 		break;
528 	case DRM_HDMI_OUTPUT_YCBCR_LQ:
529 		if (mode_420)
530 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
531 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
532 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
533 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
534 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
535 		break;
536 	case DRM_HDMI_OUTPUT_YCBCR420:
537 		if (mode_420)
538 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
539 		break;
540 	case DRM_HDMI_OUTPUT_YCBCR422:
541 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
542 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
543 		break;
544 	case DRM_HDMI_OUTPUT_YCBCR444:
545 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
546 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
547 		break;
548 	case DRM_HDMI_OUTPUT_DEFAULT_RGB:
549 	default:
550 		break;
551 	}
552 
553 	if (color_format == DRM_HDMI_OUTPUT_DEFAULT_RGB &&
554 	    info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)
555 		support_dc = true;
556 	if (color_format == DRM_HDMI_OUTPUT_YCBCR444 &&
557 	    (info->edid_hdmi_dc_modes &
558 	     (DRM_EDID_HDMI_DC_Y444 | DRM_EDID_HDMI_DC_30)))
559 		support_dc = true;
560 	if (color_format == DRM_HDMI_OUTPUT_YCBCR422)
561 		support_dc = true;
562 	if (color_format == DRM_HDMI_OUTPUT_YCBCR420 &&
563 	    info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
564 		support_dc = true;
565 
566 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
567 		pixclock *= 2;
568 
569 	if (screen_info && screen_info->depth == 10)
570 		color_depth = screen_info->depth;
571 
572 	if (color_format == DRM_HDMI_OUTPUT_YCBCR422 || color_depth == 8)
573 		tmdsclock = pixclock;
574 	else
575 		tmdsclock = pixclock * color_depth / 8;
576 
577 	if (color_format == DRM_HDMI_OUTPUT_YCBCR420)
578 		tmdsclock /= 2;
579 
580 	if (!max_tmds_clock)
581 		max_tmds_clock = 340000;
582 
583 	switch (dev_type) {
584 	case RK3368_HDMI:
585 		max_tmds_clock = min(max_tmds_clock, 340000);
586 		break;
587 	case RK3328_HDMI:
588 	case RK3228_HDMI:
589 		max_tmds_clock = min(max_tmds_clock, 371250);
590 		break;
591 	default:
592 		max_tmds_clock = min(max_tmds_clock, 594000);
593 		break;
594 	}
595 
596 	if (tmdsclock > max_tmds_clock) {
597 		if (max_tmds_clock >= 594000) {
598 			color_depth = 8;
599 		} else if (max_tmds_clock > 340000) {
600 			if (drm_mode_is_420(info, mode))
601 				color_format = DRM_HDMI_OUTPUT_YCBCR420;
602 		} else {
603 			color_depth = 8;
604 			if (drm_mode_is_420(info, mode))
605 				color_format = DRM_HDMI_OUTPUT_YCBCR420;
606 		}
607 	}
608 
609 	if (color_depth > 8 && support_dc) {
610 		if (dev_type == RK3288_HDMI)
611 			return MEDIA_BUS_FMT_RGB101010_1X30;
612 		switch (color_format) {
613 		case DRM_HDMI_OUTPUT_YCBCR444:
614 			return MEDIA_BUS_FMT_YUV10_1X30;
615 		case DRM_HDMI_OUTPUT_YCBCR422:
616 			return MEDIA_BUS_FMT_UYVY10_1X20;
617 		case DRM_HDMI_OUTPUT_YCBCR420:
618 			return MEDIA_BUS_FMT_UYYVYY10_0_5X30;
619 		default:
620 			return MEDIA_BUS_FMT_RGB101010_1X30;
621 		}
622 	} else {
623 		if (dev_type == RK3288_HDMI)
624 			return MEDIA_BUS_FMT_RGB888_1X24;
625 		switch (color_format) {
626 		case DRM_HDMI_OUTPUT_YCBCR444:
627 			return MEDIA_BUS_FMT_YUV8_1X24;
628 		case DRM_HDMI_OUTPUT_YCBCR422:
629 			return MEDIA_BUS_FMT_UYVY8_1X16;
630 		case DRM_HDMI_OUTPUT_YCBCR420:
631 			return MEDIA_BUS_FMT_UYYVYY8_0_5X24;
632 		default:
633 			return MEDIA_BUS_FMT_RGB888_1X24;
634 		}
635 	}
636 }
637 
638 void drm_rk_selete_output(struct hdmi_edid_data *edid_data,
639 			  unsigned int *bus_format,
640 			  struct overscan *overscan,
641 			  enum dw_hdmi_devtype dev_type)
642 {
643 	int ret, i, screen_size;
644 	struct base_disp_info base_parameter;
645 	const struct base_overscan *scan;
646 	struct base_screen_info *screen_info = NULL;
647 	int max_scan = 100;
648 	int min_scan = 51;
649 	struct blk_desc *dev_desc;
650 	disk_partition_t part_info;
651 	char baseparameter_buf[8 * RK_BLK_SIZE] __aligned(ARCH_DMA_MINALIGN);
652 
653 	overscan->left_margin = max_scan;
654 	overscan->right_margin = max_scan;
655 	overscan->top_margin = max_scan;
656 	overscan->bottom_margin = max_scan;
657 
658 	if (dev_type == RK3288_HDMI)
659 		*bus_format = MEDIA_BUS_FMT_RGB888_1X24;
660 	else
661 		*bus_format = MEDIA_BUS_FMT_YUV8_1X24;
662 
663 	dev_desc = rockchip_get_bootdev();
664 	if (!dev_desc) {
665 		printf("%s: Could not find device\n", __func__);
666 		return;
667 	}
668 
669 	if (part_get_info_by_name(dev_desc, "baseparameter", &part_info) < 0) {
670 		printf("Could not find baseparameter partition\n");
671 		return;
672 	}
673 
674 	ret = blk_dread(dev_desc, part_info.start, 1,
675 			(void *)baseparameter_buf);
676 	if (ret < 0) {
677 		printf("read baseparameter failed\n");
678 		return;
679 	}
680 
681 	memcpy(&base_parameter, baseparameter_buf, sizeof(base_parameter));
682 	scan = &base_parameter.scan;
683 
684 	if (scan->leftscale < min_scan && scan->leftscale > 0)
685 		overscan->left_margin = min_scan;
686 	else if (scan->leftscale < max_scan && scan->leftscale > 0)
687 		overscan->left_margin = scan->leftscale;
688 
689 	if (scan->rightscale < min_scan && scan->rightscale > 0)
690 		overscan->right_margin = min_scan;
691 	else if (scan->rightscale < max_scan && scan->rightscale > 0)
692 		overscan->right_margin = scan->rightscale;
693 
694 	if (scan->topscale < min_scan && scan->topscale > 0)
695 		overscan->top_margin = min_scan;
696 	else if (scan->topscale < max_scan && scan->topscale > 0)
697 		overscan->top_margin = scan->topscale;
698 
699 	if (scan->bottomscale < min_scan && scan->bottomscale > 0)
700 		overscan->bottom_margin = min_scan;
701 	else if (scan->bottomscale < max_scan && scan->bottomscale > 0)
702 		overscan->bottom_margin = scan->bottomscale;
703 
704 	screen_size = sizeof(base_parameter.screen_list) /
705 		sizeof(base_parameter.screen_list[0]);
706 
707 	for (i = 0; i < screen_size; i++) {
708 		if (base_parameter.screen_list[i].type ==
709 		    DRM_MODE_CONNECTOR_HDMIA) {
710 			screen_info = &base_parameter.screen_list[i];
711 			break;
712 		}
713 	}
714 
715 	if (screen_info)
716 		printf("base_parameter.mode:%dx%d\n",
717 		       screen_info->mode.hdisplay,
718 		       screen_info->mode.vdisplay);
719 	drm_rk_select_mode(edid_data, screen_info);
720 
721 	*bus_format = drm_rk_select_color(edid_data, screen_info,
722 					  dev_type);
723 }
724 
725 void inno_dw_hdmi_set_domain(void *grf, int status)
726 {
727 	if (status)
728 		writel(RK3328_IO_5V_DOMAIN, grf + RK3328_GRF_SOC_CON4);
729 	else
730 		writel(RK3328_IO_3V_DOMAIN, grf + RK3328_GRF_SOC_CON4);
731 }
732 
733 void dw_hdmi_set_iomux(void *grf, int dev_type)
734 {
735 	switch (dev_type) {
736 	case RK3328_HDMI:
737 		writel(RK3328_IO_DDC_IN_MSK, grf + RK3328_GRF_SOC_CON2);
738 		writel(RK3328_IO_CTRL_BY_HDMI, grf + RK3328_GRF_SOC_CON3);
739 		break;
740 	case RK3228_HDMI:
741 		writel(RK3228_IO_3V_DOMAIN, grf + RK3228_GRF_SOC_CON6);
742 		writel(RK3228_IO_DDC_IN_MSK, grf + RK3228_GRF_SOC_CON2);
743 		break;
744 	default:
745 		break;
746 	}
747 }
748 
749 static const struct dw_hdmi_phy_ops inno_dw_hdmi_phy_ops = {
750 	.init = inno_dw_hdmi_phy_init,
751 	.disable = inno_dw_hdmi_phy_disable,
752 	.read_hpd = inno_dw_hdmi_phy_read_hpd,
753 	.mode_valid = inno_dw_hdmi_mode_valid,
754 };
755 
756 static const struct rockchip_connector_funcs rockchip_dw_hdmi_funcs = {
757 	.init = rockchip_dw_hdmi_init,
758 	.deinit = rockchip_dw_hdmi_deinit,
759 	.prepare = rockchip_dw_hdmi_prepare,
760 	.enable = rockchip_dw_hdmi_enable,
761 	.disable = rockchip_dw_hdmi_disable,
762 	.get_timing = rockchip_dw_hdmi_get_timing,
763 	.detect = rockchip_dw_hdmi_detect,
764 	.get_edid = rockchip_dw_hdmi_get_edid,
765 };
766 
767 const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = {
768 	.vop_sel_bit = 4,
769 	.grf_vop_sel_reg = RK3288_GRF_SOC_CON6,
770 	.mpll_cfg   = rockchip_mpll_cfg,
771 	.cur_ctr    = rockchip_cur_ctr,
772 	.phy_config = rockchip_phy_config,
773 	.dev_type   = RK3288_HDMI,
774 };
775 
776 const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = {
777 	.vop_sel_bit = 0,
778 	.grf_vop_sel_reg = 0,
779 	.phy_ops    = &inno_dw_hdmi_phy_ops,
780 	.phy_name   = "inno_dw_hdmi_phy2",
781 	.dev_type   = RK3328_HDMI,
782 };
783 
784 const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = {
785 	.vop_sel_bit = 0,
786 	.grf_vop_sel_reg = 0,
787 	.phy_ops    = &inno_dw_hdmi_phy_ops,
788 	.phy_name   = "inno_dw_hdmi_phy",
789 	.dev_type   = RK3228_HDMI,
790 };
791 
792 const struct dw_hdmi_plat_data rk3368_hdmi_drv_data = {
793 	.mpll_cfg   = rockchip_mpll_cfg,
794 	.cur_ctr    = rockchip_cur_ctr,
795 	.phy_config = rockchip_phy_config,
796 	.mpll_cfg_420 = rockchip_mpll_cfg_420,
797 	.dev_type   = RK3368_HDMI,
798 };
799 
800 const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
801 	.vop_sel_bit = 6,
802 	.grf_vop_sel_reg = RK3399_GRF_SOC_CON20,
803 	.mpll_cfg   = rockchip_mpll_cfg,
804 	.cur_ctr    = rockchip_cur_ctr,
805 	.phy_config = rockchip_phy_config,
806 	.mpll_cfg_420 = rockchip_mpll_cfg_420,
807 	.dev_type   = RK3399_HDMI,
808 };
809 
810 static int rockchip_dw_hdmi_probe(struct udevice *dev)
811 {
812 	return 0;
813 }
814 
815 static const struct rockchip_connector rk3399_dw_hdmi_data = {
816 	.funcs = &rockchip_dw_hdmi_funcs,
817 	.data = &rk3399_hdmi_drv_data,
818 };
819 
820 static const struct rockchip_connector rk3368_dw_hdmi_data = {
821 	.funcs = &rockchip_dw_hdmi_funcs,
822 	.data = &rk3368_hdmi_drv_data,
823 };
824 
825 static const struct rockchip_connector rk3288_dw_hdmi_data = {
826 	.funcs = &rockchip_dw_hdmi_funcs,
827 	.data = &rk3288_hdmi_drv_data,
828 };
829 
830 static const struct rockchip_connector rk3328_dw_hdmi_data = {
831 	.funcs = &rockchip_dw_hdmi_funcs,
832 	.data = &rk3328_hdmi_drv_data,
833 };
834 
835 static const struct rockchip_connector rk3228_dw_hdmi_data = {
836 	.funcs = &rockchip_dw_hdmi_funcs,
837 	.data = &rk3228_hdmi_drv_data,
838 };
839 
840 static const struct udevice_id rockchip_dw_hdmi_ids[] = {
841 	{
842 	 .compatible = "rockchip,rk3399-dw-hdmi",
843 	 .data = (ulong)&rk3399_dw_hdmi_data,
844 	}, {
845 	 .compatible = "rockchip,rk3368-dw-hdmi",
846 	 .data = (ulong)&rk3368_dw_hdmi_data,
847 	}, {
848 	 .compatible = "rockchip,rk3288-dw-hdmi",
849 	 .data = (ulong)&rk3288_dw_hdmi_data,
850 	}, {
851 	 .compatible = "rockchip,rk3328-dw-hdmi",
852 	 .data = (ulong)&rk3328_dw_hdmi_data,
853 	}, {
854 	 .compatible = "rockchip,rk3128-inno-hdmi",
855 	 .data = (ulong)&rk3228_dw_hdmi_data,
856 	}, {
857 	 .compatible = "rockchip,rk3228-dw-hdmi",
858 	 .data = (ulong)&rk3228_dw_hdmi_data,
859 	}, {}
860 };
861 
862 U_BOOT_DRIVER(rockchip_dw_hdmi) = {
863 	.name = "rockchip_dw_hdmi",
864 	.id = UCLASS_DISPLAY,
865 	.of_match = rockchip_dw_hdmi_ids,
866 	.probe	= rockchip_dw_hdmi_probe,
867 };
868