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 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 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 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 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 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 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