1817 lines · c
1/*2 * Copyright 2012-15 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include "reg_helper.h"27 28#include "core_types.h"29#include "link_encoder.h"30#include "dce_link_encoder.h"31#include "stream_encoder.h"32#include "dc_bios_types.h"33 34#include "gpio_service_interface.h"35 36#include "dce/dce_11_0_d.h"37#include "dce/dce_11_0_sh_mask.h"38#include "dce/dce_11_0_enum.h"39 40#ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT41#define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT 0xa42#endif43 44#ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK45#define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK 0x00000400L46#endif47 48#ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK49#define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK 0x10000000L50#endif51 52#ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT53#define HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT 0x1c54#endif55 56#define CTX \57 enc110->base.ctx58#define DC_LOGGER \59 enc110->base.ctx->logger60 61#define REG(reg)\62 (enc110->link_regs->reg)63 64#define AUX_REG(reg)\65 (enc110->aux_regs->reg)66 67#define HPD_REG(reg)\68 (enc110->hpd_regs->reg)69 70#define DEFAULT_AUX_MAX_DATA_SIZE 1671#define AUX_MAX_DEFER_WRITE_RETRY 2072/*73 * @brief74 * Trigger Source Select75 * ASIC-dependent, actual values for register programming76 */77#define DCE110_DIG_FE_SOURCE_SELECT_INVALID 0x078#define DCE110_DIG_FE_SOURCE_SELECT_DIGA 0x179#define DCE110_DIG_FE_SOURCE_SELECT_DIGB 0x280#define DCE110_DIG_FE_SOURCE_SELECT_DIGC 0x481#define DCE110_DIG_FE_SOURCE_SELECT_DIGD 0x0882#define DCE110_DIG_FE_SOURCE_SELECT_DIGE 0x1083#define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x2084#define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x4085 86enum {87 DP_MST_UPDATE_MAX_RETRY = 5088};89 90#define DIG_REG(reg)\91 (reg + enc110->offsets.dig)92 93#define DP_REG(reg)\94 (reg + enc110->offsets.dp)95 96static const struct link_encoder_funcs dce110_lnk_enc_funcs = {97 .validate_output_with_stream =98 dce110_link_encoder_validate_output_with_stream,99 .hw_init = dce110_link_encoder_hw_init,100 .setup = dce110_link_encoder_setup,101 .enable_tmds_output = dce110_link_encoder_enable_tmds_output,102 .enable_dp_output = dce110_link_encoder_enable_dp_output,103 .enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output,104 .enable_lvds_output = dce110_link_encoder_enable_lvds_output,105 .disable_output = dce110_link_encoder_disable_output,106 .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,107 .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern,108 .update_mst_stream_allocation_table =109 dce110_link_encoder_update_mst_stream_allocation_table,110 .psr_program_dp_dphy_fast_training =111 dce110_psr_program_dp_dphy_fast_training,112 .psr_program_secondary_packet = dce110_psr_program_secondary_packet,113 .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,114 .enable_hpd = dce110_link_encoder_enable_hpd,115 .disable_hpd = dce110_link_encoder_disable_hpd,116 .is_dig_enabled = dce110_is_dig_enabled,117 .destroy = dce110_link_encoder_destroy,118 .get_max_link_cap = dce110_link_encoder_get_max_link_cap,119 .get_dig_frontend = dce110_get_dig_frontend,120};121 122static enum bp_result link_transmitter_control(123 struct dce110_link_encoder *enc110,124 struct bp_transmitter_control *cntl)125{126 enum bp_result result;127 struct dc_bios *bp = enc110->base.ctx->dc_bios;128 129 result = bp->funcs->transmitter_control(bp, cntl);130 131 return result;132}133 134static void enable_phy_bypass_mode(135 struct dce110_link_encoder *enc110,136 bool enable)137{138 /* This register resides in DP back end block;139 * transmitter is used for the offset */140 141 REG_UPDATE(DP_DPHY_CNTL, DPHY_BYPASS, enable);142 143}144 145static void disable_prbs_symbols(146 struct dce110_link_encoder *enc110,147 bool disable)148{149 /* This register resides in DP back end block;150 * transmitter is used for the offset */151 152 REG_UPDATE_4(DP_DPHY_CNTL,153 DPHY_ATEST_SEL_LANE0, disable,154 DPHY_ATEST_SEL_LANE1, disable,155 DPHY_ATEST_SEL_LANE2, disable,156 DPHY_ATEST_SEL_LANE3, disable);157}158 159static void disable_prbs_mode(160 struct dce110_link_encoder *enc110)161{162 REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0);163}164 165static void program_pattern_symbols(166 struct dce110_link_encoder *enc110,167 uint16_t pattern_symbols[8])168{169 /* This register resides in DP back end block;170 * transmitter is used for the offset */171 172 REG_SET_3(DP_DPHY_SYM0, 0,173 DPHY_SYM1, pattern_symbols[0],174 DPHY_SYM2, pattern_symbols[1],175 DPHY_SYM3, pattern_symbols[2]);176 177 /* This register resides in DP back end block;178 * transmitter is used for the offset */179 180 REG_SET_3(DP_DPHY_SYM1, 0,181 DPHY_SYM4, pattern_symbols[3],182 DPHY_SYM5, pattern_symbols[4],183 DPHY_SYM6, pattern_symbols[5]);184 185 /* This register resides in DP back end block;186 * transmitter is used for the offset */187 188 REG_SET_2(DP_DPHY_SYM2, 0,189 DPHY_SYM7, pattern_symbols[6],190 DPHY_SYM8, pattern_symbols[7]);191}192 193static void set_dp_phy_pattern_d102(194 struct dce110_link_encoder *enc110)195{196 /* Disable PHY Bypass mode to setup the test pattern */197 enable_phy_bypass_mode(enc110, false);198 199 /* For 10-bit PRBS or debug symbols200 * please use the following sequence: */201 202 /* Enable debug symbols on the lanes */203 204 disable_prbs_symbols(enc110, true);205 206 /* Disable PRBS mode */207 disable_prbs_mode(enc110);208 209 /* Program debug symbols to be output */210 {211 uint16_t pattern_symbols[8] = {212 0x2AA, 0x2AA, 0x2AA, 0x2AA,213 0x2AA, 0x2AA, 0x2AA, 0x2AA214 };215 216 program_pattern_symbols(enc110, pattern_symbols);217 }218 219 /* Enable phy bypass mode to enable the test pattern */220 221 enable_phy_bypass_mode(enc110, true);222}223 224static void set_link_training_complete(225 struct dce110_link_encoder *enc110,226 bool complete)227{228 /* This register resides in DP back end block;229 * transmitter is used for the offset */230 231 REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete);232 233}234 235unsigned int dce110_get_dig_frontend(struct link_encoder *enc)236{237 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);238 u32 value;239 enum engine_id result;240 241 REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value);242 243 switch (value) {244 case DCE110_DIG_FE_SOURCE_SELECT_DIGA:245 result = ENGINE_ID_DIGA;246 break;247 case DCE110_DIG_FE_SOURCE_SELECT_DIGB:248 result = ENGINE_ID_DIGB;249 break;250 case DCE110_DIG_FE_SOURCE_SELECT_DIGC:251 result = ENGINE_ID_DIGC;252 break;253 case DCE110_DIG_FE_SOURCE_SELECT_DIGD:254 result = ENGINE_ID_DIGD;255 break;256 case DCE110_DIG_FE_SOURCE_SELECT_DIGE:257 result = ENGINE_ID_DIGE;258 break;259 case DCE110_DIG_FE_SOURCE_SELECT_DIGF:260 result = ENGINE_ID_DIGF;261 break;262 case DCE110_DIG_FE_SOURCE_SELECT_DIGG:263 result = ENGINE_ID_DIGG;264 break;265 default:266 // invalid source select DIG267 result = ENGINE_ID_UNKNOWN;268 }269 270 return result;271}272 273void dce110_link_encoder_set_dp_phy_pattern_training_pattern(274 struct link_encoder *enc,275 uint32_t index)276{277 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);278 /* Write Training Pattern */279 280 REG_WRITE(DP_DPHY_TRAINING_PATTERN_SEL, index);281 282 /* Set HW Register Training Complete to false */283 284 set_link_training_complete(enc110, false);285 286 /* Disable PHY Bypass mode to output Training Pattern */287 288 enable_phy_bypass_mode(enc110, false);289 290 /* Disable PRBS mode */291 disable_prbs_mode(enc110);292}293 294static void setup_panel_mode(295 struct dce110_link_encoder *enc110,296 enum dp_panel_mode panel_mode)297{298 uint32_t value;299 struct dc_context *ctx = enc110->base.ctx;300 301 /* if psp set panel mode, dal should be program it */302 if (ctx->dc->caps.psp_setup_panel_mode)303 return;304 305 ASSERT(REG(DP_DPHY_INTERNAL_CTRL));306 value = REG_READ(DP_DPHY_INTERNAL_CTRL);307 308 switch (panel_mode) {309 case DP_PANEL_MODE_EDP:310 value = 0x1;311 break;312 case DP_PANEL_MODE_SPECIAL:313 value = 0x11;314 break;315 default:316 value = 0x0;317 break;318 }319 320 REG_WRITE(DP_DPHY_INTERNAL_CTRL, value);321}322 323static void set_dp_phy_pattern_symbol_error(324 struct dce110_link_encoder *enc110)325{326 /* Disable PHY Bypass mode to setup the test pattern */327 enable_phy_bypass_mode(enc110, false);328 329 /* program correct panel mode*/330 setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);331 332 /* A PRBS23 pattern is used for most DP electrical measurements. */333 334 /* Enable PRBS symbols on the lanes */335 disable_prbs_symbols(enc110, false);336 337 /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */338 REG_UPDATE_2(DP_DPHY_PRBS_CNTL,339 DPHY_PRBS_SEL, 1,340 DPHY_PRBS_EN, 1);341 342 /* Enable phy bypass mode to enable the test pattern */343 enable_phy_bypass_mode(enc110, true);344}345 346static void set_dp_phy_pattern_prbs7(347 struct dce110_link_encoder *enc110)348{349 /* Disable PHY Bypass mode to setup the test pattern */350 enable_phy_bypass_mode(enc110, false);351 352 /* A PRBS7 pattern is used for most DP electrical measurements. */353 354 /* Enable PRBS symbols on the lanes */355 disable_prbs_symbols(enc110, false);356 357 /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */358 REG_UPDATE_2(DP_DPHY_PRBS_CNTL,359 DPHY_PRBS_SEL, 0,360 DPHY_PRBS_EN, 1);361 362 /* Enable phy bypass mode to enable the test pattern */363 enable_phy_bypass_mode(enc110, true);364}365 366static void set_dp_phy_pattern_80bit_custom(367 struct dce110_link_encoder *enc110,368 const uint8_t *pattern)369{370 /* Disable PHY Bypass mode to setup the test pattern */371 enable_phy_bypass_mode(enc110, false);372 373 /* Enable debug symbols on the lanes */374 375 disable_prbs_symbols(enc110, true);376 377 /* Enable PHY bypass mode to enable the test pattern */378 /* TODO is it really needed ? */379 380 enable_phy_bypass_mode(enc110, true);381 382 /* Program 80 bit custom pattern */383 {384 uint16_t pattern_symbols[8];385 386 pattern_symbols[0] =387 ((pattern[1] & 0x03) << 8) | pattern[0];388 pattern_symbols[1] =389 ((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f);390 pattern_symbols[2] =391 ((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f);392 pattern_symbols[3] =393 (pattern[4] << 2) | ((pattern[3] >> 6) & 0x03);394 pattern_symbols[4] =395 ((pattern[6] & 0x03) << 8) | pattern[5];396 pattern_symbols[5] =397 ((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f);398 pattern_symbols[6] =399 ((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f);400 pattern_symbols[7] =401 (pattern[9] << 2) | ((pattern[8] >> 6) & 0x03);402 403 program_pattern_symbols(enc110, pattern_symbols);404 }405 406 /* Enable phy bypass mode to enable the test pattern */407 408 enable_phy_bypass_mode(enc110, true);409}410 411static void set_dp_phy_pattern_hbr2_compliance_cp2520_2(412 struct dce110_link_encoder *enc110,413 unsigned int cp2520_pattern)414{415 416 /* previously there is a register DP_HBR2_EYE_PATTERN417 * that is enabled to get the pattern.418 * But it does not work with the latest spec change,419 * so we are programming the following registers manually.420 *421 * The following settings have been confirmed422 * by Nick Chorney and Sandra Liu */423 424 /* Disable PHY Bypass mode to setup the test pattern */425 426 enable_phy_bypass_mode(enc110, false);427 428 /* Setup DIG encoder in DP SST mode */429 enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT);430 431 /* ensure normal panel mode. */432 setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);433 434 /* no vbid after BS (SR)435 * DP_LINK_FRAMING_CNTL changed history Sandra Liu436 * 11000260 / 11000104 / 110000FC */437 REG_UPDATE_3(DP_LINK_FRAMING_CNTL,438 DP_IDLE_BS_INTERVAL, 0xFC,439 DP_VBID_DISABLE, 1,440 DP_VID_ENHANCED_FRAME_MODE, 1);441 442 /* swap every BS with SR */443 REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0);444 445 /* select cp2520 patterns */446 if (REG(DP_DPHY_HBR2_PATTERN_CONTROL))447 REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL,448 DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern);449 else450 /* pre-DCE11 can only generate CP2520 pattern 2 */451 ASSERT(cp2520_pattern == 2);452 453 /* set link training complete */454 set_link_training_complete(enc110, true);455 456 /* disable video stream */457 REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);458 459 /* Disable PHY Bypass mode to setup the test pattern */460 enable_phy_bypass_mode(enc110, false);461}462 463#if defined(CONFIG_DRM_AMD_DC_SI)464static void dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(465 struct dce110_link_encoder *enc110,466 unsigned int cp2520_pattern)467{468 469 /* previously there is a register DP_HBR2_EYE_PATTERN470 * that is enabled to get the pattern.471 * But it does not work with the latest spec change,472 * so we are programming the following registers manually.473 *474 * The following settings have been confirmed475 * by Nick Chorney and Sandra Liu */476 477 /* Disable PHY Bypass mode to setup the test pattern */478 479 enable_phy_bypass_mode(enc110, false);480 481 /* Setup DIG encoder in DP SST mode */482 enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT);483 484 /* ensure normal panel mode. */485 setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);486 487 /* no vbid after BS (SR)488 * DP_LINK_FRAMING_CNTL changed history Sandra Liu489 * 11000260 / 11000104 / 110000FC */490 REG_UPDATE_3(DP_LINK_FRAMING_CNTL,491 DP_IDLE_BS_INTERVAL, 0xFC,492 DP_VBID_DISABLE, 1,493 DP_VID_ENHANCED_FRAME_MODE, 1);494 495 /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip swap BS with SR */496 497 /* select cp2520 patterns */498 if (REG(DP_DPHY_HBR2_PATTERN_CONTROL))499 REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL,500 DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern);501 else502 /* pre-DCE11 can only generate CP2520 pattern 2 */503 ASSERT(cp2520_pattern == 2);504 505 /* set link training complete */506 set_link_training_complete(enc110, true);507 508 /* disable video stream */509 REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);510 511 /* Disable PHY Bypass mode to setup the test pattern */512 enable_phy_bypass_mode(enc110, false);513}514#endif515 516static void set_dp_phy_pattern_passthrough_mode(517 struct dce110_link_encoder *enc110,518 enum dp_panel_mode panel_mode)519{520 /* program correct panel mode */521 setup_panel_mode(enc110, panel_mode);522 523 /* restore LINK_FRAMING_CNTL and DPHY_SCRAMBLER_BS_COUNT524 * in case we were doing HBR2 compliance pattern before525 */526 REG_UPDATE_3(DP_LINK_FRAMING_CNTL,527 DP_IDLE_BS_INTERVAL, 0x2000,528 DP_VBID_DISABLE, 0,529 DP_VID_ENHANCED_FRAME_MODE, 1);530 531 REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF);532 533 /* set link training complete */534 set_link_training_complete(enc110, true);535 536 /* Disable PHY Bypass mode to setup the test pattern */537 enable_phy_bypass_mode(enc110, false);538 539 /* Disable PRBS mode */540 disable_prbs_mode(enc110);541}542 543#if defined(CONFIG_DRM_AMD_DC_SI)544static void dce60_set_dp_phy_pattern_passthrough_mode(545 struct dce110_link_encoder *enc110,546 enum dp_panel_mode panel_mode)547{548 /* program correct panel mode */549 setup_panel_mode(enc110, panel_mode);550 551 /* restore LINK_FRAMING_CNTL552 * in case we were doing HBR2 compliance pattern before553 */554 REG_UPDATE_3(DP_LINK_FRAMING_CNTL,555 DP_IDLE_BS_INTERVAL, 0x2000,556 DP_VBID_DISABLE, 0,557 DP_VID_ENHANCED_FRAME_MODE, 1);558 559 /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip DPHY_SCRAMBLER_BS_COUNT restore */560 561 /* set link training complete */562 set_link_training_complete(enc110, true);563 564 /* Disable PHY Bypass mode to setup the test pattern */565 enable_phy_bypass_mode(enc110, false);566 567 /* Disable PRBS mode */568 disable_prbs_mode(enc110);569}570#endif571 572/* return value is bit-vector */573static uint8_t get_frontend_source(574 enum engine_id engine)575{576 switch (engine) {577 case ENGINE_ID_DIGA:578 return DCE110_DIG_FE_SOURCE_SELECT_DIGA;579 case ENGINE_ID_DIGB:580 return DCE110_DIG_FE_SOURCE_SELECT_DIGB;581 case ENGINE_ID_DIGC:582 return DCE110_DIG_FE_SOURCE_SELECT_DIGC;583 case ENGINE_ID_DIGD:584 return DCE110_DIG_FE_SOURCE_SELECT_DIGD;585 case ENGINE_ID_DIGE:586 return DCE110_DIG_FE_SOURCE_SELECT_DIGE;587 case ENGINE_ID_DIGF:588 return DCE110_DIG_FE_SOURCE_SELECT_DIGF;589 case ENGINE_ID_DIGG:590 return DCE110_DIG_FE_SOURCE_SELECT_DIGG;591 default:592 ASSERT_CRITICAL(false);593 return DCE110_DIG_FE_SOURCE_SELECT_INVALID;594 }595}596 597static void configure_encoder(598 struct dce110_link_encoder *enc110,599 const struct dc_link_settings *link_settings)600{601 /* set number of lanes */602 603 REG_SET(DP_CONFIG, 0,604 DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE);605 606 /* setup scrambler */607 REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1);608}609 610#if defined(CONFIG_DRM_AMD_DC_SI)611static void dce60_configure_encoder(612 struct dce110_link_encoder *enc110,613 const struct dc_link_settings *link_settings)614{615 /* set number of lanes */616 617 REG_SET(DP_CONFIG, 0,618 DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE);619 620 /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip setup scrambler */621}622#endif623 624static void aux_initialize(625 struct dce110_link_encoder *enc110)626{627 struct dc_context *ctx = enc110->base.ctx;628 enum hpd_source_id hpd_source = enc110->base.hpd_source;629 uint32_t addr = AUX_REG(AUX_CONTROL);630 uint32_t value = dm_read_reg(ctx, addr);631 632 set_reg_field_value(value, hpd_source, AUX_CONTROL, AUX_HPD_SEL);633 set_reg_field_value(value, 0, AUX_CONTROL, AUX_LS_READ_EN);634 dm_write_reg(ctx, addr, value);635 636 addr = AUX_REG(AUX_DPHY_RX_CONTROL0);637 value = dm_read_reg(ctx, addr);638 639 /* 1/4 window (the maximum allowed) */640 set_reg_field_value(value, 1,641 AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW);642 dm_write_reg(ctx, addr, value);643 644}645 646void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc,647 bool exit_link_training_required)648{649 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);650 651 if (exit_link_training_required)652 REG_UPDATE(DP_DPHY_FAST_TRAINING,653 DPHY_RX_FAST_TRAINING_CAPABLE, 1);654 else {655 REG_UPDATE(DP_DPHY_FAST_TRAINING,656 DPHY_RX_FAST_TRAINING_CAPABLE, 0);657 /*In DCE 11, we are able to pre-program a Force SR register658 * to be able to trigger SR symbol after 5 idle patterns659 * transmitted. Upon PSR Exit, DMCU can trigger660 * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to661 * DPHY_LOAD_BS_COUNT_START and the internal counter662 * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be663 * replaced by SR symbol once.664 */665 666 REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5);667 }668}669 670void dce110_psr_program_secondary_packet(struct link_encoder *enc,671 unsigned int sdp_transmit_line_num_deadline)672{673 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);674 675 REG_UPDATE_2(DP_SEC_CNTL1,676 DP_SEC_GSP0_LINE_NUM, sdp_transmit_line_num_deadline,677 DP_SEC_GSP0_PRIORITY, 1);678}679 680bool dce110_is_dig_enabled(struct link_encoder *enc)681{682 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);683 uint32_t value;684 685 REG_GET(DIG_BE_EN_CNTL, DIG_ENABLE, &value);686 return value;687}688 689static void link_encoder_disable(struct dce110_link_encoder *enc110)690{691 /* reset training pattern */692 REG_SET(DP_DPHY_TRAINING_PATTERN_SEL, 0,693 DPHY_TRAINING_PATTERN_SEL, 0);694 695 /* reset training complete */696 REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0);697 698 /* reset panel mode */699 setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);700}701 702static void hpd_initialize(703 struct dce110_link_encoder *enc110)704{705 /* Associate HPD with DIG_BE */706 enum hpd_source_id hpd_source = enc110->base.hpd_source;707 708 REG_UPDATE(DIG_BE_CNTL, DIG_HPD_SELECT, hpd_source);709}710 711bool dce110_link_encoder_validate_dvi_output(712 const struct dce110_link_encoder *enc110,713 enum signal_type connector_signal,714 enum signal_type signal,715 const struct dc_crtc_timing *crtc_timing)716{717 uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK;718 719 if (signal == SIGNAL_TYPE_DVI_DUAL_LINK)720 max_pixel_clock *= 2;721 722 /* This handles the case of HDMI downgrade to DVI we don't want to723 * we don't want to cap the pixel clock if the DDI is not DVI.724 */725 if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK &&726 connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)727 max_pixel_clock = enc110->base.features.max_hdmi_pixel_clock;728 729 /* DVI only support RGB pixel encoding */730 if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB)731 return false;732 733 /*connect DVI via adpater's HDMI connector*/734 if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||735 connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) &&736 signal != SIGNAL_TYPE_HDMI_TYPE_A &&737 crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10))738 return false;739 if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10))740 return false;741 742 if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10))743 return false;744 745 /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */746 switch (crtc_timing->display_color_depth) {747 case COLOR_DEPTH_666:748 case COLOR_DEPTH_888:749 break;750 case COLOR_DEPTH_101010:751 case COLOR_DEPTH_161616:752 if (signal != SIGNAL_TYPE_DVI_DUAL_LINK)753 return false;754 break;755 default:756 return false;757 }758 759 return true;760}761 762static bool dce110_link_encoder_validate_hdmi_output(763 const struct dce110_link_encoder *enc110,764 const struct dc_crtc_timing *crtc_timing,765 int adjusted_pix_clk_khz)766{767 enum dc_color_depth max_deep_color =768 enc110->base.features.max_hdmi_deep_color;769 770 if (max_deep_color < crtc_timing->display_color_depth)771 return false;772 773 if (crtc_timing->display_color_depth < COLOR_DEPTH_888)774 return false;775 if (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)776 return false;777 778 if ((adjusted_pix_clk_khz == 0) ||779 (adjusted_pix_clk_khz > enc110->base.features.max_hdmi_pixel_clock))780 return false;781 782 /* DCE11 HW does not support 420 */783 if (!enc110->base.features.hdmi_ycbcr420_supported &&784 crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)785 return false;786 787 if ((!enc110->base.features.flags.bits.HDMI_6GB_EN ||788 enc110->base.ctx->dc->debug.hdmi20_disable) &&789 adjusted_pix_clk_khz >= 300000)790 return false;791 if (enc110->base.ctx->dc->debug.hdmi20_disable &&792 crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)793 return false;794 return true;795}796 797bool dce110_link_encoder_validate_dp_output(798 const struct dce110_link_encoder *enc110,799 const struct dc_crtc_timing *crtc_timing)800{801 if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)802 return false;803 804 return true;805}806 807void dce110_link_encoder_construct(808 struct dce110_link_encoder *enc110,809 const struct encoder_init_data *init_data,810 const struct encoder_feature_support *enc_features,811 const struct dce110_link_enc_registers *link_regs,812 const struct dce110_link_enc_aux_registers *aux_regs,813 const struct dce110_link_enc_hpd_registers *hpd_regs)814{815 struct bp_encoder_cap_info bp_cap_info = {0};816 const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;817 enum bp_result result = BP_RESULT_OK;818 819 enc110->base.funcs = &dce110_lnk_enc_funcs;820 enc110->base.ctx = init_data->ctx;821 enc110->base.id = init_data->encoder;822 823 enc110->base.hpd_source = init_data->hpd_source;824 enc110->base.connector = init_data->connector;825 826 enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;827 828 enc110->base.features = *enc_features;829 830 enc110->base.transmitter = init_data->transmitter;831 832 /* set the flag to indicate whether driver poll the I2C data pin833 * while doing the DP sink detect834 */835 836/* if (dal_adapter_service_is_feature_supported(as,837 FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))838 enc110->base.features.flags.bits.839 DP_SINK_DETECT_POLL_DATA_PIN = true;*/840 841 enc110->base.output_signals =842 SIGNAL_TYPE_DVI_SINGLE_LINK |843 SIGNAL_TYPE_DVI_DUAL_LINK |844 SIGNAL_TYPE_LVDS |845 SIGNAL_TYPE_DISPLAY_PORT |846 SIGNAL_TYPE_DISPLAY_PORT_MST |847 SIGNAL_TYPE_EDP |848 SIGNAL_TYPE_HDMI_TYPE_A;849 850 /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE.851 * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY.852 * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer853 * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS.854 * Prefer DIG assignment is decided by board design.855 * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design856 * and VBIOS will filter out 7 UNIPHY for DCE 8.0.857 * By this, adding DIGG should not hurt DCE 8.0.858 * This will let DCE 8.1 share DCE 8.0 as much as possible859 */860 861 enc110->link_regs = link_regs;862 enc110->aux_regs = aux_regs;863 enc110->hpd_regs = hpd_regs;864 865 switch (enc110->base.transmitter) {866 case TRANSMITTER_UNIPHY_A:867 enc110->base.preferred_engine = ENGINE_ID_DIGA;868 break;869 case TRANSMITTER_UNIPHY_B:870 enc110->base.preferred_engine = ENGINE_ID_DIGB;871 break;872 case TRANSMITTER_UNIPHY_C:873 enc110->base.preferred_engine = ENGINE_ID_DIGC;874 break;875 case TRANSMITTER_UNIPHY_D:876 enc110->base.preferred_engine = ENGINE_ID_DIGD;877 break;878 case TRANSMITTER_UNIPHY_E:879 enc110->base.preferred_engine = ENGINE_ID_DIGE;880 break;881 case TRANSMITTER_UNIPHY_F:882 enc110->base.preferred_engine = ENGINE_ID_DIGF;883 break;884 case TRANSMITTER_UNIPHY_G:885 enc110->base.preferred_engine = ENGINE_ID_DIGG;886 break;887 default:888 ASSERT_CRITICAL(false);889 enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;890 }891 892 /* default to one to mirror Windows behavior */893 enc110->base.features.flags.bits.HDMI_6GB_EN = 1;894 895 result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios,896 enc110->base.id, &bp_cap_info);897 898 /* Override features with DCE-specific values */899 if (BP_RESULT_OK == result) {900 enc110->base.features.flags.bits.IS_HBR2_CAPABLE =901 bp_cap_info.DP_HBR2_EN;902 enc110->base.features.flags.bits.IS_HBR3_CAPABLE =903 bp_cap_info.DP_HBR3_EN;904 enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;905 } else {906 DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",907 __func__,908 result);909 }910 if (enc110->base.ctx->dc->debug.hdmi20_disable) {911 enc110->base.features.flags.bits.HDMI_6GB_EN = 0;912 }913}914 915bool dce110_link_encoder_validate_output_with_stream(916 struct link_encoder *enc,917 const struct dc_stream_state *stream)918{919 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);920 bool is_valid;921 922 switch (stream->signal) {923 case SIGNAL_TYPE_DVI_SINGLE_LINK:924 case SIGNAL_TYPE_DVI_DUAL_LINK:925 is_valid = dce110_link_encoder_validate_dvi_output(926 enc110,927 stream->link->connector_signal,928 stream->signal,929 &stream->timing);930 break;931 case SIGNAL_TYPE_HDMI_TYPE_A:932 is_valid = dce110_link_encoder_validate_hdmi_output(933 enc110,934 &stream->timing,935 stream->phy_pix_clk);936 break;937 case SIGNAL_TYPE_DISPLAY_PORT:938 case SIGNAL_TYPE_DISPLAY_PORT_MST:939 is_valid = dce110_link_encoder_validate_dp_output(940 enc110, &stream->timing);941 break;942 case SIGNAL_TYPE_EDP:943 case SIGNAL_TYPE_LVDS:944 is_valid = stream->timing.pixel_encoding == PIXEL_ENCODING_RGB;945 break;946 case SIGNAL_TYPE_VIRTUAL:947 is_valid = true;948 break;949 default:950 is_valid = false;951 break;952 }953 954 return is_valid;955}956 957void dce110_link_encoder_hw_init(958 struct link_encoder *enc)959{960 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);961 struct bp_transmitter_control cntl = { 0 };962 enum bp_result result;963 964 cntl.action = TRANSMITTER_CONTROL_INIT;965 cntl.engine_id = ENGINE_ID_UNKNOWN;966 cntl.transmitter = enc110->base.transmitter;967 cntl.connector_obj_id = enc110->base.connector;968 cntl.lanes_number = LANE_COUNT_FOUR;969 cntl.coherent = false;970 cntl.hpd_sel = enc110->base.hpd_source;971 972 if (enc110->base.connector.id == CONNECTOR_ID_EDP)973 cntl.signal = SIGNAL_TYPE_EDP;974 975 result = link_transmitter_control(enc110, &cntl);976 977 if (result != BP_RESULT_OK) {978 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",979 __func__);980 BREAK_TO_DEBUGGER();981 return;982 }983 984 if (enc110->base.connector.id == CONNECTOR_ID_LVDS) {985 cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS;986 987 result = link_transmitter_control(enc110, &cntl);988 989 ASSERT(result == BP_RESULT_OK);990 991 }992 aux_initialize(enc110);993 994 /* reinitialize HPD.995 * hpd_initialize() will pass DIG_FE id to HW context.996 * All other routine within HW context will use fe_engine_offset997 * as DIG_FE id even caller pass DIG_FE id.998 * So this routine must be called first. */999 hpd_initialize(enc110);1000}1001 1002void dce110_link_encoder_destroy(struct link_encoder **enc)1003{1004 kfree(TO_DCE110_LINK_ENC(*enc));1005 *enc = NULL;1006}1007 1008void dce110_link_encoder_setup(1009 struct link_encoder *enc,1010 enum signal_type signal)1011{1012 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1013 1014 switch (signal) {1015 case SIGNAL_TYPE_EDP:1016 case SIGNAL_TYPE_DISPLAY_PORT:1017 /* DP SST */1018 REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 0);1019 break;1020 case SIGNAL_TYPE_LVDS:1021 /* LVDS */1022 REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 1);1023 break;1024 case SIGNAL_TYPE_DVI_SINGLE_LINK:1025 case SIGNAL_TYPE_DVI_DUAL_LINK:1026 /* TMDS-DVI */1027 REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 2);1028 break;1029 case SIGNAL_TYPE_HDMI_TYPE_A:1030 /* TMDS-HDMI */1031 REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 3);1032 break;1033 case SIGNAL_TYPE_DISPLAY_PORT_MST:1034 /* DP MST */1035 REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 5);1036 break;1037 default:1038 ASSERT_CRITICAL(false);1039 /* invalid mode ! */1040 break;1041 }1042 1043}1044 1045/* TODO: still need depth or just pass in adjusted pixel clock? */1046void dce110_link_encoder_enable_tmds_output(1047 struct link_encoder *enc,1048 enum clock_source_id clock_source,1049 enum dc_color_depth color_depth,1050 enum signal_type signal,1051 uint32_t pixel_clock)1052{1053 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1054 struct bp_transmitter_control cntl = { 0 };1055 enum bp_result result;1056 1057 /* Enable the PHY */1058 cntl.connector_obj_id = enc110->base.connector;1059 cntl.action = TRANSMITTER_CONTROL_ENABLE;1060 cntl.engine_id = enc->preferred_engine;1061 cntl.transmitter = enc110->base.transmitter;1062 cntl.pll_id = clock_source;1063 cntl.signal = signal;1064 if (cntl.signal == SIGNAL_TYPE_DVI_DUAL_LINK)1065 cntl.lanes_number = 8;1066 else1067 cntl.lanes_number = 4;1068 1069 cntl.hpd_sel = enc110->base.hpd_source;1070 1071 cntl.pixel_clock = pixel_clock;1072 cntl.color_depth = color_depth;1073 1074 result = link_transmitter_control(enc110, &cntl);1075 1076 if (result != BP_RESULT_OK) {1077 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1078 __func__);1079 BREAK_TO_DEBUGGER();1080 }1081}1082 1083/* TODO: still need depth or just pass in adjusted pixel clock? */1084void dce110_link_encoder_enable_lvds_output(1085 struct link_encoder *enc,1086 enum clock_source_id clock_source,1087 uint32_t pixel_clock)1088{1089 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1090 struct bp_transmitter_control cntl = { 0 };1091 enum bp_result result;1092 1093 /* Enable the PHY */1094 cntl.connector_obj_id = enc110->base.connector;1095 cntl.action = TRANSMITTER_CONTROL_ENABLE;1096 cntl.engine_id = enc->preferred_engine;1097 cntl.transmitter = enc110->base.transmitter;1098 cntl.pll_id = clock_source;1099 cntl.signal = SIGNAL_TYPE_LVDS;1100 cntl.lanes_number = 4;1101 1102 cntl.hpd_sel = enc110->base.hpd_source;1103 1104 cntl.pixel_clock = pixel_clock;1105 1106 result = link_transmitter_control(enc110, &cntl);1107 1108 if (result != BP_RESULT_OK) {1109 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1110 __func__);1111 BREAK_TO_DEBUGGER();1112 }1113}1114 1115/* enables DP PHY output */1116void dce110_link_encoder_enable_dp_output(1117 struct link_encoder *enc,1118 const struct dc_link_settings *link_settings,1119 enum clock_source_id clock_source)1120{1121 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1122 struct bp_transmitter_control cntl = { 0 };1123 enum bp_result result;1124 1125 /* Enable the PHY */1126 1127 /* number_of_lanes is used for pixel clock adjust,1128 * but it's not passed to asic_control.1129 * We need to set number of lanes manually.1130 */1131 configure_encoder(enc110, link_settings);1132 cntl.connector_obj_id = enc110->base.connector;1133 cntl.action = TRANSMITTER_CONTROL_ENABLE;1134 cntl.engine_id = enc->preferred_engine;1135 cntl.transmitter = enc110->base.transmitter;1136 cntl.pll_id = clock_source;1137 cntl.signal = SIGNAL_TYPE_DISPLAY_PORT;1138 cntl.lanes_number = link_settings->lane_count;1139 cntl.hpd_sel = enc110->base.hpd_source;1140 cntl.pixel_clock = link_settings->link_rate1141 * LINK_RATE_REF_FREQ_IN_KHZ;1142 /* TODO: check if undefined works */1143 cntl.color_depth = COLOR_DEPTH_UNDEFINED;1144 1145 result = link_transmitter_control(enc110, &cntl);1146 1147 if (result != BP_RESULT_OK) {1148 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1149 __func__);1150 BREAK_TO_DEBUGGER();1151 }1152}1153 1154/* enables DP PHY output in MST mode */1155void dce110_link_encoder_enable_dp_mst_output(1156 struct link_encoder *enc,1157 const struct dc_link_settings *link_settings,1158 enum clock_source_id clock_source)1159{1160 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1161 struct bp_transmitter_control cntl = { 0 };1162 enum bp_result result;1163 1164 /* Enable the PHY */1165 1166 /* number_of_lanes is used for pixel clock adjust,1167 * but it's not passed to asic_control.1168 * We need to set number of lanes manually.1169 */1170 configure_encoder(enc110, link_settings);1171 1172 cntl.action = TRANSMITTER_CONTROL_ENABLE;1173 cntl.engine_id = ENGINE_ID_UNKNOWN;1174 cntl.transmitter = enc110->base.transmitter;1175 cntl.pll_id = clock_source;1176 cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;1177 cntl.lanes_number = link_settings->lane_count;1178 cntl.hpd_sel = enc110->base.hpd_source;1179 cntl.pixel_clock = link_settings->link_rate1180 * LINK_RATE_REF_FREQ_IN_KHZ;1181 /* TODO: check if undefined works */1182 cntl.color_depth = COLOR_DEPTH_UNDEFINED;1183 1184 result = link_transmitter_control(enc110, &cntl);1185 1186 if (result != BP_RESULT_OK) {1187 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1188 __func__);1189 BREAK_TO_DEBUGGER();1190 }1191}1192 1193#if defined(CONFIG_DRM_AMD_DC_SI)1194/* enables DP PHY output */1195static void dce60_link_encoder_enable_dp_output(1196 struct link_encoder *enc,1197 const struct dc_link_settings *link_settings,1198 enum clock_source_id clock_source)1199{1200 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1201 struct bp_transmitter_control cntl = { 0 };1202 enum bp_result result;1203 1204 /* Enable the PHY */1205 1206 /* number_of_lanes is used for pixel clock adjust,1207 * but it's not passed to asic_control.1208 * We need to set number of lanes manually.1209 */1210 dce60_configure_encoder(enc110, link_settings);1211 cntl.connector_obj_id = enc110->base.connector;1212 cntl.action = TRANSMITTER_CONTROL_ENABLE;1213 cntl.engine_id = enc->preferred_engine;1214 cntl.transmitter = enc110->base.transmitter;1215 cntl.pll_id = clock_source;1216 cntl.signal = SIGNAL_TYPE_DISPLAY_PORT;1217 cntl.lanes_number = link_settings->lane_count;1218 cntl.hpd_sel = enc110->base.hpd_source;1219 cntl.pixel_clock = link_settings->link_rate1220 * LINK_RATE_REF_FREQ_IN_KHZ;1221 /* TODO: check if undefined works */1222 cntl.color_depth = COLOR_DEPTH_UNDEFINED;1223 1224 result = link_transmitter_control(enc110, &cntl);1225 1226 if (result != BP_RESULT_OK) {1227 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1228 __func__);1229 BREAK_TO_DEBUGGER();1230 }1231}1232 1233/* enables DP PHY output in MST mode */1234static void dce60_link_encoder_enable_dp_mst_output(1235 struct link_encoder *enc,1236 const struct dc_link_settings *link_settings,1237 enum clock_source_id clock_source)1238{1239 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1240 struct bp_transmitter_control cntl = { 0 };1241 enum bp_result result;1242 1243 /* Enable the PHY */1244 1245 /* number_of_lanes is used for pixel clock adjust,1246 * but it's not passed to asic_control.1247 * We need to set number of lanes manually.1248 */1249 dce60_configure_encoder(enc110, link_settings);1250 1251 cntl.action = TRANSMITTER_CONTROL_ENABLE;1252 cntl.engine_id = ENGINE_ID_UNKNOWN;1253 cntl.transmitter = enc110->base.transmitter;1254 cntl.pll_id = clock_source;1255 cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;1256 cntl.lanes_number = link_settings->lane_count;1257 cntl.hpd_sel = enc110->base.hpd_source;1258 cntl.pixel_clock = link_settings->link_rate1259 * LINK_RATE_REF_FREQ_IN_KHZ;1260 /* TODO: check if undefined works */1261 cntl.color_depth = COLOR_DEPTH_UNDEFINED;1262 1263 result = link_transmitter_control(enc110, &cntl);1264 1265 if (result != BP_RESULT_OK) {1266 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1267 __func__);1268 BREAK_TO_DEBUGGER();1269 }1270}1271#endif1272 1273/*1274 * @brief1275 * Disable transmitter and its encoder1276 */1277void dce110_link_encoder_disable_output(1278 struct link_encoder *enc,1279 enum signal_type signal)1280{1281 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1282 struct bp_transmitter_control cntl = { 0 };1283 enum bp_result result;1284 1285 if (!dce110_is_dig_enabled(enc)) {1286 /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */1287 return;1288 }1289 /* Power-down RX and disable GPU PHY should be paired.1290 * Disabling PHY without powering down RX may cause1291 * symbol lock loss, on which we will get DP Sink interrupt. */1292 1293 /* There is a case for the DP active dongles1294 * where we want to disable the PHY but keep RX powered,1295 * for those we need to ignore DP Sink interrupt1296 * by checking lane count that has been set1297 * on the last do_enable_output(). */1298 1299 /* disable transmitter */1300 cntl.action = TRANSMITTER_CONTROL_DISABLE;1301 cntl.transmitter = enc110->base.transmitter;1302 cntl.hpd_sel = enc110->base.hpd_source;1303 cntl.signal = signal;1304 cntl.connector_obj_id = enc110->base.connector;1305 1306 result = link_transmitter_control(enc110, &cntl);1307 1308 if (result != BP_RESULT_OK) {1309 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1310 __func__);1311 BREAK_TO_DEBUGGER();1312 return;1313 }1314 1315 /* disable encoder */1316 if (dc_is_dp_signal(signal))1317 link_encoder_disable(enc110);1318}1319 1320void dce110_link_encoder_dp_set_lane_settings(1321 struct link_encoder *enc,1322 const struct dc_link_settings *link_settings,1323 const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])1324{1325 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1326 union dpcd_training_lane_set training_lane_set = { { 0 } };1327 int32_t lane = 0;1328 struct bp_transmitter_control cntl = { 0 };1329 1330 if (!link_settings) {1331 BREAK_TO_DEBUGGER();1332 return;1333 }1334 1335 cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;1336 cntl.transmitter = enc110->base.transmitter;1337 cntl.connector_obj_id = enc110->base.connector;1338 cntl.lanes_number = link_settings->lane_count;1339 cntl.hpd_sel = enc110->base.hpd_source;1340 cntl.pixel_clock = link_settings->link_rate *1341 LINK_RATE_REF_FREQ_IN_KHZ;1342 1343 for (lane = 0; lane < link_settings->lane_count; lane++) {1344 /* translate lane settings */1345 1346 training_lane_set.bits.VOLTAGE_SWING_SET =1347 lane_settings[lane].VOLTAGE_SWING;1348 training_lane_set.bits.PRE_EMPHASIS_SET =1349 lane_settings[lane].PRE_EMPHASIS;1350 1351 /* post cursor 2 setting only applies to HBR2 link rate */1352 if (link_settings->link_rate == LINK_RATE_HIGH2) {1353 /* this is passed to VBIOS1354 * to program post cursor 2 level */1355 1356 training_lane_set.bits.POST_CURSOR2_SET =1357 lane_settings[lane].POST_CURSOR2;1358 }1359 1360 cntl.lane_select = lane;1361 cntl.lane_settings = training_lane_set.raw;1362 1363 /* call VBIOS table to set voltage swing and pre-emphasis */1364 if (link_transmitter_control(enc110, &cntl) != BP_RESULT_OK) {1365 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", __func__);1366 BREAK_TO_DEBUGGER();1367 }1368 }1369}1370 1371/* set DP PHY test and training patterns */1372void dce110_link_encoder_dp_set_phy_pattern(1373 struct link_encoder *enc,1374 const struct encoder_set_dp_phy_pattern_param *param)1375{1376 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1377 1378 switch (param->dp_phy_pattern) {1379 case DP_TEST_PATTERN_TRAINING_PATTERN1:1380 dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0);1381 break;1382 case DP_TEST_PATTERN_TRAINING_PATTERN2:1383 dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1);1384 break;1385 case DP_TEST_PATTERN_TRAINING_PATTERN3:1386 dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2);1387 break;1388 case DP_TEST_PATTERN_TRAINING_PATTERN4:1389 dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3);1390 break;1391 case DP_TEST_PATTERN_D102:1392 set_dp_phy_pattern_d102(enc110);1393 break;1394 case DP_TEST_PATTERN_SYMBOL_ERROR:1395 set_dp_phy_pattern_symbol_error(enc110);1396 break;1397 case DP_TEST_PATTERN_PRBS7:1398 set_dp_phy_pattern_prbs7(enc110);1399 break;1400 case DP_TEST_PATTERN_80BIT_CUSTOM:1401 set_dp_phy_pattern_80bit_custom(1402 enc110, param->custom_pattern);1403 break;1404 case DP_TEST_PATTERN_CP2520_1:1405 set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 1);1406 break;1407 case DP_TEST_PATTERN_CP2520_2:1408 set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2);1409 break;1410 case DP_TEST_PATTERN_CP2520_3:1411 set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 3);1412 break;1413 case DP_TEST_PATTERN_VIDEO_MODE: {1414 set_dp_phy_pattern_passthrough_mode(1415 enc110, param->dp_panel_mode);1416 break;1417 }1418 1419 default:1420 /* invalid phy pattern */1421 ASSERT_CRITICAL(false);1422 break;1423 }1424}1425 1426#if defined(CONFIG_DRM_AMD_DC_SI)1427/* set DP PHY test and training patterns */1428static void dce60_link_encoder_dp_set_phy_pattern(1429 struct link_encoder *enc,1430 const struct encoder_set_dp_phy_pattern_param *param)1431{1432 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1433 1434 switch (param->dp_phy_pattern) {1435 case DP_TEST_PATTERN_TRAINING_PATTERN1:1436 dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0);1437 break;1438 case DP_TEST_PATTERN_TRAINING_PATTERN2:1439 dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1);1440 break;1441 case DP_TEST_PATTERN_TRAINING_PATTERN3:1442 dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2);1443 break;1444 case DP_TEST_PATTERN_TRAINING_PATTERN4:1445 dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3);1446 break;1447 case DP_TEST_PATTERN_D102:1448 set_dp_phy_pattern_d102(enc110);1449 break;1450 case DP_TEST_PATTERN_SYMBOL_ERROR:1451 set_dp_phy_pattern_symbol_error(enc110);1452 break;1453 case DP_TEST_PATTERN_PRBS7:1454 set_dp_phy_pattern_prbs7(enc110);1455 break;1456 case DP_TEST_PATTERN_80BIT_CUSTOM:1457 set_dp_phy_pattern_80bit_custom(1458 enc110, param->custom_pattern);1459 break;1460 case DP_TEST_PATTERN_CP2520_1:1461 dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 1);1462 break;1463 case DP_TEST_PATTERN_CP2520_2:1464 dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2);1465 break;1466 case DP_TEST_PATTERN_CP2520_3:1467 dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 3);1468 break;1469 case DP_TEST_PATTERN_VIDEO_MODE: {1470 dce60_set_dp_phy_pattern_passthrough_mode(1471 enc110, param->dp_panel_mode);1472 break;1473 }1474 1475 default:1476 /* invalid phy pattern */1477 ASSERT_CRITICAL(false);1478 break;1479 }1480}1481#endif1482 1483static void fill_stream_allocation_row_info(1484 const struct link_mst_stream_allocation *stream_allocation,1485 uint32_t *src,1486 uint32_t *slots)1487{1488 const struct stream_encoder *stream_enc = stream_allocation->stream_enc;1489 1490 if (stream_enc) {1491 *src = stream_enc->id;1492 *slots = stream_allocation->slot_count;1493 } else {1494 *src = 0;1495 *slots = 0;1496 }1497}1498 1499/* programs DP MST VC payload allocation */1500void dce110_link_encoder_update_mst_stream_allocation_table(1501 struct link_encoder *enc,1502 const struct link_mst_stream_allocation_table *table)1503{1504 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1505 uint32_t value1 = 0;1506 uint32_t value2 = 0;1507 uint32_t slots = 0;1508 uint32_t src = 0;1509 uint32_t retries = 0;1510 1511 /* For CZ, there are only 3 pipes. So Virtual channel is up 3.*/1512 1513 /* --- Set MSE Stream Attribute -1514 * Setup VC Payload Table on Tx Side,1515 * Issue allocation change trigger1516 * to commit payload on both tx and rx side */1517 1518 /* we should clean-up table each time */1519 1520 if (table->stream_count >= 1) {1521 fill_stream_allocation_row_info(1522 &table->stream_allocations[0],1523 &src,1524 &slots);1525 } else {1526 src = 0;1527 slots = 0;1528 }1529 1530 REG_UPDATE_2(DP_MSE_SAT0,1531 DP_MSE_SAT_SRC0, src,1532 DP_MSE_SAT_SLOT_COUNT0, slots);1533 1534 if (table->stream_count >= 2) {1535 fill_stream_allocation_row_info(1536 &table->stream_allocations[1],1537 &src,1538 &slots);1539 } else {1540 src = 0;1541 slots = 0;1542 }1543 1544 REG_UPDATE_2(DP_MSE_SAT0,1545 DP_MSE_SAT_SRC1, src,1546 DP_MSE_SAT_SLOT_COUNT1, slots);1547 1548 if (table->stream_count >= 3) {1549 fill_stream_allocation_row_info(1550 &table->stream_allocations[2],1551 &src,1552 &slots);1553 } else {1554 src = 0;1555 slots = 0;1556 }1557 1558 REG_UPDATE_2(DP_MSE_SAT1,1559 DP_MSE_SAT_SRC2, src,1560 DP_MSE_SAT_SLOT_COUNT2, slots);1561 1562 if (table->stream_count >= 4) {1563 fill_stream_allocation_row_info(1564 &table->stream_allocations[3],1565 &src,1566 &slots);1567 } else {1568 src = 0;1569 slots = 0;1570 }1571 1572 REG_UPDATE_2(DP_MSE_SAT1,1573 DP_MSE_SAT_SRC3, src,1574 DP_MSE_SAT_SLOT_COUNT3, slots);1575 1576 /* --- wait for transaction finish */1577 1578 /* send allocation change trigger (ACT) ?1579 * this step first sends the ACT,1580 * then double buffers the SAT into the hardware1581 * making the new allocation active on the DP MST mode link */1582 1583 1584 /* DP_MSE_SAT_UPDATE:1585 * 0 - No Action1586 * 1 - Update SAT with trigger1587 * 2 - Update SAT without trigger */1588 1589 REG_UPDATE(DP_MSE_SAT_UPDATE,1590 DP_MSE_SAT_UPDATE, 1);1591 1592 /* wait for update to complete1593 * (i.e. DP_MSE_SAT_UPDATE field is reset to 0)1594 * then wait for the transmission1595 * of at least 16 MTP headers on immediate local link.1596 * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 01597 * a value of 1 indicates that DP MST mode1598 * is in the 16 MTP keepout region after a VC has been added.1599 * MST stream bandwidth (VC rate) can be configured1600 * after this bit is cleared */1601 1602 do {1603 udelay(10);1604 1605 REG_READ(DP_MSE_SAT_UPDATE);1606 1607 REG_GET(DP_MSE_SAT_UPDATE,1608 DP_MSE_SAT_UPDATE, &value1);1609 1610 REG_GET(DP_MSE_SAT_UPDATE,1611 DP_MSE_16_MTP_KEEPOUT, &value2);1612 1613 /* bit field DP_MSE_SAT_UPDATE is set to 1 already */1614 if (!value1 && !value2)1615 break;1616 ++retries;1617 } while (retries < DP_MST_UPDATE_MAX_RETRY);1618}1619 1620void dce110_link_encoder_connect_dig_be_to_fe(1621 struct link_encoder *enc,1622 enum engine_id engine,1623 bool connect)1624{1625 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1626 uint32_t field;1627 1628 if (engine != ENGINE_ID_UNKNOWN) {1629 1630 REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &field);1631 1632 if (connect)1633 field |= get_frontend_source(engine);1634 else1635 field &= ~get_frontend_source(engine);1636 1637 REG_UPDATE(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, field);1638 }1639}1640 1641void dce110_link_encoder_enable_hpd(struct link_encoder *enc)1642{1643 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1644 struct dc_context *ctx = enc110->base.ctx;1645 uint32_t addr = HPD_REG(DC_HPD_CONTROL);1646 uint32_t hpd_enable = 0;1647 uint32_t value = dm_read_reg(ctx, addr);1648 1649 hpd_enable = get_reg_field_value(hpd_enable, DC_HPD_CONTROL, DC_HPD_EN);1650 1651 if (hpd_enable == 0)1652 set_reg_field_value(value, 1, DC_HPD_CONTROL, DC_HPD_EN);1653}1654 1655void dce110_link_encoder_disable_hpd(struct link_encoder *enc)1656{1657 struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1658 struct dc_context *ctx = enc110->base.ctx;1659 uint32_t addr = HPD_REG(DC_HPD_CONTROL);1660 uint32_t value = dm_read_reg(ctx, addr);1661 1662 set_reg_field_value(value, 0, DC_HPD_CONTROL, DC_HPD_EN);1663}1664 1665void dce110_link_encoder_get_max_link_cap(struct link_encoder *enc,1666 struct dc_link_settings *link_settings)1667{1668 /* Set Default link settings */1669 struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,1670 LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0};1671 1672 /* Higher link settings based on feature supported */1673 if (enc->features.flags.bits.IS_HBR2_CAPABLE)1674 max_link_cap.link_rate = LINK_RATE_HIGH2;1675 1676 if (enc->features.flags.bits.IS_HBR3_CAPABLE)1677 max_link_cap.link_rate = LINK_RATE_HIGH3;1678 1679 *link_settings = max_link_cap;1680}1681 1682#if defined(CONFIG_DRM_AMD_DC_SI)1683static const struct link_encoder_funcs dce60_lnk_enc_funcs = {1684 .validate_output_with_stream =1685 dce110_link_encoder_validate_output_with_stream,1686 .hw_init = dce110_link_encoder_hw_init,1687 .setup = dce110_link_encoder_setup,1688 .enable_tmds_output = dce110_link_encoder_enable_tmds_output,1689 .enable_dp_output = dce60_link_encoder_enable_dp_output,1690 .enable_dp_mst_output = dce60_link_encoder_enable_dp_mst_output,1691 .enable_lvds_output = dce110_link_encoder_enable_lvds_output,1692 .disable_output = dce110_link_encoder_disable_output,1693 .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,1694 .dp_set_phy_pattern = dce60_link_encoder_dp_set_phy_pattern,1695 .update_mst_stream_allocation_table =1696 dce110_link_encoder_update_mst_stream_allocation_table,1697 .psr_program_dp_dphy_fast_training =1698 dce110_psr_program_dp_dphy_fast_training,1699 .psr_program_secondary_packet = dce110_psr_program_secondary_packet,1700 .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,1701 .enable_hpd = dce110_link_encoder_enable_hpd,1702 .disable_hpd = dce110_link_encoder_disable_hpd,1703 .is_dig_enabled = dce110_is_dig_enabled,1704 .destroy = dce110_link_encoder_destroy,1705 .get_max_link_cap = dce110_link_encoder_get_max_link_cap,1706 .get_dig_frontend = dce110_get_dig_frontend1707};1708 1709void dce60_link_encoder_construct(1710 struct dce110_link_encoder *enc110,1711 const struct encoder_init_data *init_data,1712 const struct encoder_feature_support *enc_features,1713 const struct dce110_link_enc_registers *link_regs,1714 const struct dce110_link_enc_aux_registers *aux_regs,1715 const struct dce110_link_enc_hpd_registers *hpd_regs)1716{1717 struct bp_encoder_cap_info bp_cap_info = {0};1718 const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;1719 enum bp_result result = BP_RESULT_OK;1720 1721 enc110->base.funcs = &dce60_lnk_enc_funcs;1722 enc110->base.ctx = init_data->ctx;1723 enc110->base.id = init_data->encoder;1724 1725 enc110->base.hpd_source = init_data->hpd_source;1726 enc110->base.connector = init_data->connector;1727 1728 enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;1729 1730 enc110->base.features = *enc_features;1731 1732 enc110->base.transmitter = init_data->transmitter;1733 1734 /* set the flag to indicate whether driver poll the I2C data pin1735 * while doing the DP sink detect1736 */1737 1738/* if (dal_adapter_service_is_feature_supported(as,1739 FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))1740 enc110->base.features.flags.bits.1741 DP_SINK_DETECT_POLL_DATA_PIN = true;*/1742 1743 enc110->base.output_signals =1744 SIGNAL_TYPE_DVI_SINGLE_LINK |1745 SIGNAL_TYPE_DVI_DUAL_LINK |1746 SIGNAL_TYPE_LVDS |1747 SIGNAL_TYPE_DISPLAY_PORT |1748 SIGNAL_TYPE_DISPLAY_PORT_MST |1749 SIGNAL_TYPE_EDP |1750 SIGNAL_TYPE_HDMI_TYPE_A;1751 1752 /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE.1753 * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY.1754 * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer1755 * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS.1756 * Prefer DIG assignment is decided by board design.1757 * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design1758 * and VBIOS will filter out 7 UNIPHY for DCE 8.0.1759 * By this, adding DIGG should not hurt DCE 8.0.1760 * This will let DCE 8.1 share DCE 8.0 as much as possible1761 */1762 1763 enc110->link_regs = link_regs;1764 enc110->aux_regs = aux_regs;1765 enc110->hpd_regs = hpd_regs;1766 1767 switch (enc110->base.transmitter) {1768 case TRANSMITTER_UNIPHY_A:1769 enc110->base.preferred_engine = ENGINE_ID_DIGA;1770 break;1771 case TRANSMITTER_UNIPHY_B:1772 enc110->base.preferred_engine = ENGINE_ID_DIGB;1773 break;1774 case TRANSMITTER_UNIPHY_C:1775 enc110->base.preferred_engine = ENGINE_ID_DIGC;1776 break;1777 case TRANSMITTER_UNIPHY_D:1778 enc110->base.preferred_engine = ENGINE_ID_DIGD;1779 break;1780 case TRANSMITTER_UNIPHY_E:1781 enc110->base.preferred_engine = ENGINE_ID_DIGE;1782 break;1783 case TRANSMITTER_UNIPHY_F:1784 enc110->base.preferred_engine = ENGINE_ID_DIGF;1785 break;1786 case TRANSMITTER_UNIPHY_G:1787 enc110->base.preferred_engine = ENGINE_ID_DIGG;1788 break;1789 default:1790 ASSERT_CRITICAL(false);1791 enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;1792 }1793 1794 /* default to one to mirror Windows behavior */1795 enc110->base.features.flags.bits.HDMI_6GB_EN = 1;1796 1797 result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios,1798 enc110->base.id, &bp_cap_info);1799 1800 /* Override features with DCE-specific values */1801 if (BP_RESULT_OK == result) {1802 enc110->base.features.flags.bits.IS_HBR2_CAPABLE =1803 bp_cap_info.DP_HBR2_EN;1804 enc110->base.features.flags.bits.IS_HBR3_CAPABLE =1805 bp_cap_info.DP_HBR3_EN;1806 enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;1807 } else {1808 DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",1809 __func__,1810 result);1811 }1812 if (enc110->base.ctx->dc->debug.hdmi20_disable) {1813 enc110->base.features.flags.bits.HDMI_6GB_EN = 0;1814 }1815}1816#endif1817