.. | .. |
---|
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" |
---|
.. | .. |
---|
102 | 105 | .enable_tmds_output = dce110_link_encoder_enable_tmds_output, |
---|
103 | 106 | .enable_dp_output = dce110_link_encoder_enable_dp_output, |
---|
104 | 107 | .enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output, |
---|
| 108 | + .enable_lvds_output = dce110_link_encoder_enable_lvds_output, |
---|
105 | 109 | .disable_output = dce110_link_encoder_disable_output, |
---|
106 | 110 | .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings, |
---|
107 | 111 | .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern, |
---|
.. | .. |
---|
114 | 118 | .enable_hpd = dce110_link_encoder_enable_hpd, |
---|
115 | 119 | .disable_hpd = dce110_link_encoder_disable_hpd, |
---|
116 | 120 | .is_dig_enabled = dce110_is_dig_enabled, |
---|
117 | | - .destroy = dce110_link_encoder_destroy |
---|
| 121 | + .destroy = dce110_link_encoder_destroy, |
---|
| 122 | + .get_max_link_cap = dce110_link_encoder_get_max_link_cap, |
---|
| 123 | + .get_dig_frontend = dce110_get_dig_frontend, |
---|
118 | 124 | }; |
---|
119 | 125 | |
---|
120 | 126 | static enum bp_result link_transmitter_control( |
---|
.. | .. |
---|
228 | 234 | |
---|
229 | 235 | REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete); |
---|
230 | 236 | |
---|
| 237 | +} |
---|
| 238 | + |
---|
| 239 | +unsigned int dce110_get_dig_frontend(struct link_encoder *enc) |
---|
| 240 | +{ |
---|
| 241 | + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); |
---|
| 242 | + u32 value; |
---|
| 243 | + enum engine_id result; |
---|
| 244 | + |
---|
| 245 | + REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value); |
---|
| 246 | + |
---|
| 247 | + switch (value) { |
---|
| 248 | + case DCE110_DIG_FE_SOURCE_SELECT_DIGA: |
---|
| 249 | + result = ENGINE_ID_DIGA; |
---|
| 250 | + break; |
---|
| 251 | + case DCE110_DIG_FE_SOURCE_SELECT_DIGB: |
---|
| 252 | + result = ENGINE_ID_DIGB; |
---|
| 253 | + break; |
---|
| 254 | + case DCE110_DIG_FE_SOURCE_SELECT_DIGC: |
---|
| 255 | + result = ENGINE_ID_DIGC; |
---|
| 256 | + break; |
---|
| 257 | + case DCE110_DIG_FE_SOURCE_SELECT_DIGD: |
---|
| 258 | + result = ENGINE_ID_DIGD; |
---|
| 259 | + break; |
---|
| 260 | + case DCE110_DIG_FE_SOURCE_SELECT_DIGE: |
---|
| 261 | + result = ENGINE_ID_DIGE; |
---|
| 262 | + break; |
---|
| 263 | + case DCE110_DIG_FE_SOURCE_SELECT_DIGF: |
---|
| 264 | + result = ENGINE_ID_DIGF; |
---|
| 265 | + break; |
---|
| 266 | + case DCE110_DIG_FE_SOURCE_SELECT_DIGG: |
---|
| 267 | + result = ENGINE_ID_DIGG; |
---|
| 268 | + break; |
---|
| 269 | + default: |
---|
| 270 | + // invalid source select DIG |
---|
| 271 | + result = ENGINE_ID_UNKNOWN; |
---|
| 272 | + } |
---|
| 273 | + |
---|
| 274 | + return result; |
---|
231 | 275 | } |
---|
232 | 276 | |
---|
233 | 277 | void dce110_link_encoder_set_dp_phy_pattern_training_pattern( |
---|
.. | .. |
---|
420 | 464 | enable_phy_bypass_mode(enc110, false); |
---|
421 | 465 | } |
---|
422 | 466 | |
---|
| 467 | +#if defined(CONFIG_DRM_AMD_DC_SI) |
---|
| 468 | +static void dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2( |
---|
| 469 | + struct dce110_link_encoder *enc110, |
---|
| 470 | + unsigned int cp2520_pattern) |
---|
| 471 | +{ |
---|
| 472 | + |
---|
| 473 | + /* previously there is a register DP_HBR2_EYE_PATTERN |
---|
| 474 | + * that is enabled to get the pattern. |
---|
| 475 | + * But it does not work with the latest spec change, |
---|
| 476 | + * so we are programming the following registers manually. |
---|
| 477 | + * |
---|
| 478 | + * The following settings have been confirmed |
---|
| 479 | + * by Nick Chorney and Sandra Liu */ |
---|
| 480 | + |
---|
| 481 | + /* Disable PHY Bypass mode to setup the test pattern */ |
---|
| 482 | + |
---|
| 483 | + enable_phy_bypass_mode(enc110, false); |
---|
| 484 | + |
---|
| 485 | + /* Setup DIG encoder in DP SST mode */ |
---|
| 486 | + enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT); |
---|
| 487 | + |
---|
| 488 | + /* ensure normal panel mode. */ |
---|
| 489 | + setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT); |
---|
| 490 | + |
---|
| 491 | + /* no vbid after BS (SR) |
---|
| 492 | + * DP_LINK_FRAMING_CNTL changed history Sandra Liu |
---|
| 493 | + * 11000260 / 11000104 / 110000FC */ |
---|
| 494 | + REG_UPDATE_3(DP_LINK_FRAMING_CNTL, |
---|
| 495 | + DP_IDLE_BS_INTERVAL, 0xFC, |
---|
| 496 | + DP_VBID_DISABLE, 1, |
---|
| 497 | + DP_VID_ENHANCED_FRAME_MODE, 1); |
---|
| 498 | + |
---|
| 499 | + /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip swap BS with SR */ |
---|
| 500 | + |
---|
| 501 | + /* select cp2520 patterns */ |
---|
| 502 | + if (REG(DP_DPHY_HBR2_PATTERN_CONTROL)) |
---|
| 503 | + REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL, |
---|
| 504 | + DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern); |
---|
| 505 | + else |
---|
| 506 | + /* pre-DCE11 can only generate CP2520 pattern 2 */ |
---|
| 507 | + ASSERT(cp2520_pattern == 2); |
---|
| 508 | + |
---|
| 509 | + /* set link training complete */ |
---|
| 510 | + set_link_training_complete(enc110, true); |
---|
| 511 | + |
---|
| 512 | + /* disable video stream */ |
---|
| 513 | + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); |
---|
| 514 | + |
---|
| 515 | + /* Disable PHY Bypass mode to setup the test pattern */ |
---|
| 516 | + enable_phy_bypass_mode(enc110, false); |
---|
| 517 | +} |
---|
| 518 | +#endif |
---|
| 519 | + |
---|
423 | 520 | static void set_dp_phy_pattern_passthrough_mode( |
---|
424 | 521 | struct dce110_link_encoder *enc110, |
---|
425 | 522 | enum dp_panel_mode panel_mode) |
---|
.. | .. |
---|
446 | 543 | /* Disable PRBS mode */ |
---|
447 | 544 | disable_prbs_mode(enc110); |
---|
448 | 545 | } |
---|
| 546 | + |
---|
| 547 | +#if defined(CONFIG_DRM_AMD_DC_SI) |
---|
| 548 | +static void dce60_set_dp_phy_pattern_passthrough_mode( |
---|
| 549 | + struct dce110_link_encoder *enc110, |
---|
| 550 | + enum dp_panel_mode panel_mode) |
---|
| 551 | +{ |
---|
| 552 | + /* program correct panel mode */ |
---|
| 553 | + setup_panel_mode(enc110, panel_mode); |
---|
| 554 | + |
---|
| 555 | + /* restore LINK_FRAMING_CNTL |
---|
| 556 | + * in case we were doing HBR2 compliance pattern before |
---|
| 557 | + */ |
---|
| 558 | + REG_UPDATE_3(DP_LINK_FRAMING_CNTL, |
---|
| 559 | + DP_IDLE_BS_INTERVAL, 0x2000, |
---|
| 560 | + DP_VBID_DISABLE, 0, |
---|
| 561 | + DP_VID_ENHANCED_FRAME_MODE, 1); |
---|
| 562 | + |
---|
| 563 | + /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip DPHY_SCRAMBLER_BS_COUNT restore */ |
---|
| 564 | + |
---|
| 565 | + /* set link training complete */ |
---|
| 566 | + set_link_training_complete(enc110, true); |
---|
| 567 | + |
---|
| 568 | + /* Disable PHY Bypass mode to setup the test pattern */ |
---|
| 569 | + enable_phy_bypass_mode(enc110, false); |
---|
| 570 | + |
---|
| 571 | + /* Disable PRBS mode */ |
---|
| 572 | + disable_prbs_mode(enc110); |
---|
| 573 | +} |
---|
| 574 | +#endif |
---|
449 | 575 | |
---|
450 | 576 | /* return value is bit-vector */ |
---|
451 | 577 | static uint8_t get_frontend_source( |
---|
.. | .. |
---|
484 | 610 | /* setup scrambler */ |
---|
485 | 611 | REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1); |
---|
486 | 612 | } |
---|
| 613 | + |
---|
| 614 | +#if defined(CONFIG_DRM_AMD_DC_SI) |
---|
| 615 | +static void dce60_configure_encoder( |
---|
| 616 | + struct dce110_link_encoder *enc110, |
---|
| 617 | + const struct dc_link_settings *link_settings) |
---|
| 618 | +{ |
---|
| 619 | + /* set number of lanes */ |
---|
| 620 | + |
---|
| 621 | + REG_SET(DP_CONFIG, 0, |
---|
| 622 | + DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE); |
---|
| 623 | + |
---|
| 624 | + /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip setup scrambler */ |
---|
| 625 | +} |
---|
| 626 | +#endif |
---|
487 | 627 | |
---|
488 | 628 | static void aux_initialize( |
---|
489 | 629 | struct dce110_link_encoder *enc110) |
---|
.. | .. |
---|
598 | 738 | if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || |
---|
599 | 739 | connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) && |
---|
600 | 740 | signal != SIGNAL_TYPE_HDMI_TYPE_A && |
---|
601 | | - crtc_timing->pix_clk_khz > TMDS_MAX_PIXEL_CLOCK) |
---|
| 741 | + crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10)) |
---|
602 | 742 | return false; |
---|
603 | | - if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) |
---|
| 743 | + if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) |
---|
604 | 744 | return false; |
---|
605 | 745 | |
---|
606 | | - if (crtc_timing->pix_clk_khz > max_pixel_clock) |
---|
| 746 | + if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10)) |
---|
607 | 747 | return false; |
---|
608 | 748 | |
---|
609 | 749 | /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */ |
---|
.. | .. |
---|
644 | 784 | return false; |
---|
645 | 785 | |
---|
646 | 786 | /* DCE11 HW does not support 420 */ |
---|
647 | | - if (!enc110->base.features.ycbcr420_supported && |
---|
| 787 | + if (!enc110->base.features.hdmi_ycbcr420_supported && |
---|
648 | 788 | crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) |
---|
649 | 789 | return false; |
---|
650 | 790 | |
---|
.. | .. |
---|
661 | 801 | const struct dce110_link_encoder *enc110, |
---|
662 | 802 | const struct dc_crtc_timing *crtc_timing) |
---|
663 | 803 | { |
---|
664 | | - /* default RGB only */ |
---|
665 | | - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) |
---|
666 | | - return true; |
---|
| 804 | + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) |
---|
| 805 | + return false; |
---|
667 | 806 | |
---|
668 | | - if (enc110->base.features.flags.bits.IS_YCBCR_CAPABLE) |
---|
669 | | - return true; |
---|
670 | | - |
---|
671 | | - /* for DCE 8.x or later DP Y-only feature, |
---|
672 | | - * we need ASIC cap + FeatureSupportDPYonly, not support 666 */ |
---|
673 | | - if (crtc_timing->flags.Y_ONLY && |
---|
674 | | - enc110->base.features.flags.bits.IS_YCBCR_CAPABLE && |
---|
675 | | - crtc_timing->display_color_depth != COLOR_DEPTH_666) |
---|
676 | | - return true; |
---|
677 | | - |
---|
678 | | - return false; |
---|
| 807 | + return true; |
---|
679 | 808 | } |
---|
680 | 809 | |
---|
681 | 810 | void dce110_link_encoder_construct( |
---|
.. | .. |
---|
798 | 927 | case SIGNAL_TYPE_DVI_DUAL_LINK: |
---|
799 | 928 | is_valid = dce110_link_encoder_validate_dvi_output( |
---|
800 | 929 | enc110, |
---|
801 | | - stream->sink->link->connector_signal, |
---|
| 930 | + stream->link->connector_signal, |
---|
802 | 931 | stream->signal, |
---|
803 | 932 | &stream->timing); |
---|
804 | 933 | break; |
---|
.. | .. |
---|
814 | 943 | enc110, &stream->timing); |
---|
815 | 944 | break; |
---|
816 | 945 | case SIGNAL_TYPE_EDP: |
---|
| 946 | + case SIGNAL_TYPE_LVDS: |
---|
817 | 947 | is_valid = |
---|
818 | 948 | (stream->timing. |
---|
819 | 949 | pixel_encoding == PIXEL_ENCODING_RGB) ? true : false; |
---|
.. | .. |
---|
955 | 1085 | } |
---|
956 | 1086 | } |
---|
957 | 1087 | |
---|
| 1088 | +/* TODO: still need depth or just pass in adjusted pixel clock? */ |
---|
| 1089 | +void dce110_link_encoder_enable_lvds_output( |
---|
| 1090 | + struct link_encoder *enc, |
---|
| 1091 | + enum clock_source_id clock_source, |
---|
| 1092 | + uint32_t pixel_clock) |
---|
| 1093 | +{ |
---|
| 1094 | + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); |
---|
| 1095 | + struct bp_transmitter_control cntl = { 0 }; |
---|
| 1096 | + enum bp_result result; |
---|
| 1097 | + |
---|
| 1098 | + /* Enable the PHY */ |
---|
| 1099 | + cntl.connector_obj_id = enc110->base.connector; |
---|
| 1100 | + cntl.action = TRANSMITTER_CONTROL_ENABLE; |
---|
| 1101 | + cntl.engine_id = enc->preferred_engine; |
---|
| 1102 | + cntl.transmitter = enc110->base.transmitter; |
---|
| 1103 | + cntl.pll_id = clock_source; |
---|
| 1104 | + cntl.signal = SIGNAL_TYPE_LVDS; |
---|
| 1105 | + cntl.lanes_number = 4; |
---|
| 1106 | + |
---|
| 1107 | + cntl.hpd_sel = enc110->base.hpd_source; |
---|
| 1108 | + |
---|
| 1109 | + cntl.pixel_clock = pixel_clock; |
---|
| 1110 | + |
---|
| 1111 | + result = link_transmitter_control(enc110, &cntl); |
---|
| 1112 | + |
---|
| 1113 | + if (result != BP_RESULT_OK) { |
---|
| 1114 | + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", |
---|
| 1115 | + __func__); |
---|
| 1116 | + BREAK_TO_DEBUGGER(); |
---|
| 1117 | + } |
---|
| 1118 | +} |
---|
| 1119 | + |
---|
958 | 1120 | /* enables DP PHY output */ |
---|
959 | 1121 | void dce110_link_encoder_enable_dp_output( |
---|
960 | 1122 | struct link_encoder *enc, |
---|
.. | .. |
---|
1032 | 1194 | BREAK_TO_DEBUGGER(); |
---|
1033 | 1195 | } |
---|
1034 | 1196 | } |
---|
| 1197 | + |
---|
| 1198 | +#if defined(CONFIG_DRM_AMD_DC_SI) |
---|
| 1199 | +/* enables DP PHY output */ |
---|
| 1200 | +void dce60_link_encoder_enable_dp_output( |
---|
| 1201 | + struct link_encoder *enc, |
---|
| 1202 | + const struct dc_link_settings *link_settings, |
---|
| 1203 | + enum clock_source_id clock_source) |
---|
| 1204 | +{ |
---|
| 1205 | + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); |
---|
| 1206 | + struct bp_transmitter_control cntl = { 0 }; |
---|
| 1207 | + enum bp_result result; |
---|
| 1208 | + |
---|
| 1209 | + /* Enable the PHY */ |
---|
| 1210 | + |
---|
| 1211 | + /* number_of_lanes is used for pixel clock adjust, |
---|
| 1212 | + * but it's not passed to asic_control. |
---|
| 1213 | + * We need to set number of lanes manually. |
---|
| 1214 | + */ |
---|
| 1215 | + dce60_configure_encoder(enc110, link_settings); |
---|
| 1216 | + cntl.connector_obj_id = enc110->base.connector; |
---|
| 1217 | + cntl.action = TRANSMITTER_CONTROL_ENABLE; |
---|
| 1218 | + cntl.engine_id = enc->preferred_engine; |
---|
| 1219 | + cntl.transmitter = enc110->base.transmitter; |
---|
| 1220 | + cntl.pll_id = clock_source; |
---|
| 1221 | + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT; |
---|
| 1222 | + cntl.lanes_number = link_settings->lane_count; |
---|
| 1223 | + cntl.hpd_sel = enc110->base.hpd_source; |
---|
| 1224 | + cntl.pixel_clock = link_settings->link_rate |
---|
| 1225 | + * LINK_RATE_REF_FREQ_IN_KHZ; |
---|
| 1226 | + /* TODO: check if undefined works */ |
---|
| 1227 | + cntl.color_depth = COLOR_DEPTH_UNDEFINED; |
---|
| 1228 | + |
---|
| 1229 | + result = link_transmitter_control(enc110, &cntl); |
---|
| 1230 | + |
---|
| 1231 | + if (result != BP_RESULT_OK) { |
---|
| 1232 | + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", |
---|
| 1233 | + __func__); |
---|
| 1234 | + BREAK_TO_DEBUGGER(); |
---|
| 1235 | + } |
---|
| 1236 | +} |
---|
| 1237 | + |
---|
| 1238 | +/* enables DP PHY output in MST mode */ |
---|
| 1239 | +void dce60_link_encoder_enable_dp_mst_output( |
---|
| 1240 | + struct link_encoder *enc, |
---|
| 1241 | + const struct dc_link_settings *link_settings, |
---|
| 1242 | + enum clock_source_id clock_source) |
---|
| 1243 | +{ |
---|
| 1244 | + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); |
---|
| 1245 | + struct bp_transmitter_control cntl = { 0 }; |
---|
| 1246 | + enum bp_result result; |
---|
| 1247 | + |
---|
| 1248 | + /* Enable the PHY */ |
---|
| 1249 | + |
---|
| 1250 | + /* number_of_lanes is used for pixel clock adjust, |
---|
| 1251 | + * but it's not passed to asic_control. |
---|
| 1252 | + * We need to set number of lanes manually. |
---|
| 1253 | + */ |
---|
| 1254 | + dce60_configure_encoder(enc110, link_settings); |
---|
| 1255 | + |
---|
| 1256 | + cntl.action = TRANSMITTER_CONTROL_ENABLE; |
---|
| 1257 | + cntl.engine_id = ENGINE_ID_UNKNOWN; |
---|
| 1258 | + cntl.transmitter = enc110->base.transmitter; |
---|
| 1259 | + cntl.pll_id = clock_source; |
---|
| 1260 | + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST; |
---|
| 1261 | + cntl.lanes_number = link_settings->lane_count; |
---|
| 1262 | + cntl.hpd_sel = enc110->base.hpd_source; |
---|
| 1263 | + cntl.pixel_clock = link_settings->link_rate |
---|
| 1264 | + * LINK_RATE_REF_FREQ_IN_KHZ; |
---|
| 1265 | + /* TODO: check if undefined works */ |
---|
| 1266 | + cntl.color_depth = COLOR_DEPTH_UNDEFINED; |
---|
| 1267 | + |
---|
| 1268 | + result = link_transmitter_control(enc110, &cntl); |
---|
| 1269 | + |
---|
| 1270 | + if (result != BP_RESULT_OK) { |
---|
| 1271 | + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", |
---|
| 1272 | + __func__); |
---|
| 1273 | + BREAK_TO_DEBUGGER(); |
---|
| 1274 | + } |
---|
| 1275 | +} |
---|
| 1276 | +#endif |
---|
| 1277 | + |
---|
1035 | 1278 | /* |
---|
1036 | 1279 | * @brief |
---|
1037 | 1280 | * Disable transmitter and its encoder |
---|
.. | .. |
---|
1180 | 1423 | break; |
---|
1181 | 1424 | } |
---|
1182 | 1425 | } |
---|
| 1426 | + |
---|
| 1427 | +#if defined(CONFIG_DRM_AMD_DC_SI) |
---|
| 1428 | +/* set DP PHY test and training patterns */ |
---|
| 1429 | +void dce60_link_encoder_dp_set_phy_pattern( |
---|
| 1430 | + struct link_encoder *enc, |
---|
| 1431 | + const struct encoder_set_dp_phy_pattern_param *param) |
---|
| 1432 | +{ |
---|
| 1433 | + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); |
---|
| 1434 | + |
---|
| 1435 | + switch (param->dp_phy_pattern) { |
---|
| 1436 | + case DP_TEST_PATTERN_TRAINING_PATTERN1: |
---|
| 1437 | + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0); |
---|
| 1438 | + break; |
---|
| 1439 | + case DP_TEST_PATTERN_TRAINING_PATTERN2: |
---|
| 1440 | + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1); |
---|
| 1441 | + break; |
---|
| 1442 | + case DP_TEST_PATTERN_TRAINING_PATTERN3: |
---|
| 1443 | + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2); |
---|
| 1444 | + break; |
---|
| 1445 | + case DP_TEST_PATTERN_TRAINING_PATTERN4: |
---|
| 1446 | + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3); |
---|
| 1447 | + break; |
---|
| 1448 | + case DP_TEST_PATTERN_D102: |
---|
| 1449 | + set_dp_phy_pattern_d102(enc110); |
---|
| 1450 | + break; |
---|
| 1451 | + case DP_TEST_PATTERN_SYMBOL_ERROR: |
---|
| 1452 | + set_dp_phy_pattern_symbol_error(enc110); |
---|
| 1453 | + break; |
---|
| 1454 | + case DP_TEST_PATTERN_PRBS7: |
---|
| 1455 | + set_dp_phy_pattern_prbs7(enc110); |
---|
| 1456 | + break; |
---|
| 1457 | + case DP_TEST_PATTERN_80BIT_CUSTOM: |
---|
| 1458 | + set_dp_phy_pattern_80bit_custom( |
---|
| 1459 | + enc110, param->custom_pattern); |
---|
| 1460 | + break; |
---|
| 1461 | + case DP_TEST_PATTERN_CP2520_1: |
---|
| 1462 | + dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 1); |
---|
| 1463 | + break; |
---|
| 1464 | + case DP_TEST_PATTERN_CP2520_2: |
---|
| 1465 | + dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2); |
---|
| 1466 | + break; |
---|
| 1467 | + case DP_TEST_PATTERN_CP2520_3: |
---|
| 1468 | + dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 3); |
---|
| 1469 | + break; |
---|
| 1470 | + case DP_TEST_PATTERN_VIDEO_MODE: { |
---|
| 1471 | + dce60_set_dp_phy_pattern_passthrough_mode( |
---|
| 1472 | + enc110, param->dp_panel_mode); |
---|
| 1473 | + break; |
---|
| 1474 | + } |
---|
| 1475 | + |
---|
| 1476 | + default: |
---|
| 1477 | + /* invalid phy pattern */ |
---|
| 1478 | + ASSERT_CRITICAL(false); |
---|
| 1479 | + break; |
---|
| 1480 | + } |
---|
| 1481 | +} |
---|
| 1482 | +#endif |
---|
1183 | 1483 | |
---|
1184 | 1484 | static void fill_stream_allocation_row_info( |
---|
1185 | 1485 | const struct link_mst_stream_allocation *stream_allocation, |
---|
.. | .. |
---|
1363 | 1663 | |
---|
1364 | 1664 | set_reg_field_value(value, 0, DC_HPD_CONTROL, DC_HPD_EN); |
---|
1365 | 1665 | } |
---|
| 1666 | + |
---|
| 1667 | +void dce110_link_encoder_get_max_link_cap(struct link_encoder *enc, |
---|
| 1668 | + struct dc_link_settings *link_settings) |
---|
| 1669 | +{ |
---|
| 1670 | + /* Set Default link settings */ |
---|
| 1671 | + struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH, |
---|
| 1672 | + LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0}; |
---|
| 1673 | + |
---|
| 1674 | + /* Higher link settings based on feature supported */ |
---|
| 1675 | + if (enc->features.flags.bits.IS_HBR2_CAPABLE) |
---|
| 1676 | + max_link_cap.link_rate = LINK_RATE_HIGH2; |
---|
| 1677 | + |
---|
| 1678 | + if (enc->features.flags.bits.IS_HBR3_CAPABLE) |
---|
| 1679 | + max_link_cap.link_rate = LINK_RATE_HIGH3; |
---|
| 1680 | + |
---|
| 1681 | + *link_settings = max_link_cap; |
---|
| 1682 | +} |
---|
| 1683 | + |
---|
| 1684 | +#if defined(CONFIG_DRM_AMD_DC_SI) |
---|
| 1685 | +static const struct link_encoder_funcs dce60_lnk_enc_funcs = { |
---|
| 1686 | + .validate_output_with_stream = |
---|
| 1687 | + dce110_link_encoder_validate_output_with_stream, |
---|
| 1688 | + .hw_init = dce110_link_encoder_hw_init, |
---|
| 1689 | + .setup = dce110_link_encoder_setup, |
---|
| 1690 | + .enable_tmds_output = dce110_link_encoder_enable_tmds_output, |
---|
| 1691 | + .enable_dp_output = dce60_link_encoder_enable_dp_output, |
---|
| 1692 | + .enable_dp_mst_output = dce60_link_encoder_enable_dp_mst_output, |
---|
| 1693 | + .enable_lvds_output = dce110_link_encoder_enable_lvds_output, |
---|
| 1694 | + .disable_output = dce110_link_encoder_disable_output, |
---|
| 1695 | + .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings, |
---|
| 1696 | + .dp_set_phy_pattern = dce60_link_encoder_dp_set_phy_pattern, |
---|
| 1697 | + .update_mst_stream_allocation_table = |
---|
| 1698 | + dce110_link_encoder_update_mst_stream_allocation_table, |
---|
| 1699 | + .psr_program_dp_dphy_fast_training = |
---|
| 1700 | + dce110_psr_program_dp_dphy_fast_training, |
---|
| 1701 | + .psr_program_secondary_packet = dce110_psr_program_secondary_packet, |
---|
| 1702 | + .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, |
---|
| 1703 | + .enable_hpd = dce110_link_encoder_enable_hpd, |
---|
| 1704 | + .disable_hpd = dce110_link_encoder_disable_hpd, |
---|
| 1705 | + .is_dig_enabled = dce110_is_dig_enabled, |
---|
| 1706 | + .destroy = dce110_link_encoder_destroy, |
---|
| 1707 | + .get_max_link_cap = dce110_link_encoder_get_max_link_cap, |
---|
| 1708 | + .get_dig_frontend = dce110_get_dig_frontend |
---|
| 1709 | +}; |
---|
| 1710 | + |
---|
| 1711 | +void dce60_link_encoder_construct( |
---|
| 1712 | + struct dce110_link_encoder *enc110, |
---|
| 1713 | + const struct encoder_init_data *init_data, |
---|
| 1714 | + const struct encoder_feature_support *enc_features, |
---|
| 1715 | + const struct dce110_link_enc_registers *link_regs, |
---|
| 1716 | + const struct dce110_link_enc_aux_registers *aux_regs, |
---|
| 1717 | + const struct dce110_link_enc_hpd_registers *hpd_regs) |
---|
| 1718 | +{ |
---|
| 1719 | + struct bp_encoder_cap_info bp_cap_info = {0}; |
---|
| 1720 | + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; |
---|
| 1721 | + enum bp_result result = BP_RESULT_OK; |
---|
| 1722 | + |
---|
| 1723 | + enc110->base.funcs = &dce60_lnk_enc_funcs; |
---|
| 1724 | + enc110->base.ctx = init_data->ctx; |
---|
| 1725 | + enc110->base.id = init_data->encoder; |
---|
| 1726 | + |
---|
| 1727 | + enc110->base.hpd_source = init_data->hpd_source; |
---|
| 1728 | + enc110->base.connector = init_data->connector; |
---|
| 1729 | + |
---|
| 1730 | + enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; |
---|
| 1731 | + |
---|
| 1732 | + enc110->base.features = *enc_features; |
---|
| 1733 | + |
---|
| 1734 | + enc110->base.transmitter = init_data->transmitter; |
---|
| 1735 | + |
---|
| 1736 | + /* set the flag to indicate whether driver poll the I2C data pin |
---|
| 1737 | + * while doing the DP sink detect |
---|
| 1738 | + */ |
---|
| 1739 | + |
---|
| 1740 | +/* if (dal_adapter_service_is_feature_supported(as, |
---|
| 1741 | + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) |
---|
| 1742 | + enc110->base.features.flags.bits. |
---|
| 1743 | + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ |
---|
| 1744 | + |
---|
| 1745 | + enc110->base.output_signals = |
---|
| 1746 | + SIGNAL_TYPE_DVI_SINGLE_LINK | |
---|
| 1747 | + SIGNAL_TYPE_DVI_DUAL_LINK | |
---|
| 1748 | + SIGNAL_TYPE_LVDS | |
---|
| 1749 | + SIGNAL_TYPE_DISPLAY_PORT | |
---|
| 1750 | + SIGNAL_TYPE_DISPLAY_PORT_MST | |
---|
| 1751 | + SIGNAL_TYPE_EDP | |
---|
| 1752 | + SIGNAL_TYPE_HDMI_TYPE_A; |
---|
| 1753 | + |
---|
| 1754 | + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. |
---|
| 1755 | + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. |
---|
| 1756 | + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer |
---|
| 1757 | + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. |
---|
| 1758 | + * Prefer DIG assignment is decided by board design. |
---|
| 1759 | + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design |
---|
| 1760 | + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. |
---|
| 1761 | + * By this, adding DIGG should not hurt DCE 8.0. |
---|
| 1762 | + * This will let DCE 8.1 share DCE 8.0 as much as possible |
---|
| 1763 | + */ |
---|
| 1764 | + |
---|
| 1765 | + enc110->link_regs = link_regs; |
---|
| 1766 | + enc110->aux_regs = aux_regs; |
---|
| 1767 | + enc110->hpd_regs = hpd_regs; |
---|
| 1768 | + |
---|
| 1769 | + switch (enc110->base.transmitter) { |
---|
| 1770 | + case TRANSMITTER_UNIPHY_A: |
---|
| 1771 | + enc110->base.preferred_engine = ENGINE_ID_DIGA; |
---|
| 1772 | + break; |
---|
| 1773 | + case TRANSMITTER_UNIPHY_B: |
---|
| 1774 | + enc110->base.preferred_engine = ENGINE_ID_DIGB; |
---|
| 1775 | + break; |
---|
| 1776 | + case TRANSMITTER_UNIPHY_C: |
---|
| 1777 | + enc110->base.preferred_engine = ENGINE_ID_DIGC; |
---|
| 1778 | + break; |
---|
| 1779 | + case TRANSMITTER_UNIPHY_D: |
---|
| 1780 | + enc110->base.preferred_engine = ENGINE_ID_DIGD; |
---|
| 1781 | + break; |
---|
| 1782 | + case TRANSMITTER_UNIPHY_E: |
---|
| 1783 | + enc110->base.preferred_engine = ENGINE_ID_DIGE; |
---|
| 1784 | + break; |
---|
| 1785 | + case TRANSMITTER_UNIPHY_F: |
---|
| 1786 | + enc110->base.preferred_engine = ENGINE_ID_DIGF; |
---|
| 1787 | + break; |
---|
| 1788 | + case TRANSMITTER_UNIPHY_G: |
---|
| 1789 | + enc110->base.preferred_engine = ENGINE_ID_DIGG; |
---|
| 1790 | + break; |
---|
| 1791 | + default: |
---|
| 1792 | + ASSERT_CRITICAL(false); |
---|
| 1793 | + enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; |
---|
| 1794 | + } |
---|
| 1795 | + |
---|
| 1796 | + /* default to one to mirror Windows behavior */ |
---|
| 1797 | + enc110->base.features.flags.bits.HDMI_6GB_EN = 1; |
---|
| 1798 | + |
---|
| 1799 | + result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios, |
---|
| 1800 | + enc110->base.id, &bp_cap_info); |
---|
| 1801 | + |
---|
| 1802 | + /* Override features with DCE-specific values */ |
---|
| 1803 | + if (BP_RESULT_OK == result) { |
---|
| 1804 | + enc110->base.features.flags.bits.IS_HBR2_CAPABLE = |
---|
| 1805 | + bp_cap_info.DP_HBR2_EN; |
---|
| 1806 | + enc110->base.features.flags.bits.IS_HBR3_CAPABLE = |
---|
| 1807 | + bp_cap_info.DP_HBR3_EN; |
---|
| 1808 | + enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; |
---|
| 1809 | + } else { |
---|
| 1810 | + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", |
---|
| 1811 | + __func__, |
---|
| 1812 | + result); |
---|
| 1813 | + } |
---|
| 1814 | + if (enc110->base.ctx->dc->debug.hdmi20_disable) { |
---|
| 1815 | + enc110->base.features.flags.bits.HDMI_6GB_EN = 0; |
---|
| 1816 | + } |
---|
| 1817 | +} |
---|
| 1818 | +#endif |
---|