Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-15 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include "reg_helper.h"
0027 
0028 #include "core_types.h"
0029 #include "link_encoder.h"
0030 #include "dce_link_encoder.h"
0031 #include "stream_encoder.h"
0032 #include "i2caux_interface.h"
0033 #include "dc_bios_types.h"
0034 
0035 #include "gpio_service_interface.h"
0036 
0037 #include "dce/dce_11_0_d.h"
0038 #include "dce/dce_11_0_sh_mask.h"
0039 #include "dce/dce_11_0_enum.h"
0040 
0041 #ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT
0042 #define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT 0xa
0043 #endif
0044 
0045 #ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK
0046 #define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK 0x00000400L
0047 #endif
0048 
0049 #ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK
0050 #define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK  0x10000000L
0051 #endif
0052 
0053 #ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT
0054 #define HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT  0x1c
0055 #endif
0056 
0057 #define CTX \
0058     enc110->base.ctx
0059 #define DC_LOGGER \
0060     enc110->base.ctx->logger
0061 
0062 #define REG(reg)\
0063     (enc110->link_regs->reg)
0064 
0065 #define AUX_REG(reg)\
0066     (enc110->aux_regs->reg)
0067 
0068 #define HPD_REG(reg)\
0069     (enc110->hpd_regs->reg)
0070 
0071 #define DEFAULT_AUX_MAX_DATA_SIZE 16
0072 #define AUX_MAX_DEFER_WRITE_RETRY 20
0073 /*
0074  * @brief
0075  * Trigger Source Select
0076  * ASIC-dependent, actual values for register programming
0077  */
0078 #define DCE110_DIG_FE_SOURCE_SELECT_INVALID 0x0
0079 #define DCE110_DIG_FE_SOURCE_SELECT_DIGA 0x1
0080 #define DCE110_DIG_FE_SOURCE_SELECT_DIGB 0x2
0081 #define DCE110_DIG_FE_SOURCE_SELECT_DIGC 0x4
0082 #define DCE110_DIG_FE_SOURCE_SELECT_DIGD 0x08
0083 #define DCE110_DIG_FE_SOURCE_SELECT_DIGE 0x10
0084 #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20
0085 #define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40
0086 
0087 enum {
0088     DP_MST_UPDATE_MAX_RETRY = 50
0089 };
0090 
0091 #define DIG_REG(reg)\
0092     (reg + enc110->offsets.dig)
0093 
0094 #define DP_REG(reg)\
0095     (reg + enc110->offsets.dp)
0096 
0097 static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
0098     .validate_output_with_stream =
0099         dce110_link_encoder_validate_output_with_stream,
0100     .hw_init = dce110_link_encoder_hw_init,
0101     .setup = dce110_link_encoder_setup,
0102     .enable_tmds_output = dce110_link_encoder_enable_tmds_output,
0103     .enable_dp_output = dce110_link_encoder_enable_dp_output,
0104     .enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output,
0105     .enable_lvds_output = dce110_link_encoder_enable_lvds_output,
0106     .disable_output = dce110_link_encoder_disable_output,
0107     .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,
0108     .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern,
0109     .update_mst_stream_allocation_table =
0110         dce110_link_encoder_update_mst_stream_allocation_table,
0111     .psr_program_dp_dphy_fast_training =
0112             dce110_psr_program_dp_dphy_fast_training,
0113     .psr_program_secondary_packet = dce110_psr_program_secondary_packet,
0114     .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,
0115     .enable_hpd = dce110_link_encoder_enable_hpd,
0116     .disable_hpd = dce110_link_encoder_disable_hpd,
0117     .is_dig_enabled = dce110_is_dig_enabled,
0118     .destroy = dce110_link_encoder_destroy,
0119     .get_max_link_cap = dce110_link_encoder_get_max_link_cap,
0120     .get_dig_frontend = dce110_get_dig_frontend,
0121 };
0122 
0123 static enum bp_result link_transmitter_control(
0124     struct dce110_link_encoder *enc110,
0125     struct bp_transmitter_control *cntl)
0126 {
0127     enum bp_result result;
0128     struct dc_bios *bp = enc110->base.ctx->dc_bios;
0129 
0130     result = bp->funcs->transmitter_control(bp, cntl);
0131 
0132     return result;
0133 }
0134 
0135 static void enable_phy_bypass_mode(
0136     struct dce110_link_encoder *enc110,
0137     bool enable)
0138 {
0139     /* This register resides in DP back end block;
0140      * transmitter is used for the offset */
0141 
0142     REG_UPDATE(DP_DPHY_CNTL, DPHY_BYPASS, enable);
0143 
0144 }
0145 
0146 static void disable_prbs_symbols(
0147     struct dce110_link_encoder *enc110,
0148     bool disable)
0149 {
0150     /* This register resides in DP back end block;
0151      * transmitter is used for the offset */
0152 
0153     REG_UPDATE_4(DP_DPHY_CNTL,
0154             DPHY_ATEST_SEL_LANE0, disable,
0155             DPHY_ATEST_SEL_LANE1, disable,
0156             DPHY_ATEST_SEL_LANE2, disable,
0157             DPHY_ATEST_SEL_LANE3, disable);
0158 }
0159 
0160 static void disable_prbs_mode(
0161     struct dce110_link_encoder *enc110)
0162 {
0163     REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0);
0164 }
0165 
0166 static void program_pattern_symbols(
0167     struct dce110_link_encoder *enc110,
0168     uint16_t pattern_symbols[8])
0169 {
0170     /* This register resides in DP back end block;
0171      * transmitter is used for the offset */
0172 
0173     REG_SET_3(DP_DPHY_SYM0, 0,
0174             DPHY_SYM1, pattern_symbols[0],
0175             DPHY_SYM2, pattern_symbols[1],
0176             DPHY_SYM3, pattern_symbols[2]);
0177 
0178     /* This register resides in DP back end block;
0179      * transmitter is used for the offset */
0180 
0181     REG_SET_3(DP_DPHY_SYM1, 0,
0182             DPHY_SYM4, pattern_symbols[3],
0183             DPHY_SYM5, pattern_symbols[4],
0184             DPHY_SYM6, pattern_symbols[5]);
0185 
0186     /* This register resides in DP back end block;
0187      * transmitter is used for the offset */
0188 
0189     REG_SET_2(DP_DPHY_SYM2, 0,
0190             DPHY_SYM7, pattern_symbols[6],
0191             DPHY_SYM8, pattern_symbols[7]);
0192 }
0193 
0194 static void set_dp_phy_pattern_d102(
0195     struct dce110_link_encoder *enc110)
0196 {
0197     /* Disable PHY Bypass mode to setup the test pattern */
0198     enable_phy_bypass_mode(enc110, false);
0199 
0200     /* For 10-bit PRBS or debug symbols
0201      * please use the following sequence: */
0202 
0203     /* Enable debug symbols on the lanes */
0204 
0205     disable_prbs_symbols(enc110, true);
0206 
0207     /* Disable PRBS mode */
0208     disable_prbs_mode(enc110);
0209 
0210     /* Program debug symbols to be output */
0211     {
0212         uint16_t pattern_symbols[8] = {
0213             0x2AA, 0x2AA, 0x2AA, 0x2AA,
0214             0x2AA, 0x2AA, 0x2AA, 0x2AA
0215         };
0216 
0217         program_pattern_symbols(enc110, pattern_symbols);
0218     }
0219 
0220     /* Enable phy bypass mode to enable the test pattern */
0221 
0222     enable_phy_bypass_mode(enc110, true);
0223 }
0224 
0225 static void set_link_training_complete(
0226     struct dce110_link_encoder *enc110,
0227     bool complete)
0228 {
0229     /* This register resides in DP back end block;
0230      * transmitter is used for the offset */
0231 
0232     REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete);
0233 
0234 }
0235 
0236 unsigned int dce110_get_dig_frontend(struct link_encoder *enc)
0237 {
0238     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
0239     u32 value;
0240     enum engine_id result;
0241 
0242     REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value);
0243 
0244     switch (value) {
0245     case DCE110_DIG_FE_SOURCE_SELECT_DIGA:
0246         result = ENGINE_ID_DIGA;
0247         break;
0248     case DCE110_DIG_FE_SOURCE_SELECT_DIGB:
0249         result = ENGINE_ID_DIGB;
0250         break;
0251     case DCE110_DIG_FE_SOURCE_SELECT_DIGC:
0252         result = ENGINE_ID_DIGC;
0253         break;
0254     case DCE110_DIG_FE_SOURCE_SELECT_DIGD:
0255         result = ENGINE_ID_DIGD;
0256         break;
0257     case DCE110_DIG_FE_SOURCE_SELECT_DIGE:
0258         result = ENGINE_ID_DIGE;
0259         break;
0260     case DCE110_DIG_FE_SOURCE_SELECT_DIGF:
0261         result = ENGINE_ID_DIGF;
0262         break;
0263     case DCE110_DIG_FE_SOURCE_SELECT_DIGG:
0264         result = ENGINE_ID_DIGG;
0265         break;
0266     default:
0267         // invalid source select DIG
0268         result = ENGINE_ID_UNKNOWN;
0269     }
0270 
0271     return result;
0272 }
0273 
0274 void dce110_link_encoder_set_dp_phy_pattern_training_pattern(
0275     struct link_encoder *enc,
0276     uint32_t index)
0277 {
0278     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
0279     /* Write Training Pattern */
0280 
0281     REG_WRITE(DP_DPHY_TRAINING_PATTERN_SEL, index);
0282 
0283     /* Set HW Register Training Complete to false */
0284 
0285     set_link_training_complete(enc110, false);
0286 
0287     /* Disable PHY Bypass mode to output Training Pattern */
0288 
0289     enable_phy_bypass_mode(enc110, false);
0290 
0291     /* Disable PRBS mode */
0292     disable_prbs_mode(enc110);
0293 }
0294 
0295 static void setup_panel_mode(
0296     struct dce110_link_encoder *enc110,
0297     enum dp_panel_mode panel_mode)
0298 {
0299     uint32_t value;
0300     struct dc_context *ctx = enc110->base.ctx;
0301 
0302     /* if psp set panel mode, dal should be program it */
0303     if (ctx->dc->caps.psp_setup_panel_mode)
0304         return;
0305 
0306     ASSERT(REG(DP_DPHY_INTERNAL_CTRL));
0307     value = REG_READ(DP_DPHY_INTERNAL_CTRL);
0308 
0309     switch (panel_mode) {
0310     case DP_PANEL_MODE_EDP:
0311         value = 0x1;
0312         break;
0313     case DP_PANEL_MODE_SPECIAL:
0314         value = 0x11;
0315         break;
0316     default:
0317         value = 0x0;
0318         break;
0319     }
0320 
0321     REG_WRITE(DP_DPHY_INTERNAL_CTRL, value);
0322 }
0323 
0324 static void set_dp_phy_pattern_symbol_error(
0325     struct dce110_link_encoder *enc110)
0326 {
0327     /* Disable PHY Bypass mode to setup the test pattern */
0328     enable_phy_bypass_mode(enc110, false);
0329 
0330     /* program correct panel mode*/
0331     setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);
0332 
0333     /* A PRBS23 pattern is used for most DP electrical measurements. */
0334 
0335     /* Enable PRBS symbols on the lanes */
0336     disable_prbs_symbols(enc110, false);
0337 
0338     /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */
0339     REG_UPDATE_2(DP_DPHY_PRBS_CNTL,
0340             DPHY_PRBS_SEL, 1,
0341             DPHY_PRBS_EN, 1);
0342 
0343     /* Enable phy bypass mode to enable the test pattern */
0344     enable_phy_bypass_mode(enc110, true);
0345 }
0346 
0347 static void set_dp_phy_pattern_prbs7(
0348     struct dce110_link_encoder *enc110)
0349 {
0350     /* Disable PHY Bypass mode to setup the test pattern */
0351     enable_phy_bypass_mode(enc110, false);
0352 
0353     /* A PRBS7 pattern is used for most DP electrical measurements. */
0354 
0355     /* Enable PRBS symbols on the lanes */
0356     disable_prbs_symbols(enc110, false);
0357 
0358     /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */
0359     REG_UPDATE_2(DP_DPHY_PRBS_CNTL,
0360             DPHY_PRBS_SEL, 0,
0361             DPHY_PRBS_EN, 1);
0362 
0363     /* Enable phy bypass mode to enable the test pattern */
0364     enable_phy_bypass_mode(enc110, true);
0365 }
0366 
0367 static void set_dp_phy_pattern_80bit_custom(
0368     struct dce110_link_encoder *enc110,
0369     const uint8_t *pattern)
0370 {
0371     /* Disable PHY Bypass mode to setup the test pattern */
0372     enable_phy_bypass_mode(enc110, false);
0373 
0374     /* Enable debug symbols on the lanes */
0375 
0376     disable_prbs_symbols(enc110, true);
0377 
0378     /* Enable PHY bypass mode to enable the test pattern */
0379     /* TODO is it really needed ? */
0380 
0381     enable_phy_bypass_mode(enc110, true);
0382 
0383     /* Program 80 bit custom pattern */
0384     {
0385         uint16_t pattern_symbols[8];
0386 
0387         pattern_symbols[0] =
0388             ((pattern[1] & 0x03) << 8) | pattern[0];
0389         pattern_symbols[1] =
0390             ((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f);
0391         pattern_symbols[2] =
0392             ((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f);
0393         pattern_symbols[3] =
0394             (pattern[4] << 2) | ((pattern[3] >> 6) & 0x03);
0395         pattern_symbols[4] =
0396             ((pattern[6] & 0x03) << 8) | pattern[5];
0397         pattern_symbols[5] =
0398             ((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f);
0399         pattern_symbols[6] =
0400             ((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f);
0401         pattern_symbols[7] =
0402             (pattern[9] << 2) | ((pattern[8] >> 6) & 0x03);
0403 
0404         program_pattern_symbols(enc110, pattern_symbols);
0405     }
0406 
0407     /* Enable phy bypass mode to enable the test pattern */
0408 
0409     enable_phy_bypass_mode(enc110, true);
0410 }
0411 
0412 static void set_dp_phy_pattern_hbr2_compliance_cp2520_2(
0413     struct dce110_link_encoder *enc110,
0414     unsigned int cp2520_pattern)
0415 {
0416 
0417     /* previously there is a register DP_HBR2_EYE_PATTERN
0418      * that is enabled to get the pattern.
0419      * But it does not work with the latest spec change,
0420      * so we are programming the following registers manually.
0421      *
0422      * The following settings have been confirmed
0423      * by Nick Chorney and Sandra Liu */
0424 
0425     /* Disable PHY Bypass mode to setup the test pattern */
0426 
0427     enable_phy_bypass_mode(enc110, false);
0428 
0429     /* Setup DIG encoder in DP SST mode */
0430     enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT);
0431 
0432     /* ensure normal panel mode. */
0433     setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);
0434 
0435     /* no vbid after BS (SR)
0436      * DP_LINK_FRAMING_CNTL changed history Sandra Liu
0437      * 11000260 / 11000104 / 110000FC */
0438     REG_UPDATE_3(DP_LINK_FRAMING_CNTL,
0439             DP_IDLE_BS_INTERVAL, 0xFC,
0440             DP_VBID_DISABLE, 1,
0441             DP_VID_ENHANCED_FRAME_MODE, 1);
0442 
0443     /* swap every BS with SR */
0444     REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0);
0445 
0446     /* select cp2520 patterns */
0447     if (REG(DP_DPHY_HBR2_PATTERN_CONTROL))
0448         REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL,
0449                 DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern);
0450     else
0451         /* pre-DCE11 can only generate CP2520 pattern 2 */
0452         ASSERT(cp2520_pattern == 2);
0453 
0454     /* set link training complete */
0455     set_link_training_complete(enc110, true);
0456 
0457     /* disable video stream */
0458     REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);
0459 
0460     /* Disable PHY Bypass mode to setup the test pattern */
0461     enable_phy_bypass_mode(enc110, false);
0462 }
0463 
0464 #if defined(CONFIG_DRM_AMD_DC_SI)
0465 static void dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(
0466     struct dce110_link_encoder *enc110,
0467     unsigned int cp2520_pattern)
0468 {
0469 
0470     /* previously there is a register DP_HBR2_EYE_PATTERN
0471      * that is enabled to get the pattern.
0472      * But it does not work with the latest spec change,
0473      * so we are programming the following registers manually.
0474      *
0475      * The following settings have been confirmed
0476      * by Nick Chorney and Sandra Liu */
0477 
0478     /* Disable PHY Bypass mode to setup the test pattern */
0479 
0480     enable_phy_bypass_mode(enc110, false);
0481 
0482     /* Setup DIG encoder in DP SST mode */
0483     enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT);
0484 
0485     /* ensure normal panel mode. */
0486     setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);
0487 
0488     /* no vbid after BS (SR)
0489      * DP_LINK_FRAMING_CNTL changed history Sandra Liu
0490      * 11000260 / 11000104 / 110000FC */
0491     REG_UPDATE_3(DP_LINK_FRAMING_CNTL,
0492             DP_IDLE_BS_INTERVAL, 0xFC,
0493             DP_VBID_DISABLE, 1,
0494             DP_VID_ENHANCED_FRAME_MODE, 1);
0495 
0496     /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip swap BS with SR */
0497 
0498     /* select cp2520 patterns */
0499     if (REG(DP_DPHY_HBR2_PATTERN_CONTROL))
0500         REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL,
0501                 DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern);
0502     else
0503         /* pre-DCE11 can only generate CP2520 pattern 2 */
0504         ASSERT(cp2520_pattern == 2);
0505 
0506     /* set link training complete */
0507     set_link_training_complete(enc110, true);
0508 
0509     /* disable video stream */
0510     REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);
0511 
0512     /* Disable PHY Bypass mode to setup the test pattern */
0513     enable_phy_bypass_mode(enc110, false);
0514 }
0515 #endif
0516 
0517 static void set_dp_phy_pattern_passthrough_mode(
0518     struct dce110_link_encoder *enc110,
0519     enum dp_panel_mode panel_mode)
0520 {
0521     /* program correct panel mode */
0522     setup_panel_mode(enc110, panel_mode);
0523 
0524     /* restore LINK_FRAMING_CNTL and DPHY_SCRAMBLER_BS_COUNT
0525      * in case we were doing HBR2 compliance pattern before
0526      */
0527     REG_UPDATE_3(DP_LINK_FRAMING_CNTL,
0528             DP_IDLE_BS_INTERVAL, 0x2000,
0529             DP_VBID_DISABLE, 0,
0530             DP_VID_ENHANCED_FRAME_MODE, 1);
0531 
0532     REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF);
0533 
0534     /* set link training complete */
0535     set_link_training_complete(enc110, true);
0536 
0537     /* Disable PHY Bypass mode to setup the test pattern */
0538     enable_phy_bypass_mode(enc110, false);
0539 
0540     /* Disable PRBS mode */
0541     disable_prbs_mode(enc110);
0542 }
0543 
0544 #if defined(CONFIG_DRM_AMD_DC_SI)
0545 static void dce60_set_dp_phy_pattern_passthrough_mode(
0546     struct dce110_link_encoder *enc110,
0547     enum dp_panel_mode panel_mode)
0548 {
0549     /* program correct panel mode */
0550     setup_panel_mode(enc110, panel_mode);
0551 
0552     /* restore LINK_FRAMING_CNTL
0553      * in case we were doing HBR2 compliance pattern before
0554      */
0555     REG_UPDATE_3(DP_LINK_FRAMING_CNTL,
0556             DP_IDLE_BS_INTERVAL, 0x2000,
0557             DP_VBID_DISABLE, 0,
0558             DP_VID_ENHANCED_FRAME_MODE, 1);
0559 
0560     /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip DPHY_SCRAMBLER_BS_COUNT restore */
0561 
0562     /* set link training complete */
0563     set_link_training_complete(enc110, true);
0564 
0565     /* Disable PHY Bypass mode to setup the test pattern */
0566     enable_phy_bypass_mode(enc110, false);
0567 
0568     /* Disable PRBS mode */
0569     disable_prbs_mode(enc110);
0570 }
0571 #endif
0572 
0573 /* return value is bit-vector */
0574 static uint8_t get_frontend_source(
0575     enum engine_id engine)
0576 {
0577     switch (engine) {
0578     case ENGINE_ID_DIGA:
0579         return DCE110_DIG_FE_SOURCE_SELECT_DIGA;
0580     case ENGINE_ID_DIGB:
0581         return DCE110_DIG_FE_SOURCE_SELECT_DIGB;
0582     case ENGINE_ID_DIGC:
0583         return DCE110_DIG_FE_SOURCE_SELECT_DIGC;
0584     case ENGINE_ID_DIGD:
0585         return DCE110_DIG_FE_SOURCE_SELECT_DIGD;
0586     case ENGINE_ID_DIGE:
0587         return DCE110_DIG_FE_SOURCE_SELECT_DIGE;
0588     case ENGINE_ID_DIGF:
0589         return DCE110_DIG_FE_SOURCE_SELECT_DIGF;
0590     case ENGINE_ID_DIGG:
0591         return DCE110_DIG_FE_SOURCE_SELECT_DIGG;
0592     default:
0593         ASSERT_CRITICAL(false);
0594         return DCE110_DIG_FE_SOURCE_SELECT_INVALID;
0595     }
0596 }
0597 
0598 static void configure_encoder(
0599     struct dce110_link_encoder *enc110,
0600     const struct dc_link_settings *link_settings)
0601 {
0602     /* set number of lanes */
0603 
0604     REG_SET(DP_CONFIG, 0,
0605             DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE);
0606 
0607     /* setup scrambler */
0608     REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1);
0609 }
0610 
0611 #if defined(CONFIG_DRM_AMD_DC_SI)
0612 static void dce60_configure_encoder(
0613     struct dce110_link_encoder *enc110,
0614     const struct dc_link_settings *link_settings)
0615 {
0616     /* set number of lanes */
0617 
0618     REG_SET(DP_CONFIG, 0,
0619             DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE);
0620 
0621     /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip setup scrambler */
0622 }
0623 #endif
0624 
0625 static void aux_initialize(
0626     struct dce110_link_encoder *enc110)
0627 {
0628     struct dc_context *ctx = enc110->base.ctx;
0629     enum hpd_source_id hpd_source = enc110->base.hpd_source;
0630     uint32_t addr = AUX_REG(AUX_CONTROL);
0631     uint32_t value = dm_read_reg(ctx, addr);
0632 
0633     set_reg_field_value(value, hpd_source, AUX_CONTROL, AUX_HPD_SEL);
0634     set_reg_field_value(value, 0, AUX_CONTROL, AUX_LS_READ_EN);
0635     dm_write_reg(ctx, addr, value);
0636 
0637     addr = AUX_REG(AUX_DPHY_RX_CONTROL0);
0638     value = dm_read_reg(ctx, addr);
0639 
0640     /* 1/4 window (the maximum allowed) */
0641     set_reg_field_value(value, 1,
0642             AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW);
0643     dm_write_reg(ctx, addr, value);
0644 
0645 }
0646 
0647 void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc,
0648             bool exit_link_training_required)
0649 {
0650     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
0651 
0652     if (exit_link_training_required)
0653         REG_UPDATE(DP_DPHY_FAST_TRAINING,
0654                 DPHY_RX_FAST_TRAINING_CAPABLE, 1);
0655     else {
0656         REG_UPDATE(DP_DPHY_FAST_TRAINING,
0657                 DPHY_RX_FAST_TRAINING_CAPABLE, 0);
0658         /*In DCE 11, we are able to pre-program a Force SR register
0659          * to be able to trigger SR symbol after 5 idle patterns
0660          * transmitted. Upon PSR Exit, DMCU can trigger
0661          * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to
0662          * DPHY_LOAD_BS_COUNT_START and the internal counter
0663          * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be
0664          * replaced by SR symbol once.
0665          */
0666 
0667         REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5);
0668     }
0669 }
0670 
0671 void dce110_psr_program_secondary_packet(struct link_encoder *enc,
0672             unsigned int sdp_transmit_line_num_deadline)
0673 {
0674     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
0675 
0676     REG_UPDATE_2(DP_SEC_CNTL1,
0677         DP_SEC_GSP0_LINE_NUM, sdp_transmit_line_num_deadline,
0678         DP_SEC_GSP0_PRIORITY, 1);
0679 }
0680 
0681 bool dce110_is_dig_enabled(struct link_encoder *enc)
0682 {
0683     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
0684     uint32_t value;
0685 
0686     REG_GET(DIG_BE_EN_CNTL, DIG_ENABLE, &value);
0687     return value;
0688 }
0689 
0690 static void link_encoder_disable(struct dce110_link_encoder *enc110)
0691 {
0692     /* reset training pattern */
0693     REG_SET(DP_DPHY_TRAINING_PATTERN_SEL, 0,
0694             DPHY_TRAINING_PATTERN_SEL, 0);
0695 
0696     /* reset training complete */
0697     REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0);
0698 
0699     /* reset panel mode */
0700     setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);
0701 }
0702 
0703 static void hpd_initialize(
0704     struct dce110_link_encoder *enc110)
0705 {
0706     /* Associate HPD with DIG_BE */
0707     enum hpd_source_id hpd_source = enc110->base.hpd_source;
0708 
0709     REG_UPDATE(DIG_BE_CNTL, DIG_HPD_SELECT, hpd_source);
0710 }
0711 
0712 bool dce110_link_encoder_validate_dvi_output(
0713     const struct dce110_link_encoder *enc110,
0714     enum signal_type connector_signal,
0715     enum signal_type signal,
0716     const struct dc_crtc_timing *crtc_timing)
0717 {
0718     uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK;
0719 
0720     if (signal == SIGNAL_TYPE_DVI_DUAL_LINK)
0721         max_pixel_clock *= 2;
0722 
0723     /* This handles the case of HDMI downgrade to DVI we don't want to
0724      * we don't want to cap the pixel clock if the DDI is not DVI.
0725      */
0726     if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK &&
0727             connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
0728         max_pixel_clock = enc110->base.features.max_hdmi_pixel_clock;
0729 
0730     /* DVI only support RGB pixel encoding */
0731     if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB)
0732         return false;
0733 
0734     /*connect DVI via adpater's HDMI connector*/
0735     if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
0736         connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) &&
0737         signal != SIGNAL_TYPE_HDMI_TYPE_A &&
0738         crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10))
0739         return false;
0740     if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10))
0741         return false;
0742 
0743     if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10))
0744         return false;
0745 
0746     /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */
0747     switch (crtc_timing->display_color_depth) {
0748     case COLOR_DEPTH_666:
0749     case COLOR_DEPTH_888:
0750     break;
0751     case COLOR_DEPTH_101010:
0752     case COLOR_DEPTH_161616:
0753         if (signal != SIGNAL_TYPE_DVI_DUAL_LINK)
0754             return false;
0755     break;
0756     default:
0757         return false;
0758     }
0759 
0760     return true;
0761 }
0762 
0763 static bool dce110_link_encoder_validate_hdmi_output(
0764     const struct dce110_link_encoder *enc110,
0765     const struct dc_crtc_timing *crtc_timing,
0766     int adjusted_pix_clk_khz)
0767 {
0768     enum dc_color_depth max_deep_color =
0769             enc110->base.features.max_hdmi_deep_color;
0770 
0771     if (max_deep_color < crtc_timing->display_color_depth)
0772         return false;
0773 
0774     if (crtc_timing->display_color_depth < COLOR_DEPTH_888)
0775         return false;
0776     if (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)
0777         return false;
0778 
0779     if ((adjusted_pix_clk_khz == 0) ||
0780         (adjusted_pix_clk_khz > enc110->base.features.max_hdmi_pixel_clock))
0781         return false;
0782 
0783     /* DCE11 HW does not support 420 */
0784     if (!enc110->base.features.hdmi_ycbcr420_supported &&
0785             crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
0786         return false;
0787 
0788     if ((!enc110->base.features.flags.bits.HDMI_6GB_EN ||
0789             enc110->base.ctx->dc->debug.hdmi20_disable) &&
0790             adjusted_pix_clk_khz >= 300000)
0791         return false;
0792     if (enc110->base.ctx->dc->debug.hdmi20_disable &&
0793         crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
0794         return false;
0795     return true;
0796 }
0797 
0798 bool dce110_link_encoder_validate_dp_output(
0799     const struct dce110_link_encoder *enc110,
0800     const struct dc_crtc_timing *crtc_timing)
0801 {
0802     if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
0803         return false;
0804 
0805     return true;
0806 }
0807 
0808 void dce110_link_encoder_construct(
0809     struct dce110_link_encoder *enc110,
0810     const struct encoder_init_data *init_data,
0811     const struct encoder_feature_support *enc_features,
0812     const struct dce110_link_enc_registers *link_regs,
0813     const struct dce110_link_enc_aux_registers *aux_regs,
0814     const struct dce110_link_enc_hpd_registers *hpd_regs)
0815 {
0816     struct bp_encoder_cap_info bp_cap_info = {0};
0817     const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
0818     enum bp_result result = BP_RESULT_OK;
0819 
0820     enc110->base.funcs = &dce110_lnk_enc_funcs;
0821     enc110->base.ctx = init_data->ctx;
0822     enc110->base.id = init_data->encoder;
0823 
0824     enc110->base.hpd_source = init_data->hpd_source;
0825     enc110->base.connector = init_data->connector;
0826 
0827     enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
0828 
0829     enc110->base.features = *enc_features;
0830 
0831     enc110->base.transmitter = init_data->transmitter;
0832 
0833     /* set the flag to indicate whether driver poll the I2C data pin
0834      * while doing the DP sink detect
0835      */
0836 
0837 /*  if (dal_adapter_service_is_feature_supported(as,
0838         FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))
0839         enc110->base.features.flags.bits.
0840             DP_SINK_DETECT_POLL_DATA_PIN = true;*/
0841 
0842     enc110->base.output_signals =
0843         SIGNAL_TYPE_DVI_SINGLE_LINK |
0844         SIGNAL_TYPE_DVI_DUAL_LINK |
0845         SIGNAL_TYPE_LVDS |
0846         SIGNAL_TYPE_DISPLAY_PORT |
0847         SIGNAL_TYPE_DISPLAY_PORT_MST |
0848         SIGNAL_TYPE_EDP |
0849         SIGNAL_TYPE_HDMI_TYPE_A;
0850 
0851     /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE.
0852      * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY.
0853      * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer
0854      * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS.
0855      * Prefer DIG assignment is decided by board design.
0856      * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design
0857      * and VBIOS will filter out 7 UNIPHY for DCE 8.0.
0858      * By this, adding DIGG should not hurt DCE 8.0.
0859      * This will let DCE 8.1 share DCE 8.0 as much as possible
0860      */
0861 
0862     enc110->link_regs = link_regs;
0863     enc110->aux_regs = aux_regs;
0864     enc110->hpd_regs = hpd_regs;
0865 
0866     switch (enc110->base.transmitter) {
0867     case TRANSMITTER_UNIPHY_A:
0868         enc110->base.preferred_engine = ENGINE_ID_DIGA;
0869     break;
0870     case TRANSMITTER_UNIPHY_B:
0871         enc110->base.preferred_engine = ENGINE_ID_DIGB;
0872     break;
0873     case TRANSMITTER_UNIPHY_C:
0874         enc110->base.preferred_engine = ENGINE_ID_DIGC;
0875     break;
0876     case TRANSMITTER_UNIPHY_D:
0877         enc110->base.preferred_engine = ENGINE_ID_DIGD;
0878     break;
0879     case TRANSMITTER_UNIPHY_E:
0880         enc110->base.preferred_engine = ENGINE_ID_DIGE;
0881     break;
0882     case TRANSMITTER_UNIPHY_F:
0883         enc110->base.preferred_engine = ENGINE_ID_DIGF;
0884     break;
0885     case TRANSMITTER_UNIPHY_G:
0886         enc110->base.preferred_engine = ENGINE_ID_DIGG;
0887     break;
0888     default:
0889         ASSERT_CRITICAL(false);
0890         enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
0891     }
0892 
0893     /* default to one to mirror Windows behavior */
0894     enc110->base.features.flags.bits.HDMI_6GB_EN = 1;
0895 
0896     result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios,
0897                         enc110->base.id, &bp_cap_info);
0898 
0899     /* Override features with DCE-specific values */
0900     if (BP_RESULT_OK == result) {
0901         enc110->base.features.flags.bits.IS_HBR2_CAPABLE =
0902                 bp_cap_info.DP_HBR2_EN;
0903         enc110->base.features.flags.bits.IS_HBR3_CAPABLE =
0904                 bp_cap_info.DP_HBR3_EN;
0905         enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;
0906     } else {
0907         DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
0908                 __func__,
0909                 result);
0910     }
0911     if (enc110->base.ctx->dc->debug.hdmi20_disable) {
0912         enc110->base.features.flags.bits.HDMI_6GB_EN = 0;
0913     }
0914 }
0915 
0916 bool dce110_link_encoder_validate_output_with_stream(
0917     struct link_encoder *enc,
0918     const struct dc_stream_state *stream)
0919 {
0920     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
0921     bool is_valid;
0922 
0923     switch (stream->signal) {
0924     case SIGNAL_TYPE_DVI_SINGLE_LINK:
0925     case SIGNAL_TYPE_DVI_DUAL_LINK:
0926         is_valid = dce110_link_encoder_validate_dvi_output(
0927             enc110,
0928             stream->link->connector_signal,
0929             stream->signal,
0930             &stream->timing);
0931     break;
0932     case SIGNAL_TYPE_HDMI_TYPE_A:
0933         is_valid = dce110_link_encoder_validate_hdmi_output(
0934                 enc110,
0935                 &stream->timing,
0936                 stream->phy_pix_clk);
0937     break;
0938     case SIGNAL_TYPE_DISPLAY_PORT:
0939     case SIGNAL_TYPE_DISPLAY_PORT_MST:
0940         is_valid = dce110_link_encoder_validate_dp_output(
0941                     enc110, &stream->timing);
0942     break;
0943     case SIGNAL_TYPE_EDP:
0944     case SIGNAL_TYPE_LVDS:
0945         is_valid =
0946             (stream->timing.
0947                 pixel_encoding == PIXEL_ENCODING_RGB) ? true : false;
0948     break;
0949     case SIGNAL_TYPE_VIRTUAL:
0950         is_valid = true;
0951         break;
0952     default:
0953         is_valid = false;
0954     break;
0955     }
0956 
0957     return is_valid;
0958 }
0959 
0960 void dce110_link_encoder_hw_init(
0961     struct link_encoder *enc)
0962 {
0963     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
0964     struct bp_transmitter_control cntl = { 0 };
0965     enum bp_result result;
0966 
0967     cntl.action = TRANSMITTER_CONTROL_INIT;
0968     cntl.engine_id = ENGINE_ID_UNKNOWN;
0969     cntl.transmitter = enc110->base.transmitter;
0970     cntl.connector_obj_id = enc110->base.connector;
0971     cntl.lanes_number = LANE_COUNT_FOUR;
0972     cntl.coherent = false;
0973     cntl.hpd_sel = enc110->base.hpd_source;
0974 
0975     if (enc110->base.connector.id == CONNECTOR_ID_EDP)
0976         cntl.signal = SIGNAL_TYPE_EDP;
0977 
0978     result = link_transmitter_control(enc110, &cntl);
0979 
0980     if (result != BP_RESULT_OK) {
0981         DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
0982             __func__);
0983         BREAK_TO_DEBUGGER();
0984         return;
0985     }
0986 
0987     if (enc110->base.connector.id == CONNECTOR_ID_LVDS) {
0988         cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS;
0989 
0990         result = link_transmitter_control(enc110, &cntl);
0991 
0992         ASSERT(result == BP_RESULT_OK);
0993 
0994     }
0995     aux_initialize(enc110);
0996 
0997     /* reinitialize HPD.
0998      * hpd_initialize() will pass DIG_FE id to HW context.
0999      * All other routine within HW context will use fe_engine_offset
1000      * as DIG_FE id even caller pass DIG_FE id.
1001      * So this routine must be called first. */
1002     hpd_initialize(enc110);
1003 }
1004 
1005 void dce110_link_encoder_destroy(struct link_encoder **enc)
1006 {
1007     kfree(TO_DCE110_LINK_ENC(*enc));
1008     *enc = NULL;
1009 }
1010 
1011 void dce110_link_encoder_setup(
1012     struct link_encoder *enc,
1013     enum signal_type signal)
1014 {
1015     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1016 
1017     switch (signal) {
1018     case SIGNAL_TYPE_EDP:
1019     case SIGNAL_TYPE_DISPLAY_PORT:
1020         /* DP SST */
1021         REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 0);
1022         break;
1023     case SIGNAL_TYPE_LVDS:
1024         /* LVDS */
1025         REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 1);
1026         break;
1027     case SIGNAL_TYPE_DVI_SINGLE_LINK:
1028     case SIGNAL_TYPE_DVI_DUAL_LINK:
1029         /* TMDS-DVI */
1030         REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 2);
1031         break;
1032     case SIGNAL_TYPE_HDMI_TYPE_A:
1033         /* TMDS-HDMI */
1034         REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 3);
1035         break;
1036     case SIGNAL_TYPE_DISPLAY_PORT_MST:
1037         /* DP MST */
1038         REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 5);
1039         break;
1040     default:
1041         ASSERT_CRITICAL(false);
1042         /* invalid mode ! */
1043         break;
1044     }
1045 
1046 }
1047 
1048 /* TODO: still need depth or just pass in adjusted pixel clock? */
1049 void dce110_link_encoder_enable_tmds_output(
1050     struct link_encoder *enc,
1051     enum clock_source_id clock_source,
1052     enum dc_color_depth color_depth,
1053     enum signal_type signal,
1054     uint32_t pixel_clock)
1055 {
1056     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1057     struct bp_transmitter_control cntl = { 0 };
1058     enum bp_result result;
1059 
1060     /* Enable the PHY */
1061     cntl.connector_obj_id = enc110->base.connector;
1062     cntl.action = TRANSMITTER_CONTROL_ENABLE;
1063     cntl.engine_id = enc->preferred_engine;
1064     cntl.transmitter = enc110->base.transmitter;
1065     cntl.pll_id = clock_source;
1066     cntl.signal = signal;
1067     if (cntl.signal == SIGNAL_TYPE_DVI_DUAL_LINK)
1068         cntl.lanes_number = 8;
1069     else
1070         cntl.lanes_number = 4;
1071 
1072     cntl.hpd_sel = enc110->base.hpd_source;
1073 
1074     cntl.pixel_clock = pixel_clock;
1075     cntl.color_depth = color_depth;
1076 
1077     result = link_transmitter_control(enc110, &cntl);
1078 
1079     if (result != BP_RESULT_OK) {
1080         DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1081             __func__);
1082         BREAK_TO_DEBUGGER();
1083     }
1084 }
1085 
1086 /* TODO: still need depth or just pass in adjusted pixel clock? */
1087 void dce110_link_encoder_enable_lvds_output(
1088     struct link_encoder *enc,
1089     enum clock_source_id clock_source,
1090     uint32_t pixel_clock)
1091 {
1092     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1093     struct bp_transmitter_control cntl = { 0 };
1094     enum bp_result result;
1095 
1096     /* Enable the PHY */
1097     cntl.connector_obj_id = enc110->base.connector;
1098     cntl.action = TRANSMITTER_CONTROL_ENABLE;
1099     cntl.engine_id = enc->preferred_engine;
1100     cntl.transmitter = enc110->base.transmitter;
1101     cntl.pll_id = clock_source;
1102     cntl.signal = SIGNAL_TYPE_LVDS;
1103     cntl.lanes_number = 4;
1104 
1105     cntl.hpd_sel = enc110->base.hpd_source;
1106 
1107     cntl.pixel_clock = pixel_clock;
1108 
1109     result = link_transmitter_control(enc110, &cntl);
1110 
1111     if (result != BP_RESULT_OK) {
1112         DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1113             __func__);
1114         BREAK_TO_DEBUGGER();
1115     }
1116 }
1117 
1118 /* enables DP PHY output */
1119 void dce110_link_encoder_enable_dp_output(
1120     struct link_encoder *enc,
1121     const struct dc_link_settings *link_settings,
1122     enum clock_source_id clock_source)
1123 {
1124     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1125     struct bp_transmitter_control cntl = { 0 };
1126     enum bp_result result;
1127 
1128     /* Enable the PHY */
1129 
1130     /* number_of_lanes is used for pixel clock adjust,
1131      * but it's not passed to asic_control.
1132      * We need to set number of lanes manually.
1133      */
1134     configure_encoder(enc110, link_settings);
1135     cntl.connector_obj_id = enc110->base.connector;
1136     cntl.action = TRANSMITTER_CONTROL_ENABLE;
1137     cntl.engine_id = enc->preferred_engine;
1138     cntl.transmitter = enc110->base.transmitter;
1139     cntl.pll_id = clock_source;
1140     cntl.signal = SIGNAL_TYPE_DISPLAY_PORT;
1141     cntl.lanes_number = link_settings->lane_count;
1142     cntl.hpd_sel = enc110->base.hpd_source;
1143     cntl.pixel_clock = link_settings->link_rate
1144                         * LINK_RATE_REF_FREQ_IN_KHZ;
1145     /* TODO: check if undefined works */
1146     cntl.color_depth = COLOR_DEPTH_UNDEFINED;
1147 
1148     result = link_transmitter_control(enc110, &cntl);
1149 
1150     if (result != BP_RESULT_OK) {
1151         DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1152             __func__);
1153         BREAK_TO_DEBUGGER();
1154     }
1155 }
1156 
1157 /* enables DP PHY output in MST mode */
1158 void dce110_link_encoder_enable_dp_mst_output(
1159     struct link_encoder *enc,
1160     const struct dc_link_settings *link_settings,
1161     enum clock_source_id clock_source)
1162 {
1163     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1164     struct bp_transmitter_control cntl = { 0 };
1165     enum bp_result result;
1166 
1167     /* Enable the PHY */
1168 
1169     /* number_of_lanes is used for pixel clock adjust,
1170      * but it's not passed to asic_control.
1171      * We need to set number of lanes manually.
1172      */
1173     configure_encoder(enc110, link_settings);
1174 
1175     cntl.action = TRANSMITTER_CONTROL_ENABLE;
1176     cntl.engine_id = ENGINE_ID_UNKNOWN;
1177     cntl.transmitter = enc110->base.transmitter;
1178     cntl.pll_id = clock_source;
1179     cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
1180     cntl.lanes_number = link_settings->lane_count;
1181     cntl.hpd_sel = enc110->base.hpd_source;
1182     cntl.pixel_clock = link_settings->link_rate
1183                         * LINK_RATE_REF_FREQ_IN_KHZ;
1184     /* TODO: check if undefined works */
1185     cntl.color_depth = COLOR_DEPTH_UNDEFINED;
1186 
1187     result = link_transmitter_control(enc110, &cntl);
1188 
1189     if (result != BP_RESULT_OK) {
1190         DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1191             __func__);
1192         BREAK_TO_DEBUGGER();
1193     }
1194 }
1195 
1196 #if defined(CONFIG_DRM_AMD_DC_SI)
1197 /* enables DP PHY output */
1198 static void dce60_link_encoder_enable_dp_output(
1199     struct link_encoder *enc,
1200     const struct dc_link_settings *link_settings,
1201     enum clock_source_id clock_source)
1202 {
1203     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1204     struct bp_transmitter_control cntl = { 0 };
1205     enum bp_result result;
1206 
1207     /* Enable the PHY */
1208 
1209     /* number_of_lanes is used for pixel clock adjust,
1210      * but it's not passed to asic_control.
1211      * We need to set number of lanes manually.
1212      */
1213     dce60_configure_encoder(enc110, link_settings);
1214     cntl.connector_obj_id = enc110->base.connector;
1215     cntl.action = TRANSMITTER_CONTROL_ENABLE;
1216     cntl.engine_id = enc->preferred_engine;
1217     cntl.transmitter = enc110->base.transmitter;
1218     cntl.pll_id = clock_source;
1219     cntl.signal = SIGNAL_TYPE_DISPLAY_PORT;
1220     cntl.lanes_number = link_settings->lane_count;
1221     cntl.hpd_sel = enc110->base.hpd_source;
1222     cntl.pixel_clock = link_settings->link_rate
1223                         * LINK_RATE_REF_FREQ_IN_KHZ;
1224     /* TODO: check if undefined works */
1225     cntl.color_depth = COLOR_DEPTH_UNDEFINED;
1226 
1227     result = link_transmitter_control(enc110, &cntl);
1228 
1229     if (result != BP_RESULT_OK) {
1230         DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1231             __func__);
1232         BREAK_TO_DEBUGGER();
1233     }
1234 }
1235 
1236 /* enables DP PHY output in MST mode */
1237 static void dce60_link_encoder_enable_dp_mst_output(
1238     struct link_encoder *enc,
1239     const struct dc_link_settings *link_settings,
1240     enum clock_source_id clock_source)
1241 {
1242     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1243     struct bp_transmitter_control cntl = { 0 };
1244     enum bp_result result;
1245 
1246     /* Enable the PHY */
1247 
1248     /* number_of_lanes is used for pixel clock adjust,
1249      * but it's not passed to asic_control.
1250      * We need to set number of lanes manually.
1251      */
1252     dce60_configure_encoder(enc110, link_settings);
1253 
1254     cntl.action = TRANSMITTER_CONTROL_ENABLE;
1255     cntl.engine_id = ENGINE_ID_UNKNOWN;
1256     cntl.transmitter = enc110->base.transmitter;
1257     cntl.pll_id = clock_source;
1258     cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
1259     cntl.lanes_number = link_settings->lane_count;
1260     cntl.hpd_sel = enc110->base.hpd_source;
1261     cntl.pixel_clock = link_settings->link_rate
1262                         * LINK_RATE_REF_FREQ_IN_KHZ;
1263     /* TODO: check if undefined works */
1264     cntl.color_depth = COLOR_DEPTH_UNDEFINED;
1265 
1266     result = link_transmitter_control(enc110, &cntl);
1267 
1268     if (result != BP_RESULT_OK) {
1269         DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1270             __func__);
1271         BREAK_TO_DEBUGGER();
1272     }
1273 }
1274 #endif
1275 
1276 /*
1277  * @brief
1278  * Disable transmitter and its encoder
1279  */
1280 void dce110_link_encoder_disable_output(
1281     struct link_encoder *enc,
1282     enum signal_type signal)
1283 {
1284     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1285     struct bp_transmitter_control cntl = { 0 };
1286     enum bp_result result;
1287 
1288     if (!dce110_is_dig_enabled(enc)) {
1289         /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */
1290         return;
1291     }
1292     /* Power-down RX and disable GPU PHY should be paired.
1293      * Disabling PHY without powering down RX may cause
1294      * symbol lock loss, on which we will get DP Sink interrupt. */
1295 
1296     /* There is a case for the DP active dongles
1297      * where we want to disable the PHY but keep RX powered,
1298      * for those we need to ignore DP Sink interrupt
1299      * by checking lane count that has been set
1300      * on the last do_enable_output(). */
1301 
1302     /* disable transmitter */
1303     cntl.action = TRANSMITTER_CONTROL_DISABLE;
1304     cntl.transmitter = enc110->base.transmitter;
1305     cntl.hpd_sel = enc110->base.hpd_source;
1306     cntl.signal = signal;
1307     cntl.connector_obj_id = enc110->base.connector;
1308 
1309     result = link_transmitter_control(enc110, &cntl);
1310 
1311     if (result != BP_RESULT_OK) {
1312         DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1313             __func__);
1314         BREAK_TO_DEBUGGER();
1315         return;
1316     }
1317 
1318     /* disable encoder */
1319     if (dc_is_dp_signal(signal))
1320         link_encoder_disable(enc110);
1321 }
1322 
1323 void dce110_link_encoder_dp_set_lane_settings(
1324     struct link_encoder *enc,
1325     const struct dc_link_settings *link_settings,
1326     const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
1327 {
1328     struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1329     union dpcd_training_lane_set training_lane_set = { { 0 } };
1330     int32_t lane = 0;
1331     struct bp_transmitter_control cntl = { 0 };
1332 
1333     if (!link_settings) {
1334         BREAK_TO_DEBUGGER();
1335         return;
1336     }
1337 
1338     cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;
1339     cntl.transmitter = enc110->base.transmitter;
1340     cntl.connector_obj_id = enc110->base.connector;
1341     cntl.lanes_number = link_settings->lane_count;
1342     cntl.hpd_sel = enc110->base.hpd_source;
1343     cntl.pixel_clock = link_settings->link_rate *
1344                         LINK_RATE_REF_FREQ_IN_KHZ;
1345 
1346     for (lane = 0; lane < link_settings->lane_count; lane++) {
1347         /* translate lane settings */
1348 
1349         training_lane_set.bits.VOLTAGE_SWING_SET =
1350                 lane_settings[lane].VOLTAGE_SWING;
1351         training_lane_set.bits.PRE_EMPHASIS_SET =
1352                 lane_settings[lane].PRE_EMPHASIS;
1353 
1354         /* post cursor 2 setting only applies to HBR2 link rate */
1355         if (link_settings->link_rate == LINK_RATE_HIGH2) {
1356             /* this is passed to VBIOS
1357              * to program post cursor 2 level */
1358 
1359             training_lane_set.bits.POST_CURSOR2_SET =
1360                     lane_settings[lane].POST_CURSOR2;
1361         }
1362 
1363         cntl.lane_select = lane;
1364         cntl.lane_settings = training_lane_set.raw;
1365 
1366         /* call VBIOS table to set voltage swing and pre-emphasis */
1367         link_transmitter_control(enc110, &cntl);
1368     }
1369 }
1370 
1371 /* set DP PHY test and training patterns */
1372 void 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 */
1428 static 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 #endif
1482 
1483 static 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 */
1500 void 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 trigger
1516      * 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 hardware
1581      * making the new allocation active on the DP MST mode link */
1582 
1583 
1584     /* DP_MSE_SAT_UPDATE:
1585      * 0 - No Action
1586      * 1 - Update SAT with trigger
1587      * 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 complete
1593      * (i.e. DP_MSE_SAT_UPDATE field is reset to 0)
1594      * then wait for the transmission
1595      * of at least 16 MTP headers on immediate local link.
1596      * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 0
1597      * a value of 1 indicates that DP MST mode
1598      * is in the 16 MTP keepout region after a VC has been added.
1599      * MST stream bandwidth (VC rate) can be configured
1600      * 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 
1620 void 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         else
1635             field &= ~get_frontend_source(engine);
1636 
1637         REG_UPDATE(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, field);
1638     }
1639 }
1640 
1641 void 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     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 
1655 void 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 
1665 void 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)
1683 static 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_frontend
1707 };
1708 
1709 void 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 pin
1735      * while doing the DP sink detect
1736      */
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 prefer
1755      * 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 design
1758      * 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 possible
1761      */
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 #endif