xref: /OK3568_Linux_fs/u-boot/drivers/video/drm/rockchip_dw_hdmi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 <asm/gpio.h>
11 #include <dm/of_access.h>
12 #include <dm/device.h>
13 #include <linux/dw_hdmi.h>
14 #include <linux/hdmi.h>
15 #include <linux/media-bus-format.h>
16 #include "rockchip_display.h"
17 #include "rockchip_crtc.h"
18 #include "rockchip_connector.h"
19 #include "dw_hdmi.h"
20 #include "rockchip_dw_hdmi.h"
21 
22 #define HDMI_SEL_LCDC(x, bit)  ((((x) & 1) << bit) | (1 << (16 + bit)))
23 #define RK3288_GRF_SOC_CON6		0x025C
24 #define RK3288_HDMI_LCDC_SEL		BIT(4)
25 #define RK3399_GRF_SOC_CON20		0x6250
26 #define RK3399_HDMI_LCDC_SEL		BIT(6)
27 
28 #define RK3228_IO_3V_DOMAIN              ((7 << 4) | (7 << (4 + 16)))
29 #define RK3328_IO_3V_DOMAIN              (7 << (9 + 16))
30 #define RK3328_IO_5V_DOMAIN              ((7 << 9) | (3 << (9 + 16)))
31 #define RK3328_IO_CTRL_BY_HDMI           ((1 << 13) | (1 << (13 + 16)))
32 #define RK3328_IO_DDC_IN_MSK             ((3 << 10) | (3 << (10 + 16)))
33 #define RK3228_IO_DDC_IN_MSK             ((3 << 13) | (3 << (13 + 16)))
34 #define RK3228_GRF_SOC_CON2              0x0408
35 #define RK3228_GRF_SOC_CON6              0x0418
36 #define RK3328_GRF_SOC_CON2              0x0408
37 #define RK3328_GRF_SOC_CON3              0x040c
38 #define RK3328_GRF_SOC_CON4              0x0410
39 
40 #define RK3528_GPIO0A_IOMUX_SEL_H	0x4
41 #define RK3528_GPIO0A_PULL 		0x200
42 #define RK3528_DDC_PULL			(0xf00 << 16)
43 #define RK3528_VO_GRF_HDMI_MASK		0x60014
44 #define RK3528_HDMI_SNKDET_SEL		((BIT(6) << 16) | BIT(6))
45 #define RK3528_HDMI_SNKDET		BIT(21)
46 #define RK3528_HDMI_CECIN_MSK		((BIT(2) << 16) | BIT(2))
47 #define RK3528_HDMI_SDAIN_MSK		((BIT(1) << 16) | BIT(1))
48 #define RK3528_HDMI_SCLIN_MSK		((BIT(0) << 16) | BIT(0))
49 
50 #define RK3528_GPIO_SWPORT_DR_L		0x0000
51 #define RK3528_GPIO0_A2_DR		((BIT(2) << 16) | BIT(2))
52 
53 #define RK3568_GRF_VO_CON1               0x0364
54 #define RK3568_HDMI_SDAIN_MSK            ((1 << 15) | (1 << (15 + 16)))
55 #define RK3568_HDMI_SCLIN_MSK            ((1 << 14) | (1 << (14 + 16)))
56 
57 static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = {
58 	{
59 		30666000, {
60 			{ 0x00b3, 0x0000 },
61 			{ 0x2153, 0x0000 },
62 			{ 0x40f3, 0x0000 },
63 		},
64 	},  {
65 		36800000, {
66 			{ 0x00b3, 0x0000 },
67 			{ 0x2153, 0x0000 },
68 			{ 0x40a2, 0x0001 },
69 		},
70 	},  {
71 		46000000, {
72 			{ 0x00b3, 0x0000 },
73 			{ 0x2142, 0x0001 },
74 			{ 0x40a2, 0x0001 },
75 		},
76 	},  {
77 		61333000, {
78 			{ 0x0072, 0x0001 },
79 			{ 0x2142, 0x0001 },
80 			{ 0x40a2, 0x0001 },
81 		},
82 	},  {
83 		73600000, {
84 			{ 0x0072, 0x0001 },
85 			{ 0x2142, 0x0001 },
86 			{ 0x4061, 0x0002 },
87 		},
88 	},  {
89 		92000000, {
90 			{ 0x0072, 0x0001 },
91 			{ 0x2145, 0x0002 },
92 			{ 0x4061, 0x0002 },
93 		},
94 	},  {
95 		122666000, {
96 			{ 0x0051, 0x0002 },
97 			{ 0x2145, 0x0002 },
98 			{ 0x4061, 0x0002 },
99 		},
100 	},  {
101 		147200000, {
102 			{ 0x0051, 0x0002 },
103 			{ 0x2145, 0x0002 },
104 			{ 0x4064, 0x0003 },
105 		},
106 	},  {
107 		184000000, {
108 			{ 0x0051, 0x0002 },
109 			{ 0x214c, 0x0003 },
110 			{ 0x4064, 0x0003 },
111 		},
112 	},  {
113 		226666000, {
114 			{ 0x0040, 0x0003 },
115 			{ 0x214c, 0x0003 },
116 			{ 0x4064, 0x0003 },
117 		},
118 	},  {
119 		272000000, {
120 			{ 0x0040, 0x0003 },
121 			{ 0x214c, 0x0003 },
122 			{ 0x5a64, 0x0003 },
123 		},
124 	},  {
125 		340000000, {
126 			{ 0x0040, 0x0003 },
127 			{ 0x3b4c, 0x0003 },
128 			{ 0x5a64, 0x0003 },
129 		},
130 	},  {
131 		600000000, {
132 			{ 0x1a40, 0x0003 },
133 			{ 0x3b4c, 0x0003 },
134 			{ 0x5a64, 0x0003 },
135 		},
136 	},  {
137 		~0UL, {
138 			{ 0x0000, 0x0000 },
139 			{ 0x0000, 0x0000 },
140 			{ 0x0000, 0x0000 },
141 		},
142 	}
143 };
144 
145 static const struct dw_hdmi_mpll_config rockchip_mpll_cfg_420[] = {
146 	{
147 		30666000, {
148 			{ 0x00b7, 0x0000 },
149 			{ 0x2157, 0x0000 },
150 			{ 0x40f7, 0x0000 },
151 		},
152 	},  {
153 		92000000, {
154 			{ 0x00b7, 0x0000 },
155 			{ 0x2143, 0x0001 },
156 			{ 0x40a3, 0x0001 },
157 		},
158 	},  {
159 		184000000, {
160 			{ 0x0073, 0x0001 },
161 			{ 0x2146, 0x0002 },
162 			{ 0x4062, 0x0002 },
163 		},
164 	},  {
165 		340000000, {
166 			{ 0x0052, 0x0003 },
167 			{ 0x214d, 0x0003 },
168 			{ 0x4065, 0x0003 },
169 		},
170 	},  {
171 		600000000, {
172 			{ 0x0041, 0x0003 },
173 			{ 0x3b4d, 0x0003 },
174 			{ 0x5a65, 0x0003 },
175 		},
176 	},  {
177 		~0UL, {
178 			{ 0x0000, 0x0000 },
179 			{ 0x0000, 0x0000 },
180 			{ 0x0000, 0x0000 },
181 		},
182 	}
183 };
184 
185 static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = {
186 	/*      pixelclk    bpp8    bpp10   bpp12 */
187 	{
188 		600000000, { 0x0000, 0x0000, 0x0000 },
189 	},  {
190 		~0UL,      { 0x0000, 0x0000, 0x0000},
191 	}
192 };
193 
194 static struct dw_hdmi_phy_config rockchip_phy_config[] = {
195 	/*pixelclk   symbol   term   vlev*/
196 	{ 74250000,  0x8009, 0x0004, 0x0272},
197 	{ 165000000, 0x802b, 0x0004, 0x0209},
198 	{ 297000000, 0x8039, 0x0005, 0x028d},
199 	{ 594000000, 0x8039, 0x0000, 0x019d},
200 	{ ~0UL,	     0x0000, 0x0000, 0x0000},
201 	{ ~0UL,	     0x0000, 0x0000, 0x0000}
202 };
203 
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)204 static unsigned int drm_rk_select_color(struct hdmi_edid_data *edid_data,
205 					struct base_screen_info *screen_info,
206 					enum dw_hdmi_devtype dev_type,
207 					bool output_bus_format_rgb)
208 {
209 	struct drm_display_info *info = &edid_data->display_info;
210 	struct drm_display_mode *mode = edid_data->preferred_mode;
211 	int max_tmds_clock = info->max_tmds_clock;
212 	bool support_dc = false;
213 	bool mode_420 = drm_mode_is_420(info, mode);
214 	unsigned int color_depth = 8;
215 	unsigned int base_color = DRM_HDMI_OUTPUT_YCBCR444;
216 	unsigned int color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
217 	unsigned long tmdsclock, pixclock = mode->clock;
218 
219 	if (screen_info)
220 		base_color = screen_info->format;
221 
222 	switch (base_color) {
223 	case DRM_HDMI_OUTPUT_YCBCR_HQ:
224 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
225 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
226 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
227 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
228 		else if (mode_420)
229 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
230 		break;
231 	case DRM_HDMI_OUTPUT_YCBCR_LQ:
232 		if (mode_420)
233 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
234 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
235 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
236 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
237 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
238 		break;
239 	case DRM_HDMI_OUTPUT_YCBCR420:
240 		if (mode_420)
241 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
242 		break;
243 	case DRM_HDMI_OUTPUT_YCBCR422:
244 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
245 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
246 		break;
247 	case DRM_HDMI_OUTPUT_YCBCR444:
248 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
249 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
250 		break;
251 	case DRM_HDMI_OUTPUT_DEFAULT_RGB:
252 	default:
253 		break;
254 	}
255 
256 	if (output_bus_format_rgb)
257 		color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
258 
259 	if (color_format == DRM_HDMI_OUTPUT_DEFAULT_RGB &&
260 	    info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)
261 		support_dc = true;
262 	if (color_format == DRM_HDMI_OUTPUT_YCBCR444 &&
263 	    (info->edid_hdmi_dc_modes &
264 	     (DRM_EDID_HDMI_DC_Y444 | DRM_EDID_HDMI_DC_30)))
265 		support_dc = true;
266 	if (color_format == DRM_HDMI_OUTPUT_YCBCR422)
267 		support_dc = true;
268 	if (color_format == DRM_HDMI_OUTPUT_YCBCR420 &&
269 	    info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
270 		support_dc = true;
271 
272 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
273 		pixclock *= 2;
274 
275 	if (screen_info && screen_info->depth == 10)
276 		color_depth = screen_info->depth;
277 
278 	if (color_format == DRM_HDMI_OUTPUT_YCBCR422 || color_depth == 8)
279 		tmdsclock = pixclock;
280 	else
281 		tmdsclock = pixclock * color_depth / 8;
282 
283 	if (color_format == DRM_HDMI_OUTPUT_YCBCR420)
284 		tmdsclock /= 2;
285 
286 	if (!max_tmds_clock)
287 		max_tmds_clock = 340000;
288 
289 	switch (dev_type) {
290 	case RK3368_HDMI:
291 		max_tmds_clock = min(max_tmds_clock, 340000);
292 		break;
293 	case RK3328_HDMI:
294 	case RK3228_HDMI:
295 		max_tmds_clock = min(max_tmds_clock, 371250);
296 		break;
297 	default:
298 		max_tmds_clock = min(max_tmds_clock, 594000);
299 		break;
300 	}
301 
302 	if (tmdsclock > max_tmds_clock) {
303 		if (max_tmds_clock >= 594000) {
304 			color_depth = 8;
305 		} else if (max_tmds_clock > 340000) {
306 			if (drm_mode_is_420(info, mode))
307 				color_format = DRM_HDMI_OUTPUT_YCBCR420;
308 		} else {
309 			color_depth = 8;
310 			if (drm_mode_is_420(info, mode))
311 				color_format = DRM_HDMI_OUTPUT_YCBCR420;
312 		}
313 	}
314 
315 	if (color_depth > 8 && support_dc) {
316 		if (dev_type == RK3288_HDMI)
317 			return MEDIA_BUS_FMT_RGB101010_1X30;
318 		switch (color_format) {
319 		case DRM_HDMI_OUTPUT_YCBCR444:
320 			return MEDIA_BUS_FMT_YUV10_1X30;
321 		case DRM_HDMI_OUTPUT_YCBCR422:
322 			return MEDIA_BUS_FMT_UYVY10_1X20;
323 		case DRM_HDMI_OUTPUT_YCBCR420:
324 			return MEDIA_BUS_FMT_UYYVYY10_0_5X30;
325 		default:
326 			return MEDIA_BUS_FMT_RGB101010_1X30;
327 		}
328 	} else {
329 		if (dev_type == RK3288_HDMI)
330 			return MEDIA_BUS_FMT_RGB888_1X24;
331 		switch (color_format) {
332 		case DRM_HDMI_OUTPUT_YCBCR444:
333 			return MEDIA_BUS_FMT_YUV8_1X24;
334 		case DRM_HDMI_OUTPUT_YCBCR422:
335 			return MEDIA_BUS_FMT_UYVY8_1X16;
336 		case DRM_HDMI_OUTPUT_YCBCR420:
337 			return MEDIA_BUS_FMT_UYYVYY8_0_5X24;
338 		default:
339 			return MEDIA_BUS_FMT_RGB888_1X24;
340 		}
341 	}
342 }
343 
drm_rk_selete_output(struct hdmi_edid_data * edid_data,struct connector_state * conn_state,unsigned int * bus_format,struct overscan * overscan,enum dw_hdmi_devtype dev_type,bool output_bus_format_rgb)344 void drm_rk_selete_output(struct hdmi_edid_data *edid_data,
345 			  struct connector_state *conn_state,
346 			  unsigned int *bus_format,
347 			  struct overscan *overscan,
348 			  enum dw_hdmi_devtype dev_type,
349 			  bool output_bus_format_rgb)
350 {
351 	struct base2_disp_info *base2_parameter = conn_state->disp_info;
352 	const struct base_overscan *scan;
353 	struct base_screen_info *screen_info = NULL;
354 	struct base2_screen_info *screen_info2 = NULL;
355 	int max_scan = 100;
356 	int min_scan = 51;
357 #ifdef CONFIG_SPL_BUILD
358 	int i, screen_size;
359 #else
360 	int ret, i, screen_size;
361 	int offset = 0;
362 	bool found = false;
363 	struct blk_desc *dev_desc;
364 	disk_partition_t part_info;
365 	char baseparameter_buf[8 * RK_BLK_SIZE] __aligned(ARCH_DMA_MINALIGN);
366 	struct base_disp_info base_parameter;
367 #endif
368 
369 	overscan->left_margin = max_scan;
370 	overscan->right_margin = max_scan;
371 	overscan->top_margin = max_scan;
372 	overscan->bottom_margin = max_scan;
373 
374 	if (dev_type == RK3288_HDMI || output_bus_format_rgb)
375 		*bus_format = MEDIA_BUS_FMT_RGB888_1X24;
376 	else
377 		*bus_format = MEDIA_BUS_FMT_YUV8_1X24;
378 
379 #ifdef CONFIG_SPL_BUILD
380 	scan = &base2_parameter->overscan_info;
381 	screen_size = sizeof(base2_parameter->screen_info) /
382 		sizeof(base2_parameter->screen_info[0]);
383 
384 	for (i = 0; i < screen_size; i++) {
385 		if (base2_parameter->screen_info[i].type ==
386 		    DRM_MODE_CONNECTOR_HDMIA) {
387 			screen_info2 =
388 				&base2_parameter->screen_info[i];
389 			break;
390 		}
391 	}
392 	screen_info = malloc(sizeof(*screen_info));
393 
394 	screen_info->type = screen_info2->type;
395 	screen_info->mode = screen_info2->resolution;
396 	screen_info->format = screen_info2->format;
397 	screen_info->depth = screen_info2->depthc;
398 	screen_info->feature = screen_info2->feature;
399 #else
400 	if (!base2_parameter) {
401 		dev_desc = rockchip_get_bootdev();
402 		if (!dev_desc) {
403 			printf("%s: Could not find device\n", __func__);
404 			goto null_basep;
405 		}
406 
407 		ret = part_get_info_by_name(dev_desc, "baseparameter",
408 					    &part_info);
409 		if (ret < 0) {
410 			printf("Could not find baseparameter partition\n");
411 			goto null_basep;
412 		}
413 
414 read_aux:
415 		ret = blk_dread(dev_desc, part_info.start + offset, 1,
416 				(void *)baseparameter_buf);
417 		if (ret < 0) {
418 			printf("read baseparameter failed\n");
419 			goto null_basep;
420 		}
421 
422 		memcpy(&base_parameter, baseparameter_buf,
423 		       sizeof(base_parameter));
424 		scan = &base_parameter.scan;
425 
426 		screen_size = sizeof(base_parameter.screen_list) /
427 			sizeof(base_parameter.screen_list[0]);
428 
429 		for (i = 0; i < screen_size; i++) {
430 			if (base_parameter.screen_list[i].type ==
431 			    DRM_MODE_CONNECTOR_HDMIA) {
432 				found = true;
433 				screen_info = &base_parameter.screen_list[i];
434 				break;
435 			}
436 		}
437 
438 		if (!found && !offset) {
439 			printf("hdmi info isn't saved in main block\n");
440 			offset += 16;
441 			goto read_aux;
442 		}
443 	} else {
444 		scan = &base2_parameter->overscan_info;
445 		screen_size = sizeof(base2_parameter->screen_info) /
446 			sizeof(base2_parameter->screen_info[0]);
447 
448 		for (i = 0; i < screen_size; i++) {
449 			if (base2_parameter->screen_info[i].type ==
450 			    DRM_MODE_CONNECTOR_HDMIA) {
451 				screen_info2 =
452 					&base2_parameter->screen_info[i];
453 				break;
454 			}
455 		}
456 		screen_info = malloc(sizeof(*screen_info));
457 
458 		screen_info->type = screen_info2->type;
459 		screen_info->mode = screen_info2->resolution;
460 		screen_info->format = screen_info2->format;
461 		screen_info->depth = screen_info2->depthc;
462 		screen_info->feature = screen_info2->feature;
463 	}
464 #endif
465 
466 	if (scan->leftscale < min_scan && scan->leftscale > 0)
467 		overscan->left_margin = min_scan;
468 	else if (scan->leftscale < max_scan && scan->leftscale > 0)
469 		overscan->left_margin = scan->leftscale;
470 
471 	if (scan->rightscale < min_scan && scan->rightscale > 0)
472 		overscan->right_margin = min_scan;
473 	else if (scan->rightscale < max_scan && scan->rightscale > 0)
474 		overscan->right_margin = scan->rightscale;
475 
476 	if (scan->topscale < min_scan && scan->topscale > 0)
477 		overscan->top_margin = min_scan;
478 	else if (scan->topscale < max_scan && scan->topscale > 0)
479 		overscan->top_margin = scan->topscale;
480 
481 	if (scan->bottomscale < min_scan && scan->bottomscale > 0)
482 		overscan->bottom_margin = min_scan;
483 	else if (scan->bottomscale < max_scan && scan->bottomscale > 0)
484 		overscan->bottom_margin = scan->bottomscale;
485 
486 #ifndef CONFIG_SPL_BUILD
487 null_basep:
488 #endif
489 
490 	if (screen_info)
491 		printf("base_parameter.mode:%dx%d\n",
492 		       screen_info->mode.hdisplay,
493 		       screen_info->mode.vdisplay);
494 	drm_rk_select_mode(edid_data, screen_info);
495 
496 	*bus_format = drm_rk_select_color(edid_data, screen_info,
497 					  dev_type, output_bus_format_rgb);
498 }
499 
inno_dw_hdmi_set_domain(void * grf,int status)500 void inno_dw_hdmi_set_domain(void *grf, int status)
501 {
502 	if (status)
503 		writel(RK3328_IO_5V_DOMAIN, grf + RK3328_GRF_SOC_CON4);
504 	else
505 		writel(RK3328_IO_3V_DOMAIN, grf + RK3328_GRF_SOC_CON4);
506 }
507 
dw_hdmi_set_iomux(void * grf,void * gpio_base,struct gpio_desc * hpd_gpiod,int dev_type)508 void dw_hdmi_set_iomux(void *grf, void *gpio_base, struct gpio_desc *hpd_gpiod,
509 		       int dev_type)
510 {
511 	u32 val = 0;
512 	int i = 400;
513 #ifdef CONFIG_SPL_BUILD
514 	void *gpio0_ioc = (void *)RK3528_GPIO0_IOC_BASE;
515 #endif
516 
517 	switch (dev_type) {
518 	case RK3328_HDMI:
519 		writel(RK3328_IO_DDC_IN_MSK, grf + RK3328_GRF_SOC_CON2);
520 		writel(RK3328_IO_CTRL_BY_HDMI, grf + RK3328_GRF_SOC_CON3);
521 		break;
522 	case RK3228_HDMI:
523 		writel(RK3228_IO_3V_DOMAIN, grf + RK3228_GRF_SOC_CON6);
524 		writel(RK3228_IO_DDC_IN_MSK, grf + RK3228_GRF_SOC_CON2);
525 		break;
526 	case RK3528_HDMI:
527 		writel(RK3528_HDMI_SDAIN_MSK | RK3528_HDMI_SCLIN_MSK |
528 		       RK3528_HDMI_SNKDET_SEL,
529 		       grf + RK3528_VO_GRF_HDMI_MASK);
530 
531 #ifdef CONFIG_SPL_BUILD
532 		val = (0x11 << 16) | 0x11;
533 		writel(val, gpio0_ioc + RK3528_GPIO0A_IOMUX_SEL_H);
534 
535 		writel(RK3528_DDC_PULL, gpio0_ioc + RK3528_GPIO0A_PULL);
536 
537 		/* gpio0_a2's input enable is controlled by gpio output data bit */
538 		writel(RK3528_GPIO0_A2_DR, gpio_base + RK3528_GPIO_SWPORT_DR_L);
539 
540 		while (i--) {
541 			val = readl(gpio_base + 0x70) & BIT(2);
542 			if (val)
543 				break;
544 			mdelay(5);
545 		}
546 #else
547 		writel(val, grf + RK3528_VO_GRF_HDMI_MASK);
548 
549 		/* gpio0_a2's input enable is controlled by gpio output data bit */
550 		writel(RK3528_GPIO0_A2_DR, gpio_base + RK3528_GPIO_SWPORT_DR_L);
551 
552 		if (dm_gpio_is_valid(hpd_gpiod)) {
553 			while (i--) {
554 				val = dm_gpio_get_value(hpd_gpiod);
555 				if (val)
556 					break;
557 				mdelay(5);
558 			}
559 		}
560 #endif
561 
562 		if (val)
563 			val = RK3528_HDMI_SNKDET | BIT(5);
564 		else
565 			val = RK3528_HDMI_SNKDET;
566 		writel(val, grf + RK3528_VO_GRF_HDMI_MASK);
567 
568 		break;
569 	case RK3568_HDMI:
570 		writel(RK3568_HDMI_SDAIN_MSK | RK3568_HDMI_SCLIN_MSK,
571 		       grf + RK3568_GRF_VO_CON1);
572 		break;
573 	default:
574 		break;
575 	}
576 }
577 
578 static const struct dw_hdmi_phy_ops inno_dw_hdmi_phy_ops = {
579 	.init = inno_dw_hdmi_phy_init,
580 	.disable = inno_dw_hdmi_phy_disable,
581 	.read_hpd = inno_dw_hdmi_phy_read_hpd,
582 	.mode_valid = inno_dw_hdmi_mode_valid,
583 };
584 
585 static const struct rockchip_connector_funcs rockchip_dw_hdmi_funcs = {
586 	.init = rockchip_dw_hdmi_init,
587 	.deinit = rockchip_dw_hdmi_deinit,
588 	.prepare = rockchip_dw_hdmi_prepare,
589 	.enable = rockchip_dw_hdmi_enable,
590 	.disable = rockchip_dw_hdmi_disable,
591 	.get_timing = rockchip_dw_hdmi_get_timing,
592 	.detect = rockchip_dw_hdmi_detect,
593 	.get_edid = rockchip_dw_hdmi_get_edid,
594 };
595 
596 const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = {
597 	.vop_sel_bit = 4,
598 	.grf_vop_sel_reg = RK3288_GRF_SOC_CON6,
599 	.mpll_cfg   = rockchip_mpll_cfg,
600 	.cur_ctr    = rockchip_cur_ctr,
601 	.phy_config = rockchip_phy_config,
602 	.dev_type   = RK3288_HDMI,
603 };
604 
605 const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = {
606 	.vop_sel_bit = 0,
607 	.grf_vop_sel_reg = 0,
608 	.phy_ops    = &inno_dw_hdmi_phy_ops,
609 	.phy_name   = "inno_dw_hdmi_phy2",
610 	.dev_type   = RK3328_HDMI,
611 };
612 
613 const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = {
614 	.vop_sel_bit = 0,
615 	.grf_vop_sel_reg = 0,
616 	.phy_ops    = &inno_dw_hdmi_phy_ops,
617 	.phy_name   = "inno_dw_hdmi_phy",
618 	.dev_type   = RK3228_HDMI,
619 };
620 
621 const struct dw_hdmi_plat_data rk3368_hdmi_drv_data = {
622 	.mpll_cfg   = rockchip_mpll_cfg,
623 	.cur_ctr    = rockchip_cur_ctr,
624 	.phy_config = rockchip_phy_config,
625 	.mpll_cfg_420 = rockchip_mpll_cfg_420,
626 	.dev_type   = RK3368_HDMI,
627 };
628 
629 const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
630 	.vop_sel_bit = 6,
631 	.grf_vop_sel_reg = RK3399_GRF_SOC_CON20,
632 	.mpll_cfg   = rockchip_mpll_cfg,
633 	.cur_ctr    = rockchip_cur_ctr,
634 	.phy_config = rockchip_phy_config,
635 	.mpll_cfg_420 = rockchip_mpll_cfg_420,
636 	.dev_type   = RK3399_HDMI,
637 };
638 
639 const struct dw_hdmi_plat_data rk3528_hdmi_drv_data = {
640 	.vop_sel_bit = 0,
641 	.grf_vop_sel_reg = 0,
642 	.phy_ops    = &inno_dw_hdmi_phy_ops,
643 	.phy_name   = "inno_dw_hdmi_phy2",
644 	.dev_type   = RK3528_HDMI,
645 };
646 
647 const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = {
648 	.vop_sel_bit = 0,
649 	.grf_vop_sel_reg = 0,
650 	.mpll_cfg   = rockchip_mpll_cfg,
651 	.cur_ctr    = rockchip_cur_ctr,
652 	.phy_config = rockchip_phy_config,
653 	.mpll_cfg_420 = rockchip_mpll_cfg_420,
654 	.dev_type   = RK3568_HDMI,
655 };
656 
657 #ifdef CONFIG_SPL_BUILD
rockchip_spl_dw_hdmi_probe(struct connector_state * conn_state)658 int rockchip_spl_dw_hdmi_probe(struct connector_state *conn_state)
659 {
660 	conn_state->connector = malloc(sizeof(struct rockchip_connector));
661 
662 	memset(conn_state->connector, 0, sizeof(*conn_state->connector));
663 	rockchip_connector_bind(conn_state->connector, NULL, 0, &rockchip_dw_hdmi_funcs,
664 				(void *)&rk3528_hdmi_drv_data,
665 				DRM_MODE_CONNECTOR_HDMIA);
666 
667 	return 0;
668 }
669 #else
rockchip_dw_hdmi_probe(struct udevice * dev)670 static int rockchip_dw_hdmi_probe(struct udevice *dev)
671 {
672 	int id;
673 	struct rockchip_connector *conn = dev_get_priv(dev);
674 
675 	id = of_alias_get_id(ofnode_to_np(dev->node), "hdmi");
676 	if (id < 0)
677 		id = 0;
678 
679 	rockchip_connector_bind(conn, dev, id, &rockchip_dw_hdmi_funcs, NULL,
680 				DRM_MODE_CONNECTOR_HDMIA);
681 
682 	return 0;
683 }
684 #endif
685 
686 static const struct udevice_id rockchip_dw_hdmi_ids[] = {
687 	{
688 	 .compatible = "rockchip,rk3528-dw-hdmi",
689 	 .data = (ulong)&rk3528_hdmi_drv_data,
690 	}, {
691 	 .compatible = "rockchip,rk3568-dw-hdmi",
692 	 .data = (ulong)&rk3568_hdmi_drv_data,
693 	}, {
694 	 .compatible = "rockchip,rk3399-dw-hdmi",
695 	 .data = (ulong)&rk3399_hdmi_drv_data,
696 	}, {
697 	 .compatible = "rockchip,rk3368-dw-hdmi",
698 	 .data = (ulong)&rk3368_hdmi_drv_data,
699 	}, {
700 	 .compatible = "rockchip,rk3288-dw-hdmi",
701 	 .data = (ulong)&rk3288_hdmi_drv_data,
702 	}, {
703 	 .compatible = "rockchip,rk3328-dw-hdmi",
704 	 .data = (ulong)&rk3328_hdmi_drv_data,
705 	}, {
706 	 .compatible = "rockchip,rk3128-inno-hdmi",
707 	 .data = (ulong)&rk3228_hdmi_drv_data,
708 	}, {
709 	 .compatible = "rockchip,rk3228-dw-hdmi",
710 	 .data = (ulong)&rk3228_hdmi_drv_data,
711 	}, {}
712 };
713 
714 U_BOOT_DRIVER(rockchip_dw_hdmi) = {
715 	.name = "rockchip_dw_hdmi",
716 	.id = UCLASS_DISPLAY,
717 	.of_match = rockchip_dw_hdmi_ids,
718 #ifndef CONFIG_SPL_BUILD
719 	.probe	= rockchip_dw_hdmi_probe,
720 #endif
721 	.priv_auto_alloc_size = sizeof(struct rockchip_connector),
722 };
723