| .. | .. |
|---|
| 23 | 23 | * |
|---|
| 24 | 24 | */ |
|---|
| 25 | 25 | |
|---|
| 26 | +#include <linux/delay.h> |
|---|
| 27 | +#include <linux/slab.h> |
|---|
| 28 | + |
|---|
| 26 | 29 | #include "reg_helper.h" |
|---|
| 27 | 30 | |
|---|
| 28 | 31 | #include "core_types.h" |
|---|
| .. | .. |
|---|
| 85 | 88 | .enable_hpd = dcn10_link_encoder_enable_hpd, |
|---|
| 86 | 89 | .disable_hpd = dcn10_link_encoder_disable_hpd, |
|---|
| 87 | 90 | .is_dig_enabled = dcn10_is_dig_enabled, |
|---|
| 88 | | - .destroy = dcn10_link_encoder_destroy |
|---|
| 91 | + .get_dig_frontend = dcn10_get_dig_frontend, |
|---|
| 92 | + .get_dig_mode = dcn10_get_dig_mode, |
|---|
| 93 | + .destroy = dcn10_link_encoder_destroy, |
|---|
| 94 | + .get_max_link_cap = dcn10_link_encoder_get_max_link_cap, |
|---|
| 89 | 95 | }; |
|---|
| 90 | 96 | |
|---|
| 91 | 97 | static enum bp_result link_transmitter_control( |
|---|
| .. | .. |
|---|
| 228 | 234 | { |
|---|
| 229 | 235 | uint32_t value; |
|---|
| 230 | 236 | |
|---|
| 231 | | - ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); |
|---|
| 237 | + if (!REG(DP_DPHY_INTERNAL_CTRL)) |
|---|
| 238 | + return; |
|---|
| 239 | + |
|---|
| 232 | 240 | value = REG_READ(DP_DPHY_INTERNAL_CTRL); |
|---|
| 233 | 241 | |
|---|
| 234 | 242 | switch (panel_mode) { |
|---|
| .. | .. |
|---|
| 440 | 448 | } |
|---|
| 441 | 449 | } |
|---|
| 442 | 450 | |
|---|
| 443 | | -void configure_encoder( |
|---|
| 451 | +unsigned int dcn10_get_dig_frontend(struct link_encoder *enc) |
|---|
| 452 | +{ |
|---|
| 453 | + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); |
|---|
| 454 | + int32_t value; |
|---|
| 455 | + enum engine_id result; |
|---|
| 456 | + |
|---|
| 457 | + REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value); |
|---|
| 458 | + |
|---|
| 459 | + switch (value) { |
|---|
| 460 | + case DCN10_DIG_FE_SOURCE_SELECT_DIGA: |
|---|
| 461 | + result = ENGINE_ID_DIGA; |
|---|
| 462 | + break; |
|---|
| 463 | + case DCN10_DIG_FE_SOURCE_SELECT_DIGB: |
|---|
| 464 | + result = ENGINE_ID_DIGB; |
|---|
| 465 | + break; |
|---|
| 466 | + case DCN10_DIG_FE_SOURCE_SELECT_DIGC: |
|---|
| 467 | + result = ENGINE_ID_DIGC; |
|---|
| 468 | + break; |
|---|
| 469 | + case DCN10_DIG_FE_SOURCE_SELECT_DIGD: |
|---|
| 470 | + result = ENGINE_ID_DIGD; |
|---|
| 471 | + break; |
|---|
| 472 | + case DCN10_DIG_FE_SOURCE_SELECT_DIGE: |
|---|
| 473 | + result = ENGINE_ID_DIGE; |
|---|
| 474 | + break; |
|---|
| 475 | + case DCN10_DIG_FE_SOURCE_SELECT_DIGF: |
|---|
| 476 | + result = ENGINE_ID_DIGF; |
|---|
| 477 | + break; |
|---|
| 478 | + case DCN10_DIG_FE_SOURCE_SELECT_DIGG: |
|---|
| 479 | + result = ENGINE_ID_DIGG; |
|---|
| 480 | + break; |
|---|
| 481 | + default: |
|---|
| 482 | + // invalid source select DIG |
|---|
| 483 | + result = ENGINE_ID_UNKNOWN; |
|---|
| 484 | + } |
|---|
| 485 | + |
|---|
| 486 | + return result; |
|---|
| 487 | + |
|---|
| 488 | +} |
|---|
| 489 | + |
|---|
| 490 | +void enc1_configure_encoder( |
|---|
| 444 | 491 | struct dcn10_link_encoder *enc10, |
|---|
| 445 | 492 | const struct dc_link_settings *link_settings) |
|---|
| 446 | 493 | { |
|---|
| .. | .. |
|---|
| 543 | 590 | if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || |
|---|
| 544 | 591 | connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) && |
|---|
| 545 | 592 | signal != SIGNAL_TYPE_HDMI_TYPE_A && |
|---|
| 546 | | - crtc_timing->pix_clk_khz > TMDS_MAX_PIXEL_CLOCK) |
|---|
| 593 | + crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10)) |
|---|
| 547 | 594 | return false; |
|---|
| 548 | | - if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) |
|---|
| 595 | + if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) |
|---|
| 549 | 596 | return false; |
|---|
| 550 | 597 | |
|---|
| 551 | | - if (crtc_timing->pix_clk_khz > max_pixel_clock) |
|---|
| 598 | + if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10)) |
|---|
| 552 | 599 | return false; |
|---|
| 553 | 600 | |
|---|
| 554 | 601 | /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */ |
|---|
| .. | .. |
|---|
| 571 | 618 | static bool dcn10_link_encoder_validate_hdmi_output( |
|---|
| 572 | 619 | const struct dcn10_link_encoder *enc10, |
|---|
| 573 | 620 | const struct dc_crtc_timing *crtc_timing, |
|---|
| 574 | | - int adjusted_pix_clk_khz) |
|---|
| 621 | + const struct dc_edid_caps *edid_caps, |
|---|
| 622 | + int adjusted_pix_clk_100hz) |
|---|
| 575 | 623 | { |
|---|
| 576 | 624 | enum dc_color_depth max_deep_color = |
|---|
| 577 | 625 | enc10->base.features.max_hdmi_deep_color; |
|---|
| 626 | + |
|---|
| 627 | + // check pixel clock against edid specified max TMDS clk |
|---|
| 628 | + if (edid_caps->max_tmds_clk_mhz != 0 && |
|---|
| 629 | + adjusted_pix_clk_100hz > edid_caps->max_tmds_clk_mhz * 10000) |
|---|
| 630 | + return false; |
|---|
| 578 | 631 | |
|---|
| 579 | 632 | if (max_deep_color < crtc_timing->display_color_depth) |
|---|
| 580 | 633 | return false; |
|---|
| 581 | 634 | |
|---|
| 582 | 635 | if (crtc_timing->display_color_depth < COLOR_DEPTH_888) |
|---|
| 583 | 636 | return false; |
|---|
| 584 | | - if (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) |
|---|
| 637 | + if (adjusted_pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) |
|---|
| 585 | 638 | return false; |
|---|
| 586 | 639 | |
|---|
| 587 | | - if ((adjusted_pix_clk_khz == 0) || |
|---|
| 588 | | - (adjusted_pix_clk_khz > enc10->base.features.max_hdmi_pixel_clock)) |
|---|
| 640 | + if ((adjusted_pix_clk_100hz == 0) || |
|---|
| 641 | + (adjusted_pix_clk_100hz > (enc10->base.features.max_hdmi_pixel_clock * 10))) |
|---|
| 589 | 642 | return false; |
|---|
| 590 | 643 | |
|---|
| 591 | 644 | /* DCE11 HW does not support 420 */ |
|---|
| 592 | | - if (!enc10->base.features.ycbcr420_supported && |
|---|
| 645 | + if (!enc10->base.features.hdmi_ycbcr420_supported && |
|---|
| 593 | 646 | crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) |
|---|
| 594 | 647 | return false; |
|---|
| 595 | 648 | |
|---|
| 596 | 649 | if (!enc10->base.features.flags.bits.HDMI_6GB_EN && |
|---|
| 597 | | - adjusted_pix_clk_khz >= 300000) |
|---|
| 650 | + adjusted_pix_clk_100hz >= 3000000) |
|---|
| 598 | 651 | return false; |
|---|
| 599 | 652 | if (enc10->base.ctx->dc->debug.hdmi20_disable && |
|---|
| 600 | 653 | crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) |
|---|
| .. | .. |
|---|
| 606 | 659 | const struct dcn10_link_encoder *enc10, |
|---|
| 607 | 660 | const struct dc_crtc_timing *crtc_timing) |
|---|
| 608 | 661 | { |
|---|
| 609 | | - /* default RGB only */ |
|---|
| 610 | | - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) |
|---|
| 611 | | - return true; |
|---|
| 662 | + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) { |
|---|
| 663 | + if (!enc10->base.features.dp_ycbcr420_supported) |
|---|
| 664 | + return false; |
|---|
| 665 | + } |
|---|
| 612 | 666 | |
|---|
| 613 | | - if (enc10->base.features.flags.bits.IS_YCBCR_CAPABLE) |
|---|
| 614 | | - return true; |
|---|
| 615 | | - |
|---|
| 616 | | - /* for DCE 8.x or later DP Y-only feature, |
|---|
| 617 | | - * we need ASIC cap + FeatureSupportDPYonly, not support 666 |
|---|
| 618 | | - */ |
|---|
| 619 | | - if (crtc_timing->flags.Y_ONLY && |
|---|
| 620 | | - enc10->base.features.flags.bits.IS_YCBCR_CAPABLE && |
|---|
| 621 | | - crtc_timing->display_color_depth != COLOR_DEPTH_666) |
|---|
| 622 | | - return true; |
|---|
| 623 | | - |
|---|
| 624 | | - return false; |
|---|
| 667 | + return true; |
|---|
| 625 | 668 | } |
|---|
| 626 | 669 | |
|---|
| 627 | 670 | void dcn10_link_encoder_construct( |
|---|
| .. | .. |
|---|
| 726 | 769 | enc10->base.features.flags.bits.IS_HBR3_CAPABLE = |
|---|
| 727 | 770 | bp_cap_info.DP_HBR3_EN; |
|---|
| 728 | 771 | enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; |
|---|
| 772 | + enc10->base.features.flags.bits.DP_IS_USB_C = |
|---|
| 773 | + bp_cap_info.DP_IS_USB_C; |
|---|
| 729 | 774 | } else { |
|---|
| 730 | 775 | DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", |
|---|
| 731 | 776 | __func__, |
|---|
| .. | .. |
|---|
| 743 | 788 | struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); |
|---|
| 744 | 789 | bool is_valid; |
|---|
| 745 | 790 | |
|---|
| 791 | + //if SCDC (340-600MHz) is disabled, set to HDMI 1.4 timing limit |
|---|
| 792 | + if (stream->sink->edid_caps.panel_patch.skip_scdc_overwrite && |
|---|
| 793 | + enc10->base.features.max_hdmi_pixel_clock > 300000) |
|---|
| 794 | + enc10->base.features.max_hdmi_pixel_clock = 300000; |
|---|
| 795 | + |
|---|
| 746 | 796 | switch (stream->signal) { |
|---|
| 747 | 797 | case SIGNAL_TYPE_DVI_SINGLE_LINK: |
|---|
| 748 | 798 | case SIGNAL_TYPE_DVI_DUAL_LINK: |
|---|
| 749 | 799 | is_valid = dcn10_link_encoder_validate_dvi_output( |
|---|
| 750 | 800 | enc10, |
|---|
| 751 | | - stream->sink->link->connector_signal, |
|---|
| 801 | + stream->link->connector_signal, |
|---|
| 752 | 802 | stream->signal, |
|---|
| 753 | 803 | &stream->timing); |
|---|
| 754 | 804 | break; |
|---|
| .. | .. |
|---|
| 756 | 806 | is_valid = dcn10_link_encoder_validate_hdmi_output( |
|---|
| 757 | 807 | enc10, |
|---|
| 758 | 808 | &stream->timing, |
|---|
| 759 | | - stream->phy_pix_clk); |
|---|
| 809 | + &stream->sink->edid_caps, |
|---|
| 810 | + stream->phy_pix_clk * 10); |
|---|
| 760 | 811 | break; |
|---|
| 761 | 812 | case SIGNAL_TYPE_DISPLAY_PORT: |
|---|
| 762 | 813 | case SIGNAL_TYPE_DISPLAY_PORT_MST: |
|---|
| .. | .. |
|---|
| 920 | 971 | * but it's not passed to asic_control. |
|---|
| 921 | 972 | * We need to set number of lanes manually. |
|---|
| 922 | 973 | */ |
|---|
| 923 | | - configure_encoder(enc10, link_settings); |
|---|
| 974 | + enc1_configure_encoder(enc10, link_settings); |
|---|
| 924 | 975 | |
|---|
| 925 | 976 | cntl.action = TRANSMITTER_CONTROL_ENABLE; |
|---|
| 926 | 977 | cntl.engine_id = enc->preferred_engine; |
|---|
| .. | .. |
|---|
| 959 | 1010 | * but it's not passed to asic_control. |
|---|
| 960 | 1011 | * We need to set number of lanes manually. |
|---|
| 961 | 1012 | */ |
|---|
| 962 | | - configure_encoder(enc10, link_settings); |
|---|
| 1013 | + enc1_configure_encoder(enc10, link_settings); |
|---|
| 963 | 1014 | |
|---|
| 964 | 1015 | cntl.action = TRANSMITTER_CONTROL_ENABLE; |
|---|
| 965 | 1016 | cntl.engine_id = ENGINE_ID_UNKNOWN; |
|---|
| .. | .. |
|---|
| 1304 | 1355 | #define HPD_REG_UPDATE_N(reg_name, n, ...) \ |
|---|
| 1305 | 1356 | generic_reg_update_ex(CTX, \ |
|---|
| 1306 | 1357 | HPD_REG(reg_name), \ |
|---|
| 1307 | | - HPD_REG_READ(reg_name), \ |
|---|
| 1308 | 1358 | n, __VA_ARGS__) |
|---|
| 1309 | 1359 | |
|---|
| 1310 | 1360 | #define HPD_REG_UPDATE(reg_name, field, val) \ |
|---|
| .. | .. |
|---|
| 1327 | 1377 | DC_HPD_EN, 0); |
|---|
| 1328 | 1378 | } |
|---|
| 1329 | 1379 | |
|---|
| 1330 | | - |
|---|
| 1331 | 1380 | #define AUX_REG(reg)\ |
|---|
| 1332 | 1381 | (enc10->aux_regs->reg) |
|---|
| 1333 | 1382 | |
|---|
| .. | .. |
|---|
| 1337 | 1386 | #define AUX_REG_UPDATE_N(reg_name, n, ...) \ |
|---|
| 1338 | 1387 | generic_reg_update_ex(CTX, \ |
|---|
| 1339 | 1388 | AUX_REG(reg_name), \ |
|---|
| 1340 | | - AUX_REG_READ(reg_name), \ |
|---|
| 1341 | 1389 | n, __VA_ARGS__) |
|---|
| 1342 | 1390 | |
|---|
| 1343 | 1391 | #define AUX_REG_UPDATE(reg_name, field, val) \ |
|---|
| .. | .. |
|---|
| 1359 | 1407 | |
|---|
| 1360 | 1408 | /* 1/4 window (the maximum allowed) */ |
|---|
| 1361 | 1409 | AUX_REG_UPDATE(AUX_DPHY_RX_CONTROL0, |
|---|
| 1362 | | - AUX_RX_RECEIVE_WINDOW, 1); |
|---|
| 1410 | + AUX_RX_RECEIVE_WINDOW, 0); |
|---|
| 1411 | +} |
|---|
| 1412 | + |
|---|
| 1413 | +enum signal_type dcn10_get_dig_mode( |
|---|
| 1414 | + struct link_encoder *enc) |
|---|
| 1415 | +{ |
|---|
| 1416 | + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); |
|---|
| 1417 | + uint32_t value; |
|---|
| 1418 | + REG_GET(DIG_BE_CNTL, DIG_MODE, &value); |
|---|
| 1419 | + switch (value) { |
|---|
| 1420 | + case 1: |
|---|
| 1421 | + return SIGNAL_TYPE_DISPLAY_PORT; |
|---|
| 1422 | + case 2: |
|---|
| 1423 | + return SIGNAL_TYPE_DVI_SINGLE_LINK; |
|---|
| 1424 | + case 3: |
|---|
| 1425 | + return SIGNAL_TYPE_HDMI_TYPE_A; |
|---|
| 1426 | + case 5: |
|---|
| 1427 | + return SIGNAL_TYPE_DISPLAY_PORT_MST; |
|---|
| 1428 | + default: |
|---|
| 1429 | + return SIGNAL_TYPE_NONE; |
|---|
| 1430 | + } |
|---|
| 1431 | + return SIGNAL_TYPE_NONE; |
|---|
| 1432 | +} |
|---|
| 1433 | + |
|---|
| 1434 | +void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc, |
|---|
| 1435 | + struct dc_link_settings *link_settings) |
|---|
| 1436 | +{ |
|---|
| 1437 | + /* Set Default link settings */ |
|---|
| 1438 | + struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH, |
|---|
| 1439 | + LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0}; |
|---|
| 1440 | + |
|---|
| 1441 | + /* Higher link settings based on feature supported */ |
|---|
| 1442 | + if (enc->features.flags.bits.IS_HBR2_CAPABLE) |
|---|
| 1443 | + max_link_cap.link_rate = LINK_RATE_HIGH2; |
|---|
| 1444 | + |
|---|
| 1445 | + if (enc->features.flags.bits.IS_HBR3_CAPABLE) |
|---|
| 1446 | + max_link_cap.link_rate = LINK_RATE_HIGH3; |
|---|
| 1447 | + |
|---|
| 1448 | + *link_settings = max_link_cap; |
|---|
| 1363 | 1449 | } |
|---|