LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/dce - dce_link_encoder.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 510 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 39 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2012-15 Advanced Micro Devices, Inc.
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included in
      12             :  * all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      17             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      18             :  * 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 OR
      20             :  * OTHER DEALINGS IN THE SOFTWARE.
      21             :  *
      22             :  * Authors: AMD
      23             :  *
      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 "i2caux_interface.h"
      33             : #include "dc_bios_types.h"
      34             : 
      35             : #include "gpio_service_interface.h"
      36             : 
      37             : #include "dce/dce_11_0_d.h"
      38             : #include "dce/dce_11_0_sh_mask.h"
      39             : #include "dce/dce_11_0_enum.h"
      40             : 
      41             : #ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT
      42             : #define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT 0xa
      43             : #endif
      44             : 
      45             : #ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK
      46             : #define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK 0x00000400L
      47             : #endif
      48             : 
      49             : #ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK
      50             : #define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK  0x10000000L
      51             : #endif
      52             : 
      53             : #ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT
      54             : #define HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT  0x1c
      55             : #endif
      56             : 
      57             : #define CTX \
      58             :         enc110->base.ctx
      59             : #define DC_LOGGER \
      60             :         enc110->base.ctx->logger
      61             : 
      62             : #define REG(reg)\
      63             :         (enc110->link_regs->reg)
      64             : 
      65             : #define AUX_REG(reg)\
      66             :         (enc110->aux_regs->reg)
      67             : 
      68             : #define HPD_REG(reg)\
      69             :         (enc110->hpd_regs->reg)
      70             : 
      71             : #define DEFAULT_AUX_MAX_DATA_SIZE 16
      72             : #define AUX_MAX_DEFER_WRITE_RETRY 20
      73             : /*
      74             :  * @brief
      75             :  * Trigger Source Select
      76             :  * ASIC-dependent, actual values for register programming
      77             :  */
      78             : #define DCE110_DIG_FE_SOURCE_SELECT_INVALID 0x0
      79             : #define DCE110_DIG_FE_SOURCE_SELECT_DIGA 0x1
      80             : #define DCE110_DIG_FE_SOURCE_SELECT_DIGB 0x2
      81             : #define DCE110_DIG_FE_SOURCE_SELECT_DIGC 0x4
      82             : #define DCE110_DIG_FE_SOURCE_SELECT_DIGD 0x08
      83             : #define DCE110_DIG_FE_SOURCE_SELECT_DIGE 0x10
      84             : #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20
      85             : #define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40
      86             : 
      87             : enum {
      88             :         DP_MST_UPDATE_MAX_RETRY = 50
      89             : };
      90             : 
      91             : #define DIG_REG(reg)\
      92             :         (reg + enc110->offsets.dig)
      93             : 
      94             : #define DP_REG(reg)\
      95             :         (reg + enc110->offsets.dp)
      96             : 
      97             : static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
      98             :         .validate_output_with_stream =
      99             :                 dce110_link_encoder_validate_output_with_stream,
     100             :         .hw_init = dce110_link_encoder_hw_init,
     101             :         .setup = dce110_link_encoder_setup,
     102             :         .enable_tmds_output = dce110_link_encoder_enable_tmds_output,
     103             :         .enable_dp_output = dce110_link_encoder_enable_dp_output,
     104             :         .enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output,
     105             :         .enable_lvds_output = dce110_link_encoder_enable_lvds_output,
     106             :         .disable_output = dce110_link_encoder_disable_output,
     107             :         .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,
     108             :         .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern,
     109             :         .update_mst_stream_allocation_table =
     110             :                 dce110_link_encoder_update_mst_stream_allocation_table,
     111             :         .psr_program_dp_dphy_fast_training =
     112             :                         dce110_psr_program_dp_dphy_fast_training,
     113             :         .psr_program_secondary_packet = dce110_psr_program_secondary_packet,
     114             :         .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,
     115             :         .enable_hpd = dce110_link_encoder_enable_hpd,
     116             :         .disable_hpd = dce110_link_encoder_disable_hpd,
     117             :         .is_dig_enabled = dce110_is_dig_enabled,
     118             :         .destroy = dce110_link_encoder_destroy,
     119             :         .get_max_link_cap = dce110_link_encoder_get_max_link_cap,
     120             :         .get_dig_frontend = dce110_get_dig_frontend,
     121             : };
     122             : 
     123             : static enum bp_result link_transmitter_control(
     124             :         struct dce110_link_encoder *enc110,
     125             :         struct bp_transmitter_control *cntl)
     126             : {
     127             :         enum bp_result result;
     128           0 :         struct dc_bios *bp = enc110->base.ctx->dc_bios;
     129             : 
     130           0 :         result = bp->funcs->transmitter_control(bp, cntl);
     131             : 
     132             :         return result;
     133             : }
     134             : 
     135             : static void enable_phy_bypass_mode(
     136             :         struct dce110_link_encoder *enc110,
     137             :         bool enable)
     138             : {
     139             :         /* This register resides in DP back end block;
     140             :          * transmitter is used for the offset */
     141             : 
     142           0 :         REG_UPDATE(DP_DPHY_CNTL, DPHY_BYPASS, enable);
     143             : 
     144             : }
     145             : 
     146           0 : static void disable_prbs_symbols(
     147             :         struct dce110_link_encoder *enc110,
     148             :         bool disable)
     149             : {
     150             :         /* This register resides in DP back end block;
     151             :          * transmitter is used for the offset */
     152             : 
     153           0 :         REG_UPDATE_4(DP_DPHY_CNTL,
     154             :                         DPHY_ATEST_SEL_LANE0, disable,
     155             :                         DPHY_ATEST_SEL_LANE1, disable,
     156             :                         DPHY_ATEST_SEL_LANE2, disable,
     157             :                         DPHY_ATEST_SEL_LANE3, disable);
     158           0 : }
     159             : 
     160             : static void disable_prbs_mode(
     161             :         struct dce110_link_encoder *enc110)
     162             : {
     163           0 :         REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0);
     164             : }
     165             : 
     166           0 : static void program_pattern_symbols(
     167             :         struct dce110_link_encoder *enc110,
     168             :         uint16_t pattern_symbols[8])
     169             : {
     170             :         /* This register resides in DP back end block;
     171             :          * transmitter is used for the offset */
     172             : 
     173           0 :         REG_SET_3(DP_DPHY_SYM0, 0,
     174             :                         DPHY_SYM1, pattern_symbols[0],
     175             :                         DPHY_SYM2, pattern_symbols[1],
     176             :                         DPHY_SYM3, pattern_symbols[2]);
     177             : 
     178             :         /* This register resides in DP back end block;
     179             :          * transmitter is used for the offset */
     180             : 
     181           0 :         REG_SET_3(DP_DPHY_SYM1, 0,
     182             :                         DPHY_SYM4, pattern_symbols[3],
     183             :                         DPHY_SYM5, pattern_symbols[4],
     184             :                         DPHY_SYM6, pattern_symbols[5]);
     185             : 
     186             :         /* This register resides in DP back end block;
     187             :          * transmitter is used for the offset */
     188             : 
     189           0 :         REG_SET_2(DP_DPHY_SYM2, 0,
     190             :                         DPHY_SYM7, pattern_symbols[6],
     191             :                         DPHY_SYM8, pattern_symbols[7]);
     192           0 : }
     193             : 
     194           0 : static void set_dp_phy_pattern_d102(
     195             :         struct dce110_link_encoder *enc110)
     196             : {
     197             :         /* Disable PHY Bypass mode to setup the test pattern */
     198           0 :         enable_phy_bypass_mode(enc110, false);
     199             : 
     200             :         /* For 10-bit PRBS or debug symbols
     201             :          * please use the following sequence: */
     202             : 
     203             :         /* Enable debug symbols on the lanes */
     204             : 
     205           0 :         disable_prbs_symbols(enc110, true);
     206             : 
     207             :         /* Disable PRBS mode */
     208           0 :         disable_prbs_mode(enc110);
     209             : 
     210             :         /* Program debug symbols to be output */
     211             :         {
     212           0 :                 uint16_t pattern_symbols[8] = {
     213             :                         0x2AA, 0x2AA, 0x2AA, 0x2AA,
     214             :                         0x2AA, 0x2AA, 0x2AA, 0x2AA
     215             :                 };
     216             : 
     217           0 :                 program_pattern_symbols(enc110, pattern_symbols);
     218             :         }
     219             : 
     220             :         /* Enable phy bypass mode to enable the test pattern */
     221             : 
     222           0 :         enable_phy_bypass_mode(enc110, true);
     223           0 : }
     224             : 
     225             : static void set_link_training_complete(
     226             :         struct dce110_link_encoder *enc110,
     227             :         bool complete)
     228             : {
     229             :         /* This register resides in DP back end block;
     230             :          * transmitter is used for the offset */
     231             : 
     232           0 :         REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete);
     233             : 
     234             : }
     235             : 
     236           0 : unsigned int dce110_get_dig_frontend(struct link_encoder *enc)
     237             : {
     238           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
     239             :         u32 value;
     240             :         enum engine_id result;
     241             : 
     242           0 :         REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value);
     243             : 
     244           0 :         switch (value) {
     245             :         case DCE110_DIG_FE_SOURCE_SELECT_DIGA:
     246             :                 result = ENGINE_ID_DIGA;
     247             :                 break;
     248             :         case DCE110_DIG_FE_SOURCE_SELECT_DIGB:
     249           0 :                 result = ENGINE_ID_DIGB;
     250           0 :                 break;
     251             :         case DCE110_DIG_FE_SOURCE_SELECT_DIGC:
     252           0 :                 result = ENGINE_ID_DIGC;
     253           0 :                 break;
     254             :         case DCE110_DIG_FE_SOURCE_SELECT_DIGD:
     255           0 :                 result = ENGINE_ID_DIGD;
     256           0 :                 break;
     257             :         case DCE110_DIG_FE_SOURCE_SELECT_DIGE:
     258           0 :                 result = ENGINE_ID_DIGE;
     259           0 :                 break;
     260             :         case DCE110_DIG_FE_SOURCE_SELECT_DIGF:
     261           0 :                 result = ENGINE_ID_DIGF;
     262           0 :                 break;
     263             :         case DCE110_DIG_FE_SOURCE_SELECT_DIGG:
     264           0 :                 result = ENGINE_ID_DIGG;
     265           0 :                 break;
     266             :         default:
     267             :                 // invalid source select DIG
     268           0 :                 result = ENGINE_ID_UNKNOWN;
     269             :         }
     270             : 
     271           0 :         return result;
     272             : }
     273             : 
     274           0 : void dce110_link_encoder_set_dp_phy_pattern_training_pattern(
     275             :         struct link_encoder *enc,
     276             :         uint32_t index)
     277             : {
     278           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
     279             :         /* Write Training Pattern */
     280             : 
     281           0 :         REG_WRITE(DP_DPHY_TRAINING_PATTERN_SEL, index);
     282             : 
     283             :         /* Set HW Register Training Complete to false */
     284             : 
     285           0 :         set_link_training_complete(enc110, false);
     286             : 
     287             :         /* Disable PHY Bypass mode to output Training Pattern */
     288             : 
     289           0 :         enable_phy_bypass_mode(enc110, false);
     290             : 
     291             :         /* Disable PRBS mode */
     292           0 :         disable_prbs_mode(enc110);
     293           0 : }
     294             : 
     295           0 : static void setup_panel_mode(
     296             :         struct dce110_link_encoder *enc110,
     297             :         enum dp_panel_mode panel_mode)
     298             : {
     299             :         uint32_t value;
     300           0 :         struct dc_context *ctx = enc110->base.ctx;
     301             : 
     302             :         /* if psp set panel mode, dal should be program it */
     303           0 :         if (ctx->dc->caps.psp_setup_panel_mode)
     304             :                 return;
     305             : 
     306           0 :         ASSERT(REG(DP_DPHY_INTERNAL_CTRL));
     307           0 :         value = REG_READ(DP_DPHY_INTERNAL_CTRL);
     308             : 
     309           0 :         switch (panel_mode) {
     310             :         case DP_PANEL_MODE_EDP:
     311             :                 value = 0x1;
     312             :                 break;
     313             :         case DP_PANEL_MODE_SPECIAL:
     314           0 :                 value = 0x11;
     315             :                 break;
     316             :         default:
     317           0 :                 value = 0x0;
     318             :                 break;
     319             :         }
     320             : 
     321           0 :         REG_WRITE(DP_DPHY_INTERNAL_CTRL, value);
     322             : }
     323             : 
     324           0 : static void set_dp_phy_pattern_symbol_error(
     325             :         struct dce110_link_encoder *enc110)
     326             : {
     327             :         /* Disable PHY Bypass mode to setup the test pattern */
     328           0 :         enable_phy_bypass_mode(enc110, false);
     329             : 
     330             :         /* program correct panel mode*/
     331           0 :         setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);
     332             : 
     333             :         /* A PRBS23 pattern is used for most DP electrical measurements. */
     334             : 
     335             :         /* Enable PRBS symbols on the lanes */
     336           0 :         disable_prbs_symbols(enc110, false);
     337             : 
     338             :         /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */
     339           0 :         REG_UPDATE_2(DP_DPHY_PRBS_CNTL,
     340             :                         DPHY_PRBS_SEL, 1,
     341             :                         DPHY_PRBS_EN, 1);
     342             : 
     343             :         /* Enable phy bypass mode to enable the test pattern */
     344           0 :         enable_phy_bypass_mode(enc110, true);
     345           0 : }
     346             : 
     347           0 : static void set_dp_phy_pattern_prbs7(
     348             :         struct dce110_link_encoder *enc110)
     349             : {
     350             :         /* Disable PHY Bypass mode to setup the test pattern */
     351           0 :         enable_phy_bypass_mode(enc110, false);
     352             : 
     353             :         /* A PRBS7 pattern is used for most DP electrical measurements. */
     354             : 
     355             :         /* Enable PRBS symbols on the lanes */
     356           0 :         disable_prbs_symbols(enc110, false);
     357             : 
     358             :         /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */
     359           0 :         REG_UPDATE_2(DP_DPHY_PRBS_CNTL,
     360             :                         DPHY_PRBS_SEL, 0,
     361             :                         DPHY_PRBS_EN, 1);
     362             : 
     363             :         /* Enable phy bypass mode to enable the test pattern */
     364           0 :         enable_phy_bypass_mode(enc110, true);
     365           0 : }
     366             : 
     367           0 : static void set_dp_phy_pattern_80bit_custom(
     368             :         struct dce110_link_encoder *enc110,
     369             :         const uint8_t *pattern)
     370             : {
     371             :         /* Disable PHY Bypass mode to setup the test pattern */
     372           0 :         enable_phy_bypass_mode(enc110, false);
     373             : 
     374             :         /* Enable debug symbols on the lanes */
     375             : 
     376           0 :         disable_prbs_symbols(enc110, true);
     377             : 
     378             :         /* Enable PHY bypass mode to enable the test pattern */
     379             :         /* TODO is it really needed ? */
     380             : 
     381           0 :         enable_phy_bypass_mode(enc110, true);
     382             : 
     383             :         /* Program 80 bit custom pattern */
     384             :         {
     385             :                 uint16_t pattern_symbols[8];
     386             : 
     387           0 :                 pattern_symbols[0] =
     388           0 :                         ((pattern[1] & 0x03) << 8) | pattern[0];
     389           0 :                 pattern_symbols[1] =
     390           0 :                         ((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f);
     391           0 :                 pattern_symbols[2] =
     392           0 :                         ((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f);
     393           0 :                 pattern_symbols[3] =
     394           0 :                         (pattern[4] << 2) | ((pattern[3] >> 6) & 0x03);
     395           0 :                 pattern_symbols[4] =
     396           0 :                         ((pattern[6] & 0x03) << 8) | pattern[5];
     397           0 :                 pattern_symbols[5] =
     398           0 :                         ((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f);
     399           0 :                 pattern_symbols[6] =
     400           0 :                         ((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f);
     401           0 :                 pattern_symbols[7] =
     402           0 :                         (pattern[9] << 2) | ((pattern[8] >> 6) & 0x03);
     403             : 
     404           0 :                 program_pattern_symbols(enc110, pattern_symbols);
     405             :         }
     406             : 
     407             :         /* Enable phy bypass mode to enable the test pattern */
     408             : 
     409           0 :         enable_phy_bypass_mode(enc110, true);
     410           0 : }
     411             : 
     412           0 : static void set_dp_phy_pattern_hbr2_compliance_cp2520_2(
     413             :         struct dce110_link_encoder *enc110,
     414             :         unsigned int cp2520_pattern)
     415             : {
     416             : 
     417             :         /* previously there is a register DP_HBR2_EYE_PATTERN
     418             :          * that is enabled to get the pattern.
     419             :          * But it does not work with the latest spec change,
     420             :          * so we are programming the following registers manually.
     421             :          *
     422             :          * The following settings have been confirmed
     423             :          * by Nick Chorney and Sandra Liu */
     424             : 
     425             :         /* Disable PHY Bypass mode to setup the test pattern */
     426             : 
     427           0 :         enable_phy_bypass_mode(enc110, false);
     428             : 
     429             :         /* Setup DIG encoder in DP SST mode */
     430           0 :         enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT);
     431             : 
     432             :         /* ensure normal panel mode. */
     433           0 :         setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);
     434             : 
     435             :         /* no vbid after BS (SR)
     436             :          * DP_LINK_FRAMING_CNTL changed history Sandra Liu
     437             :          * 11000260 / 11000104 / 110000FC */
     438           0 :         REG_UPDATE_3(DP_LINK_FRAMING_CNTL,
     439             :                         DP_IDLE_BS_INTERVAL, 0xFC,
     440             :                         DP_VBID_DISABLE, 1,
     441             :                         DP_VID_ENHANCED_FRAME_MODE, 1);
     442             : 
     443             :         /* swap every BS with SR */
     444           0 :         REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0);
     445             : 
     446             :         /* select cp2520 patterns */
     447           0 :         if (REG(DP_DPHY_HBR2_PATTERN_CONTROL))
     448           0 :                 REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL,
     449             :                                 DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern);
     450             :         else
     451             :                 /* pre-DCE11 can only generate CP2520 pattern 2 */
     452           0 :                 ASSERT(cp2520_pattern == 2);
     453             : 
     454             :         /* set link training complete */
     455           0 :         set_link_training_complete(enc110, true);
     456             : 
     457             :         /* disable video stream */
     458           0 :         REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);
     459             : 
     460             :         /* Disable PHY Bypass mode to setup the test pattern */
     461           0 :         enable_phy_bypass_mode(enc110, false);
     462           0 : }
     463             : 
     464             : #if defined(CONFIG_DRM_AMD_DC_SI)
     465             : static void dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(
     466             :         struct dce110_link_encoder *enc110,
     467             :         unsigned int cp2520_pattern)
     468             : {
     469             : 
     470             :         /* previously there is a register DP_HBR2_EYE_PATTERN
     471             :          * that is enabled to get the pattern.
     472             :          * But it does not work with the latest spec change,
     473             :          * so we are programming the following registers manually.
     474             :          *
     475             :          * The following settings have been confirmed
     476             :          * by Nick Chorney and Sandra Liu */
     477             : 
     478             :         /* Disable PHY Bypass mode to setup the test pattern */
     479             : 
     480             :         enable_phy_bypass_mode(enc110, false);
     481             : 
     482             :         /* Setup DIG encoder in DP SST mode */
     483             :         enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT);
     484             : 
     485             :         /* ensure normal panel mode. */
     486             :         setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);
     487             : 
     488             :         /* no vbid after BS (SR)
     489             :          * DP_LINK_FRAMING_CNTL changed history Sandra Liu
     490             :          * 11000260 / 11000104 / 110000FC */
     491             :         REG_UPDATE_3(DP_LINK_FRAMING_CNTL,
     492             :                         DP_IDLE_BS_INTERVAL, 0xFC,
     493             :                         DP_VBID_DISABLE, 1,
     494             :                         DP_VID_ENHANCED_FRAME_MODE, 1);
     495             : 
     496             :         /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip swap BS with SR */
     497             : 
     498             :         /* select cp2520 patterns */
     499             :         if (REG(DP_DPHY_HBR2_PATTERN_CONTROL))
     500             :                 REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL,
     501             :                                 DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern);
     502             :         else
     503             :                 /* pre-DCE11 can only generate CP2520 pattern 2 */
     504             :                 ASSERT(cp2520_pattern == 2);
     505             : 
     506             :         /* set link training complete */
     507             :         set_link_training_complete(enc110, true);
     508             : 
     509             :         /* disable video stream */
     510             :         REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);
     511             : 
     512             :         /* Disable PHY Bypass mode to setup the test pattern */
     513             :         enable_phy_bypass_mode(enc110, false);
     514             : }
     515             : #endif
     516             : 
     517           0 : static void set_dp_phy_pattern_passthrough_mode(
     518             :         struct dce110_link_encoder *enc110,
     519             :         enum dp_panel_mode panel_mode)
     520             : {
     521             :         /* program correct panel mode */
     522           0 :         setup_panel_mode(enc110, panel_mode);
     523             : 
     524             :         /* restore LINK_FRAMING_CNTL and DPHY_SCRAMBLER_BS_COUNT
     525             :          * in case we were doing HBR2 compliance pattern before
     526             :          */
     527           0 :         REG_UPDATE_3(DP_LINK_FRAMING_CNTL,
     528             :                         DP_IDLE_BS_INTERVAL, 0x2000,
     529             :                         DP_VBID_DISABLE, 0,
     530             :                         DP_VID_ENHANCED_FRAME_MODE, 1);
     531             : 
     532           0 :         REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF);
     533             : 
     534             :         /* set link training complete */
     535           0 :         set_link_training_complete(enc110, true);
     536             : 
     537             :         /* Disable PHY Bypass mode to setup the test pattern */
     538           0 :         enable_phy_bypass_mode(enc110, false);
     539             : 
     540             :         /* Disable PRBS mode */
     541           0 :         disable_prbs_mode(enc110);
     542           0 : }
     543             : 
     544             : #if defined(CONFIG_DRM_AMD_DC_SI)
     545             : static void dce60_set_dp_phy_pattern_passthrough_mode(
     546             :         struct dce110_link_encoder *enc110,
     547             :         enum dp_panel_mode panel_mode)
     548             : {
     549             :         /* program correct panel mode */
     550             :         setup_panel_mode(enc110, panel_mode);
     551             : 
     552             :         /* restore LINK_FRAMING_CNTL
     553             :          * in case we were doing HBR2 compliance pattern before
     554             :          */
     555             :         REG_UPDATE_3(DP_LINK_FRAMING_CNTL,
     556             :                         DP_IDLE_BS_INTERVAL, 0x2000,
     557             :                         DP_VBID_DISABLE, 0,
     558             :                         DP_VID_ENHANCED_FRAME_MODE, 1);
     559             : 
     560             :         /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip DPHY_SCRAMBLER_BS_COUNT restore */
     561             : 
     562             :         /* set link training complete */
     563             :         set_link_training_complete(enc110, true);
     564             : 
     565             :         /* Disable PHY Bypass mode to setup the test pattern */
     566             :         enable_phy_bypass_mode(enc110, false);
     567             : 
     568             :         /* Disable PRBS mode */
     569             :         disable_prbs_mode(enc110);
     570             : }
     571             : #endif
     572             : 
     573             : /* return value is bit-vector */
     574           0 : static uint8_t get_frontend_source(
     575             :         enum engine_id engine)
     576             : {
     577           0 :         switch (engine) {
     578             :         case ENGINE_ID_DIGA:
     579             :                 return DCE110_DIG_FE_SOURCE_SELECT_DIGA;
     580             :         case ENGINE_ID_DIGB:
     581           0 :                 return DCE110_DIG_FE_SOURCE_SELECT_DIGB;
     582             :         case ENGINE_ID_DIGC:
     583           0 :                 return DCE110_DIG_FE_SOURCE_SELECT_DIGC;
     584             :         case ENGINE_ID_DIGD:
     585           0 :                 return DCE110_DIG_FE_SOURCE_SELECT_DIGD;
     586             :         case ENGINE_ID_DIGE:
     587           0 :                 return DCE110_DIG_FE_SOURCE_SELECT_DIGE;
     588             :         case ENGINE_ID_DIGF:
     589           0 :                 return DCE110_DIG_FE_SOURCE_SELECT_DIGF;
     590             :         case ENGINE_ID_DIGG:
     591           0 :                 return DCE110_DIG_FE_SOURCE_SELECT_DIGG;
     592             :         default:
     593           0 :                 ASSERT_CRITICAL(false);
     594           0 :                 return DCE110_DIG_FE_SOURCE_SELECT_INVALID;
     595             :         }
     596             : }
     597             : 
     598           0 : static void configure_encoder(
     599             :         struct dce110_link_encoder *enc110,
     600             :         const struct dc_link_settings *link_settings)
     601             : {
     602             :         /* set number of lanes */
     603             : 
     604           0 :         REG_SET(DP_CONFIG, 0,
     605             :                         DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE);
     606             : 
     607             :         /* setup scrambler */
     608           0 :         REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1);
     609           0 : }
     610             : 
     611             : #if defined(CONFIG_DRM_AMD_DC_SI)
     612             : static void dce60_configure_encoder(
     613             :         struct dce110_link_encoder *enc110,
     614             :         const struct dc_link_settings *link_settings)
     615             : {
     616             :         /* set number of lanes */
     617             : 
     618             :         REG_SET(DP_CONFIG, 0,
     619             :                         DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE);
     620             : 
     621             :         /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip setup scrambler */
     622             : }
     623             : #endif
     624             : 
     625           0 : static void aux_initialize(
     626             :         struct dce110_link_encoder *enc110)
     627             : {
     628           0 :         struct dc_context *ctx = enc110->base.ctx;
     629           0 :         enum hpd_source_id hpd_source = enc110->base.hpd_source;
     630           0 :         uint32_t addr = AUX_REG(AUX_CONTROL);
     631           0 :         uint32_t value = dm_read_reg(ctx, addr);
     632             : 
     633           0 :         set_reg_field_value(value, hpd_source, AUX_CONTROL, AUX_HPD_SEL);
     634           0 :         set_reg_field_value(value, 0, AUX_CONTROL, AUX_LS_READ_EN);
     635           0 :         dm_write_reg(ctx, addr, value);
     636             : 
     637           0 :         addr = AUX_REG(AUX_DPHY_RX_CONTROL0);
     638           0 :         value = dm_read_reg(ctx, addr);
     639             : 
     640             :         /* 1/4 window (the maximum allowed) */
     641           0 :         set_reg_field_value(value, 1,
     642             :                         AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW);
     643           0 :         dm_write_reg(ctx, addr, value);
     644             : 
     645           0 : }
     646             : 
     647           0 : void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc,
     648             :                         bool exit_link_training_required)
     649             : {
     650           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
     651             : 
     652           0 :         if (exit_link_training_required)
     653           0 :                 REG_UPDATE(DP_DPHY_FAST_TRAINING,
     654             :                                 DPHY_RX_FAST_TRAINING_CAPABLE, 1);
     655             :         else {
     656           0 :                 REG_UPDATE(DP_DPHY_FAST_TRAINING,
     657             :                                 DPHY_RX_FAST_TRAINING_CAPABLE, 0);
     658             :                 /*In DCE 11, we are able to pre-program a Force SR register
     659             :                  * to be able to trigger SR symbol after 5 idle patterns
     660             :                  * transmitted. Upon PSR Exit, DMCU can trigger
     661             :                  * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to
     662             :                  * DPHY_LOAD_BS_COUNT_START and the internal counter
     663             :                  * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be
     664             :                  * replaced by SR symbol once.
     665             :                  */
     666             : 
     667           0 :                 REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5);
     668             :         }
     669           0 : }
     670             : 
     671           0 : void dce110_psr_program_secondary_packet(struct link_encoder *enc,
     672             :                         unsigned int sdp_transmit_line_num_deadline)
     673             : {
     674           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
     675             : 
     676           0 :         REG_UPDATE_2(DP_SEC_CNTL1,
     677             :                 DP_SEC_GSP0_LINE_NUM, sdp_transmit_line_num_deadline,
     678             :                 DP_SEC_GSP0_PRIORITY, 1);
     679           0 : }
     680             : 
     681           0 : bool dce110_is_dig_enabled(struct link_encoder *enc)
     682             : {
     683           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
     684             :         uint32_t value;
     685             : 
     686           0 :         REG_GET(DIG_BE_EN_CNTL, DIG_ENABLE, &value);
     687           0 :         return value;
     688             : }
     689             : 
     690           0 : static void link_encoder_disable(struct dce110_link_encoder *enc110)
     691             : {
     692             :         /* reset training pattern */
     693           0 :         REG_SET(DP_DPHY_TRAINING_PATTERN_SEL, 0,
     694             :                         DPHY_TRAINING_PATTERN_SEL, 0);
     695             : 
     696             :         /* reset training complete */
     697           0 :         REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0);
     698             : 
     699             :         /* reset panel mode */
     700           0 :         setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);
     701           0 : }
     702             : 
     703           0 : static void hpd_initialize(
     704             :         struct dce110_link_encoder *enc110)
     705             : {
     706             :         /* Associate HPD with DIG_BE */
     707           0 :         enum hpd_source_id hpd_source = enc110->base.hpd_source;
     708             : 
     709           0 :         REG_UPDATE(DIG_BE_CNTL, DIG_HPD_SELECT, hpd_source);
     710           0 : }
     711             : 
     712           0 : bool dce110_link_encoder_validate_dvi_output(
     713             :         const struct dce110_link_encoder *enc110,
     714             :         enum signal_type connector_signal,
     715             :         enum signal_type signal,
     716             :         const struct dc_crtc_timing *crtc_timing)
     717             : {
     718           0 :         uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK;
     719             : 
     720           0 :         if (signal == SIGNAL_TYPE_DVI_DUAL_LINK)
     721           0 :                 max_pixel_clock *= 2;
     722             : 
     723             :         /* This handles the case of HDMI downgrade to DVI we don't want to
     724             :          * we don't want to cap the pixel clock if the DDI is not DVI.
     725             :          */
     726           0 :         if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK &&
     727             :                         connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
     728           0 :                 max_pixel_clock = enc110->base.features.max_hdmi_pixel_clock;
     729             : 
     730             :         /* DVI only support RGB pixel encoding */
     731           0 :         if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB)
     732             :                 return false;
     733             : 
     734             :         /*connect DVI via adpater's HDMI connector*/
     735           0 :         if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
     736           0 :                 connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) &&
     737           0 :                 signal != SIGNAL_TYPE_HDMI_TYPE_A &&
     738           0 :                 crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10))
     739             :                 return false;
     740           0 :         if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10))
     741             :                 return false;
     742             : 
     743           0 :         if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10))
     744             :                 return false;
     745             : 
     746             :         /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */
     747           0 :         switch (crtc_timing->display_color_depth) {
     748             :         case COLOR_DEPTH_666:
     749             :         case COLOR_DEPTH_888:
     750             :         break;
     751             :         case COLOR_DEPTH_101010:
     752             :         case COLOR_DEPTH_161616:
     753           0 :                 if (signal != SIGNAL_TYPE_DVI_DUAL_LINK)
     754             :                         return false;
     755             :         break;
     756             :         default:
     757             :                 return false;
     758             :         }
     759             : 
     760           0 :         return true;
     761             : }
     762             : 
     763           0 : static bool dce110_link_encoder_validate_hdmi_output(
     764             :         const struct dce110_link_encoder *enc110,
     765             :         const struct dc_crtc_timing *crtc_timing,
     766             :         int adjusted_pix_clk_khz)
     767             : {
     768           0 :         enum dc_color_depth max_deep_color =
     769             :                         enc110->base.features.max_hdmi_deep_color;
     770             : 
     771           0 :         if (max_deep_color < crtc_timing->display_color_depth)
     772             :                 return false;
     773             : 
     774           0 :         if (crtc_timing->display_color_depth < COLOR_DEPTH_888)
     775             :                 return false;
     776           0 :         if (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)
     777             :                 return false;
     778             : 
     779           0 :         if ((adjusted_pix_clk_khz == 0) ||
     780           0 :                 (adjusted_pix_clk_khz > enc110->base.features.max_hdmi_pixel_clock))
     781             :                 return false;
     782             : 
     783             :         /* DCE11 HW does not support 420 */
     784           0 :         if (!enc110->base.features.hdmi_ycbcr420_supported &&
     785           0 :                         crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
     786             :                 return false;
     787             : 
     788           0 :         if ((!enc110->base.features.flags.bits.HDMI_6GB_EN ||
     789           0 :                         enc110->base.ctx->dc->debug.hdmi20_disable) &&
     790             :                         adjusted_pix_clk_khz >= 300000)
     791             :                 return false;
     792           0 :         if (enc110->base.ctx->dc->debug.hdmi20_disable &&
     793           0 :                 crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
     794             :                 return false;
     795             :         return true;
     796             : }
     797             : 
     798           0 : bool dce110_link_encoder_validate_dp_output(
     799             :         const struct dce110_link_encoder *enc110,
     800             :         const struct dc_crtc_timing *crtc_timing)
     801             : {
     802           0 :         if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
     803             :                 return false;
     804             : 
     805           0 :         return true;
     806             : }
     807             : 
     808           0 : void dce110_link_encoder_construct(
     809             :         struct dce110_link_encoder *enc110,
     810             :         const struct encoder_init_data *init_data,
     811             :         const struct encoder_feature_support *enc_features,
     812             :         const struct dce110_link_enc_registers *link_regs,
     813             :         const struct dce110_link_enc_aux_registers *aux_regs,
     814             :         const struct dce110_link_enc_hpd_registers *hpd_regs)
     815             : {
     816           0 :         struct bp_encoder_cap_info bp_cap_info = {0};
     817           0 :         const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
     818           0 :         enum bp_result result = BP_RESULT_OK;
     819             : 
     820           0 :         enc110->base.funcs = &dce110_lnk_enc_funcs;
     821           0 :         enc110->base.ctx = init_data->ctx;
     822           0 :         enc110->base.id = init_data->encoder;
     823             : 
     824           0 :         enc110->base.hpd_source = init_data->hpd_source;
     825           0 :         enc110->base.connector = init_data->connector;
     826             : 
     827           0 :         enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
     828             : 
     829           0 :         enc110->base.features = *enc_features;
     830             : 
     831           0 :         enc110->base.transmitter = init_data->transmitter;
     832             : 
     833             :         /* set the flag to indicate whether driver poll the I2C data pin
     834             :          * while doing the DP sink detect
     835             :          */
     836             : 
     837             : /*      if (dal_adapter_service_is_feature_supported(as,
     838             :                 FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))
     839             :                 enc110->base.features.flags.bits.
     840             :                         DP_SINK_DETECT_POLL_DATA_PIN = true;*/
     841             : 
     842           0 :         enc110->base.output_signals =
     843             :                 SIGNAL_TYPE_DVI_SINGLE_LINK |
     844             :                 SIGNAL_TYPE_DVI_DUAL_LINK |
     845             :                 SIGNAL_TYPE_LVDS |
     846             :                 SIGNAL_TYPE_DISPLAY_PORT |
     847             :                 SIGNAL_TYPE_DISPLAY_PORT_MST |
     848             :                 SIGNAL_TYPE_EDP |
     849             :                 SIGNAL_TYPE_HDMI_TYPE_A;
     850             : 
     851             :         /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE.
     852             :          * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY.
     853             :          * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer
     854             :          * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS.
     855             :          * Prefer DIG assignment is decided by board design.
     856             :          * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design
     857             :          * and VBIOS will filter out 7 UNIPHY for DCE 8.0.
     858             :          * By this, adding DIGG should not hurt DCE 8.0.
     859             :          * This will let DCE 8.1 share DCE 8.0 as much as possible
     860             :          */
     861             : 
     862           0 :         enc110->link_regs = link_regs;
     863           0 :         enc110->aux_regs = aux_regs;
     864           0 :         enc110->hpd_regs = hpd_regs;
     865             : 
     866           0 :         switch (enc110->base.transmitter) {
     867             :         case TRANSMITTER_UNIPHY_A:
     868           0 :                 enc110->base.preferred_engine = ENGINE_ID_DIGA;
     869           0 :         break;
     870             :         case TRANSMITTER_UNIPHY_B:
     871           0 :                 enc110->base.preferred_engine = ENGINE_ID_DIGB;
     872           0 :         break;
     873             :         case TRANSMITTER_UNIPHY_C:
     874           0 :                 enc110->base.preferred_engine = ENGINE_ID_DIGC;
     875           0 :         break;
     876             :         case TRANSMITTER_UNIPHY_D:
     877           0 :                 enc110->base.preferred_engine = ENGINE_ID_DIGD;
     878           0 :         break;
     879             :         case TRANSMITTER_UNIPHY_E:
     880           0 :                 enc110->base.preferred_engine = ENGINE_ID_DIGE;
     881           0 :         break;
     882             :         case TRANSMITTER_UNIPHY_F:
     883           0 :                 enc110->base.preferred_engine = ENGINE_ID_DIGF;
     884           0 :         break;
     885             :         case TRANSMITTER_UNIPHY_G:
     886           0 :                 enc110->base.preferred_engine = ENGINE_ID_DIGG;
     887           0 :         break;
     888             :         default:
     889           0 :                 ASSERT_CRITICAL(false);
     890           0 :                 enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
     891             :         }
     892             : 
     893             :         /* default to one to mirror Windows behavior */
     894           0 :         enc110->base.features.flags.bits.HDMI_6GB_EN = 1;
     895             : 
     896           0 :         result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios,
     897             :                                                 enc110->base.id, &bp_cap_info);
     898             : 
     899             :         /* Override features with DCE-specific values */
     900           0 :         if (BP_RESULT_OK == result) {
     901           0 :                 enc110->base.features.flags.bits.IS_HBR2_CAPABLE =
     902           0 :                                 bp_cap_info.DP_HBR2_EN;
     903           0 :                 enc110->base.features.flags.bits.IS_HBR3_CAPABLE =
     904           0 :                                 bp_cap_info.DP_HBR3_EN;
     905           0 :                 enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;
     906             :         } else {
     907           0 :                 DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
     908             :                                 __func__,
     909             :                                 result);
     910             :         }
     911           0 :         if (enc110->base.ctx->dc->debug.hdmi20_disable) {
     912           0 :                 enc110->base.features.flags.bits.HDMI_6GB_EN = 0;
     913             :         }
     914           0 : }
     915             : 
     916           0 : bool dce110_link_encoder_validate_output_with_stream(
     917             :         struct link_encoder *enc,
     918             :         const struct dc_stream_state *stream)
     919             : {
     920           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
     921             :         bool is_valid;
     922             : 
     923           0 :         switch (stream->signal) {
     924             :         case SIGNAL_TYPE_DVI_SINGLE_LINK:
     925             :         case SIGNAL_TYPE_DVI_DUAL_LINK:
     926           0 :                 is_valid = dce110_link_encoder_validate_dvi_output(
     927             :                         enc110,
     928           0 :                         stream->link->connector_signal,
     929             :                         stream->signal,
     930             :                         &stream->timing);
     931           0 :         break;
     932             :         case SIGNAL_TYPE_HDMI_TYPE_A:
     933           0 :                 is_valid = dce110_link_encoder_validate_hdmi_output(
     934             :                                 enc110,
     935             :                                 &stream->timing,
     936             :                                 stream->phy_pix_clk);
     937           0 :         break;
     938             :         case SIGNAL_TYPE_DISPLAY_PORT:
     939             :         case SIGNAL_TYPE_DISPLAY_PORT_MST:
     940           0 :                 is_valid = dce110_link_encoder_validate_dp_output(
     941             :                                         enc110, &stream->timing);
     942             :         break;
     943             :         case SIGNAL_TYPE_EDP:
     944             :         case SIGNAL_TYPE_LVDS:
     945           0 :                 is_valid =
     946           0 :                         (stream->timing.
     947             :                                 pixel_encoding == PIXEL_ENCODING_RGB) ? true : false;
     948           0 :         break;
     949             :         case SIGNAL_TYPE_VIRTUAL:
     950             :                 is_valid = true;
     951             :                 break;
     952             :         default:
     953           0 :                 is_valid = false;
     954           0 :         break;
     955             :         }
     956             : 
     957           0 :         return is_valid;
     958             : }
     959             : 
     960           0 : void dce110_link_encoder_hw_init(
     961             :         struct link_encoder *enc)
     962             : {
     963           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
     964           0 :         struct bp_transmitter_control cntl = { 0 };
     965             :         enum bp_result result;
     966             : 
     967           0 :         cntl.action = TRANSMITTER_CONTROL_INIT;
     968           0 :         cntl.engine_id = ENGINE_ID_UNKNOWN;
     969           0 :         cntl.transmitter = enc110->base.transmitter;
     970           0 :         cntl.connector_obj_id = enc110->base.connector;
     971           0 :         cntl.lanes_number = LANE_COUNT_FOUR;
     972             :         cntl.coherent = false;
     973           0 :         cntl.hpd_sel = enc110->base.hpd_source;
     974             : 
     975           0 :         if (enc110->base.connector.id == CONNECTOR_ID_EDP)
     976           0 :                 cntl.signal = SIGNAL_TYPE_EDP;
     977             : 
     978           0 :         result = link_transmitter_control(enc110, &cntl);
     979             : 
     980           0 :         if (result != BP_RESULT_OK) {
     981           0 :                 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
     982             :                         __func__);
     983           0 :                 BREAK_TO_DEBUGGER();
     984           0 :                 return;
     985             :         }
     986             : 
     987           0 :         if (enc110->base.connector.id == CONNECTOR_ID_LVDS) {
     988           0 :                 cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS;
     989             : 
     990           0 :                 result = link_transmitter_control(enc110, &cntl);
     991             : 
     992           0 :                 ASSERT(result == BP_RESULT_OK);
     993             : 
     994             :         }
     995           0 :         aux_initialize(enc110);
     996             : 
     997             :         /* reinitialize HPD.
     998             :          * hpd_initialize() will pass DIG_FE id to HW context.
     999             :          * 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           0 :         hpd_initialize(enc110);
    1003             : }
    1004             : 
    1005           0 : void dce110_link_encoder_destroy(struct link_encoder **enc)
    1006             : {
    1007           0 :         kfree(TO_DCE110_LINK_ENC(*enc));
    1008           0 :         *enc = NULL;
    1009           0 : }
    1010             : 
    1011           0 : void dce110_link_encoder_setup(
    1012             :         struct link_encoder *enc,
    1013             :         enum signal_type signal)
    1014             : {
    1015           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
    1016             : 
    1017           0 :         switch (signal) {
    1018             :         case SIGNAL_TYPE_EDP:
    1019             :         case SIGNAL_TYPE_DISPLAY_PORT:
    1020             :                 /* DP SST */
    1021           0 :                 REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 0);
    1022           0 :                 break;
    1023             :         case SIGNAL_TYPE_LVDS:
    1024             :                 /* LVDS */
    1025           0 :                 REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 1);
    1026           0 :                 break;
    1027             :         case SIGNAL_TYPE_DVI_SINGLE_LINK:
    1028             :         case SIGNAL_TYPE_DVI_DUAL_LINK:
    1029             :                 /* TMDS-DVI */
    1030           0 :                 REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 2);
    1031           0 :                 break;
    1032             :         case SIGNAL_TYPE_HDMI_TYPE_A:
    1033             :                 /* TMDS-HDMI */
    1034           0 :                 REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 3);
    1035           0 :                 break;
    1036             :         case SIGNAL_TYPE_DISPLAY_PORT_MST:
    1037             :                 /* DP MST */
    1038           0 :                 REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 5);
    1039           0 :                 break;
    1040             :         default:
    1041           0 :                 ASSERT_CRITICAL(false);
    1042             :                 /* invalid mode ! */
    1043           0 :                 break;
    1044             :         }
    1045             : 
    1046           0 : }
    1047             : 
    1048             : /* TODO: still need depth or just pass in adjusted pixel clock? */
    1049           0 : 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           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
    1057           0 :         struct bp_transmitter_control cntl = { 0 };
    1058             :         enum bp_result result;
    1059             : 
    1060             :         /* Enable the PHY */
    1061           0 :         cntl.connector_obj_id = enc110->base.connector;
    1062           0 :         cntl.action = TRANSMITTER_CONTROL_ENABLE;
    1063           0 :         cntl.engine_id = enc->preferred_engine;
    1064           0 :         cntl.transmitter = enc110->base.transmitter;
    1065           0 :         cntl.pll_id = clock_source;
    1066           0 :         cntl.signal = signal;
    1067           0 :         if (cntl.signal == SIGNAL_TYPE_DVI_DUAL_LINK)
    1068           0 :                 cntl.lanes_number = 8;
    1069             :         else
    1070           0 :                 cntl.lanes_number = 4;
    1071             : 
    1072           0 :         cntl.hpd_sel = enc110->base.hpd_source;
    1073             : 
    1074           0 :         cntl.pixel_clock = pixel_clock;
    1075           0 :         cntl.color_depth = color_depth;
    1076             : 
    1077           0 :         result = link_transmitter_control(enc110, &cntl);
    1078             : 
    1079           0 :         if (result != BP_RESULT_OK) {
    1080           0 :                 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
    1081             :                         __func__);
    1082           0 :                 BREAK_TO_DEBUGGER();
    1083             :         }
    1084           0 : }
    1085             : 
    1086             : /* TODO: still need depth or just pass in adjusted pixel clock? */
    1087           0 : 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           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
    1093           0 :         struct bp_transmitter_control cntl = { 0 };
    1094             :         enum bp_result result;
    1095             : 
    1096             :         /* Enable the PHY */
    1097           0 :         cntl.connector_obj_id = enc110->base.connector;
    1098           0 :         cntl.action = TRANSMITTER_CONTROL_ENABLE;
    1099           0 :         cntl.engine_id = enc->preferred_engine;
    1100           0 :         cntl.transmitter = enc110->base.transmitter;
    1101           0 :         cntl.pll_id = clock_source;
    1102           0 :         cntl.signal = SIGNAL_TYPE_LVDS;
    1103           0 :         cntl.lanes_number = 4;
    1104             : 
    1105           0 :         cntl.hpd_sel = enc110->base.hpd_source;
    1106             : 
    1107           0 :         cntl.pixel_clock = pixel_clock;
    1108             : 
    1109           0 :         result = link_transmitter_control(enc110, &cntl);
    1110             : 
    1111           0 :         if (result != BP_RESULT_OK) {
    1112           0 :                 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
    1113             :                         __func__);
    1114           0 :                 BREAK_TO_DEBUGGER();
    1115             :         }
    1116           0 : }
    1117             : 
    1118             : /* enables DP PHY output */
    1119           0 : 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           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
    1125           0 :         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           0 :         configure_encoder(enc110, link_settings);
    1135           0 :         cntl.connector_obj_id = enc110->base.connector;
    1136           0 :         cntl.action = TRANSMITTER_CONTROL_ENABLE;
    1137           0 :         cntl.engine_id = enc->preferred_engine;
    1138           0 :         cntl.transmitter = enc110->base.transmitter;
    1139           0 :         cntl.pll_id = clock_source;
    1140           0 :         cntl.signal = SIGNAL_TYPE_DISPLAY_PORT;
    1141           0 :         cntl.lanes_number = link_settings->lane_count;
    1142           0 :         cntl.hpd_sel = enc110->base.hpd_source;
    1143           0 :         cntl.pixel_clock = link_settings->link_rate
    1144           0 :                                                 * LINK_RATE_REF_FREQ_IN_KHZ;
    1145             :         /* TODO: check if undefined works */
    1146           0 :         cntl.color_depth = COLOR_DEPTH_UNDEFINED;
    1147             : 
    1148           0 :         result = link_transmitter_control(enc110, &cntl);
    1149             : 
    1150           0 :         if (result != BP_RESULT_OK) {
    1151           0 :                 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
    1152             :                         __func__);
    1153           0 :                 BREAK_TO_DEBUGGER();
    1154             :         }
    1155           0 : }
    1156             : 
    1157             : /* enables DP PHY output in MST mode */
    1158           0 : 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           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
    1164           0 :         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           0 :         configure_encoder(enc110, link_settings);
    1174             : 
    1175           0 :         cntl.action = TRANSMITTER_CONTROL_ENABLE;
    1176           0 :         cntl.engine_id = ENGINE_ID_UNKNOWN;
    1177           0 :         cntl.transmitter = enc110->base.transmitter;
    1178           0 :         cntl.pll_id = clock_source;
    1179           0 :         cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
    1180           0 :         cntl.lanes_number = link_settings->lane_count;
    1181           0 :         cntl.hpd_sel = enc110->base.hpd_source;
    1182           0 :         cntl.pixel_clock = link_settings->link_rate
    1183           0 :                                                 * LINK_RATE_REF_FREQ_IN_KHZ;
    1184             :         /* TODO: check if undefined works */
    1185           0 :         cntl.color_depth = COLOR_DEPTH_UNDEFINED;
    1186             : 
    1187           0 :         result = link_transmitter_control(enc110, &cntl);
    1188             : 
    1189           0 :         if (result != BP_RESULT_OK) {
    1190           0 :                 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
    1191             :                         __func__);
    1192           0 :                 BREAK_TO_DEBUGGER();
    1193             :         }
    1194           0 : }
    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           0 : void dce110_link_encoder_disable_output(
    1281             :         struct link_encoder *enc,
    1282             :         enum signal_type signal)
    1283             : {
    1284           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
    1285           0 :         struct bp_transmitter_control cntl = { 0 };
    1286             :         enum bp_result result;
    1287             : 
    1288           0 :         if (!dce110_is_dig_enabled(enc)) {
    1289             :                 /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */
    1290           0 :                 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           0 :         cntl.action = TRANSMITTER_CONTROL_DISABLE;
    1304           0 :         cntl.transmitter = enc110->base.transmitter;
    1305           0 :         cntl.hpd_sel = enc110->base.hpd_source;
    1306           0 :         cntl.signal = signal;
    1307           0 :         cntl.connector_obj_id = enc110->base.connector;
    1308             : 
    1309           0 :         result = link_transmitter_control(enc110, &cntl);
    1310             : 
    1311           0 :         if (result != BP_RESULT_OK) {
    1312           0 :                 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
    1313             :                         __func__);
    1314           0 :                 BREAK_TO_DEBUGGER();
    1315           0 :                 return;
    1316             :         }
    1317             : 
    1318             :         /* disable encoder */
    1319           0 :         if (dc_is_dp_signal(signal))
    1320           0 :                 link_encoder_disable(enc110);
    1321             : }
    1322             : 
    1323           0 : 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           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
    1329           0 :         union dpcd_training_lane_set training_lane_set = { { 0 } };
    1330           0 :         int32_t lane = 0;
    1331           0 :         struct bp_transmitter_control cntl = { 0 };
    1332             : 
    1333           0 :         if (!link_settings) {
    1334           0 :                 BREAK_TO_DEBUGGER();
    1335           0 :                 return;
    1336             :         }
    1337             : 
    1338           0 :         cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;
    1339           0 :         cntl.transmitter = enc110->base.transmitter;
    1340           0 :         cntl.connector_obj_id = enc110->base.connector;
    1341           0 :         cntl.lanes_number = link_settings->lane_count;
    1342           0 :         cntl.hpd_sel = enc110->base.hpd_source;
    1343           0 :         cntl.pixel_clock = link_settings->link_rate *
    1344             :                                                 LINK_RATE_REF_FREQ_IN_KHZ;
    1345             : 
    1346           0 :         for (lane = 0; lane < link_settings->lane_count; lane++) {
    1347             :                 /* translate lane settings */
    1348             : 
    1349           0 :                 training_lane_set.bits.VOLTAGE_SWING_SET =
    1350           0 :                                 lane_settings[lane].VOLTAGE_SWING;
    1351           0 :                 training_lane_set.bits.PRE_EMPHASIS_SET =
    1352           0 :                                 lane_settings[lane].PRE_EMPHASIS;
    1353             : 
    1354             :                 /* post cursor 2 setting only applies to HBR2 link rate */
    1355           0 :                 if (link_settings->link_rate == LINK_RATE_HIGH2) {
    1356             :                         /* this is passed to VBIOS
    1357             :                          * to program post cursor 2 level */
    1358             : 
    1359           0 :                         training_lane_set.bits.POST_CURSOR2_SET =
    1360           0 :                                         lane_settings[lane].POST_CURSOR2;
    1361             :                 }
    1362             : 
    1363           0 :                 cntl.lane_select = lane;
    1364           0 :                 cntl.lane_settings = training_lane_set.raw;
    1365             : 
    1366             :                 /* call VBIOS table to set voltage swing and pre-emphasis */
    1367           0 :                 link_transmitter_control(enc110, &cntl);
    1368             :         }
    1369             : }
    1370             : 
    1371             : /* set DP PHY test and training patterns */
    1372           0 : 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           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
    1377             : 
    1378           0 :         switch (param->dp_phy_pattern) {
    1379             :         case DP_TEST_PATTERN_TRAINING_PATTERN1:
    1380           0 :                 dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0);
    1381           0 :                 break;
    1382             :         case DP_TEST_PATTERN_TRAINING_PATTERN2:
    1383           0 :                 dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1);
    1384           0 :                 break;
    1385             :         case DP_TEST_PATTERN_TRAINING_PATTERN3:
    1386           0 :                 dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2);
    1387           0 :                 break;
    1388             :         case DP_TEST_PATTERN_TRAINING_PATTERN4:
    1389           0 :                 dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3);
    1390           0 :                 break;
    1391             :         case DP_TEST_PATTERN_D102:
    1392           0 :                 set_dp_phy_pattern_d102(enc110);
    1393           0 :                 break;
    1394             :         case DP_TEST_PATTERN_SYMBOL_ERROR:
    1395           0 :                 set_dp_phy_pattern_symbol_error(enc110);
    1396           0 :                 break;
    1397             :         case DP_TEST_PATTERN_PRBS7:
    1398           0 :                 set_dp_phy_pattern_prbs7(enc110);
    1399           0 :                 break;
    1400             :         case DP_TEST_PATTERN_80BIT_CUSTOM:
    1401           0 :                 set_dp_phy_pattern_80bit_custom(
    1402             :                         enc110, param->custom_pattern);
    1403           0 :                 break;
    1404             :         case DP_TEST_PATTERN_CP2520_1:
    1405           0 :                 set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 1);
    1406           0 :                 break;
    1407             :         case DP_TEST_PATTERN_CP2520_2:
    1408           0 :                 set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2);
    1409           0 :                 break;
    1410             :         case DP_TEST_PATTERN_CP2520_3:
    1411           0 :                 set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 3);
    1412           0 :                 break;
    1413             :         case DP_TEST_PATTERN_VIDEO_MODE: {
    1414           0 :                 set_dp_phy_pattern_passthrough_mode(
    1415             :                         enc110, param->dp_panel_mode);
    1416           0 :                 break;
    1417             :         }
    1418             : 
    1419             :         default:
    1420             :                 /* invalid phy pattern */
    1421           0 :                 ASSERT_CRITICAL(false);
    1422           0 :                 break;
    1423             :         }
    1424           0 : }
    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           0 :         const struct stream_encoder *stream_enc = stream_allocation->stream_enc;
    1489             : 
    1490           0 :         if (stream_enc) {
    1491           0 :                 *src = stream_enc->id;
    1492           0 :                 *slots = stream_allocation->slot_count;
    1493             :         } else {
    1494             :                 *src = 0;
    1495             :                 *slots = 0;
    1496             :         }
    1497             : }
    1498             : 
    1499             : /* programs DP MST VC payload allocation */
    1500           0 : 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           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
    1505           0 :         uint32_t value1 = 0;
    1506           0 :         uint32_t value2 = 0;
    1507           0 :         uint32_t slots = 0;
    1508           0 :         uint32_t src = 0;
    1509           0 :         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           0 :         if (table->stream_count >= 1) {
    1521           0 :                 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           0 :         REG_UPDATE_2(DP_MSE_SAT0,
    1531             :                         DP_MSE_SAT_SRC0, src,
    1532             :                         DP_MSE_SAT_SLOT_COUNT0, slots);
    1533             : 
    1534           0 :         if (table->stream_count >= 2) {
    1535           0 :                 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           0 :         REG_UPDATE_2(DP_MSE_SAT0,
    1545             :                         DP_MSE_SAT_SRC1, src,
    1546             :                         DP_MSE_SAT_SLOT_COUNT1, slots);
    1547             : 
    1548           0 :         if (table->stream_count >= 3) {
    1549           0 :                 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           0 :         REG_UPDATE_2(DP_MSE_SAT1,
    1559             :                         DP_MSE_SAT_SRC2, src,
    1560             :                         DP_MSE_SAT_SLOT_COUNT2, slots);
    1561             : 
    1562           0 :         if (table->stream_count >= 4) {
    1563           0 :                 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           0 :         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           0 :         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           0 :                 udelay(10);
    1604             : 
    1605           0 :                 REG_READ(DP_MSE_SAT_UPDATE);
    1606             : 
    1607           0 :                 REG_GET(DP_MSE_SAT_UPDATE,
    1608             :                                 DP_MSE_SAT_UPDATE, &value1);
    1609             : 
    1610           0 :                 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           0 :                 if (!value1 && !value2)
    1615             :                         break;
    1616           0 :                 ++retries;
    1617           0 :         } while (retries < DP_MST_UPDATE_MAX_RETRY);
    1618           0 : }
    1619             : 
    1620           0 : void dce110_link_encoder_connect_dig_be_to_fe(
    1621             :         struct link_encoder *enc,
    1622             :         enum engine_id engine,
    1623             :         bool connect)
    1624             : {
    1625           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
    1626             :         uint32_t field;
    1627             : 
    1628           0 :         if (engine != ENGINE_ID_UNKNOWN) {
    1629             : 
    1630           0 :                 REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &field);
    1631             : 
    1632           0 :                 if (connect)
    1633           0 :                         field |= get_frontend_source(engine);
    1634             :                 else
    1635           0 :                         field &= ~get_frontend_source(engine);
    1636             : 
    1637           0 :                 REG_UPDATE(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, field);
    1638             :         }
    1639           0 : }
    1640             : 
    1641           0 : void dce110_link_encoder_enable_hpd(struct link_encoder *enc)
    1642             : {
    1643           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
    1644           0 :         struct dc_context *ctx = enc110->base.ctx;
    1645           0 :         uint32_t addr = HPD_REG(DC_HPD_CONTROL);
    1646           0 :         uint32_t hpd_enable = 0;
    1647           0 :         uint32_t value = dm_read_reg(ctx, addr);
    1648             : 
    1649           0 :         get_reg_field_value(hpd_enable, DC_HPD_CONTROL, DC_HPD_EN);
    1650             : 
    1651             :         if (hpd_enable == 0)
    1652           0 :                 set_reg_field_value(value, 1, DC_HPD_CONTROL, DC_HPD_EN);
    1653           0 : }
    1654             : 
    1655           0 : void dce110_link_encoder_disable_hpd(struct link_encoder *enc)
    1656             : {
    1657           0 :         struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
    1658           0 :         struct dc_context *ctx = enc110->base.ctx;
    1659           0 :         uint32_t addr = HPD_REG(DC_HPD_CONTROL);
    1660           0 :         uint32_t value = dm_read_reg(ctx, addr);
    1661             : 
    1662           0 :         set_reg_field_value(value, 0, DC_HPD_CONTROL, DC_HPD_EN);
    1663           0 : }
    1664             : 
    1665           0 : 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           0 :         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           0 :         if (enc->features.flags.bits.IS_HBR2_CAPABLE)
    1674           0 :                 max_link_cap.link_rate = LINK_RATE_HIGH2;
    1675             : 
    1676           0 :         if (enc->features.flags.bits.IS_HBR3_CAPABLE)
    1677           0 :                 max_link_cap.link_rate = LINK_RATE_HIGH3;
    1678             : 
    1679           0 :         *link_settings = max_link_cap;
    1680           0 : }
    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

Generated by: LCOV version 1.14