drm/amd/display: handle dp is usb-c
authorBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Fri, 11 Oct 2019 14:37:49 +0000 (10:37 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 17 Oct 2019 20:30:23 +0000 (16:30 -0400)
This patch adds handling of dp is usb-c, it is not tested but is
needed to support dp over usb-c

Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Reviewed-by: Roman Li <Roman.Li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.h

index 239a6c90ffb9601acff9ffe9dcbbdf0fc65aeca4..88fcc395adf52475672479147d6a1075e84db052 100644 (file)
@@ -113,6 +113,20 @@ struct dcn10_link_enc_registers {
        uint32_t DIG_LANE_ENABLE;
        /* UNIPHY */
        uint32_t CHANNEL_XBAR_CNTL;
+       /* DPCS */
+       uint32_t RDPCSTX_PHY_CNTL3;
+       uint32_t RDPCSTX_PHY_CNTL4;
+       uint32_t RDPCSTX_PHY_CNTL5;
+       uint32_t RDPCSTX_PHY_CNTL6;
+       uint32_t RDPCSTX_PHY_CNTL7;
+       uint32_t RDPCSTX_PHY_CNTL8;
+       uint32_t RDPCSTX_PHY_CNTL9;
+       uint32_t RDPCSTX_PHY_CNTL10;
+       uint32_t RDPCSTX_PHY_CNTL11;
+       uint32_t RDPCSTX_PHY_CNTL12;
+       uint32_t RDPCSTX_PHY_CNTL13;
+       uint32_t RDPCSTX_PHY_CNTL14;
+       uint32_t RDPCSTX_PHY_CNTL15;
        /* indirect registers */
        uint32_t RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_2;
        uint32_t RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_3;
index 526865c43b488252bd3016dd3bd2532c7a83be83..e8a504ca5890163c23b5d73d67b20a0dcbdf9ea6 100644 (file)
@@ -203,6 +203,77 @@ static bool update_cfg_data(
        return true;
 }
 
+void dcn21_link_encoder_get_max_link_cap(struct link_encoder *enc,
+       struct dc_link_settings *link_settings)
+{
+       struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+       uint32_t value;
+
+       REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &value);
+
+       if (!value && link_settings->lane_count > LANE_COUNT_TWO)
+               link_settings->lane_count = LANE_COUNT_TWO;
+}
+
+bool dcn21_link_encoder_is_in_alt_mode(struct link_encoder *enc)
+{
+       struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+       uint32_t value;
+
+       REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &value);
+
+       // if value == 1 alt mode is disabled, otherwise it is enabled
+       return !value;
+}
+
+bool dcn21_link_encoder_acquire_phy(struct link_encoder *enc)
+{
+       struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+       int value;
+
+       if (enc->features.flags.bits.DP_IS_USB_C) {
+               REG_GET(RDPCSTX_PHY_CNTL6,
+                               RDPCS_PHY_DPALT_DISABLE, &value);
+
+               if (value == 1) {
+                       ASSERT(0);
+                       return false;
+               }
+               REG_UPDATE(RDPCSTX_PHY_CNTL6,
+                               RDPCS_PHY_DPALT_DISABLE_ACK, 0);
+
+               udelay(40);
+
+               REG_GET(RDPCSTX_PHY_CNTL6,
+                                               RDPCS_PHY_DPALT_DISABLE, &value);
+               if (value == 1) {
+                       ASSERT(0);
+                       REG_UPDATE(RDPCSTX_PHY_CNTL6,
+                                       RDPCS_PHY_DPALT_DISABLE_ACK, 1);
+                       return false;
+               }
+       }
+
+       REG_UPDATE(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_REF_CLK_EN, 1);
+
+       return true;
+}
+
+
+
+static void dcn21_link_encoder_release_phy(struct link_encoder *enc)
+{
+       struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+
+       if (enc->features.flags.bits.DP_IS_USB_C) {
+               REG_UPDATE(RDPCSTX_PHY_CNTL6,
+                               RDPCS_PHY_DPALT_DISABLE_ACK, 1);
+       }
+
+       REG_UPDATE(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_REF_CLK_EN, 0);
+
+}
+
 void dcn21_link_encoder_enable_dp_output(
        struct link_encoder *enc,
        const struct dc_link_settings *link_settings,
@@ -212,6 +283,9 @@ void dcn21_link_encoder_enable_dp_output(
        struct dcn21_link_encoder *enc21 = (struct dcn21_link_encoder *) enc10;
        struct dpcssys_phy_seq_cfg *cfg = &enc21->phy_seq_cfg;
 
+       if (!dcn21_link_encoder_acquire_phy(enc))
+               return;
+
        if (!enc->ctx->dc->debug.avoid_vbios_exec_table) {
                dcn10_link_encoder_enable_dp_output(enc, link_settings, clock_source);
                return;
@@ -226,13 +300,28 @@ void dcn21_link_encoder_enable_dp_output(
 
 }
 
+void dcn21_link_encoder_enable_dp_mst_output(
+       struct link_encoder *enc,
+       const struct dc_link_settings *link_settings,
+       enum clock_source_id clock_source)
+{
+       if (!dcn21_link_encoder_acquire_phy(enc))
+               return;
+
+       dcn10_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source);
+}
+
 void dcn21_link_encoder_disable_output(
        struct link_encoder *enc,
        enum signal_type signal)
 {
        dcn10_link_encoder_disable_output(enc, signal);
 
+       if (dc_is_dp_signal(signal))
+               dcn21_link_encoder_release_phy(enc);
 }
+
+
 static const struct link_encoder_funcs dcn21_link_enc_funcs = {
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
        .read_state = link_enc2_read_state,
@@ -243,7 +332,7 @@ static const struct link_encoder_funcs dcn21_link_enc_funcs = {
        .setup = dcn10_link_encoder_setup,
        .enable_tmds_output = dcn10_link_encoder_enable_tmds_output,
        .enable_dp_output = dcn21_link_encoder_enable_dp_output,
-       .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output,
+       .enable_dp_mst_output = dcn21_link_encoder_enable_dp_mst_output,
        .disable_output = dcn21_link_encoder_disable_output,
        .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings,
        .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern,
@@ -261,6 +350,8 @@ static const struct link_encoder_funcs dcn21_link_enc_funcs = {
        .fec_set_ready = enc2_fec_set_ready,
        .fec_is_active = enc2_fec_is_active,
        .get_dig_frontend = dcn10_get_dig_frontend,
+       .is_in_alt_mode = dcn21_link_encoder_is_in_alt_mode,
+       .get_max_link_cap = dcn21_link_encoder_get_max_link_cap,
 };
 
 void dcn21_link_encoder_construct(
index 438321e547db2ce054dfa926cef3d890ef1b0bf1..1d7a1a51f13d0663774deceb932e3c560f8334b8 100644 (file)
@@ -33,6 +33,16 @@ struct dcn21_link_encoder {
        struct dpcssys_phy_seq_cfg phy_seq_cfg;
 };
 
+#define LINK_ENCODER_MASK_SH_LIST_DCN21(mask_sh)\
+       LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh),\
+       LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL0_XBAR_SOURCE, mask_sh),\
+       LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL1_XBAR_SOURCE, mask_sh),\
+       LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL2_XBAR_SOURCE, mask_sh),\
+       LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL3_XBAR_SOURCE, mask_sh), \
+       SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \
+       SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \
+       SR(RDPCSTX0_RDPCSTX_SCRATCH)
+
 void dcn21_link_encoder_enable_dp_output(
        struct link_encoder *enc,
        const struct dc_link_settings *link_settings,