Merge tag 'amd-drm-next-6.3-2023-01-27' of https://gitlab.freedesktop.org/agd5f/linux...
authorDave Airlie <airlied@redhat.com>
Mon, 30 Jan 2023 05:37:55 +0000 (15:37 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 30 Jan 2023 05:37:57 +0000 (15:37 +1000)
amd-drm-next-6.3-2023-01-27:

amdgpu:
- GC11 fixes
- SMU13 fixes
- Freesync fixes
- DP MST fixes
- DP MST code rework and cleanup
- AV1 fixes for VCN4
- DCN 3.2.x fixes
- PSR fixes
- DML optimizations
- DC link code rework

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230127225917.2419162-1-alexander.deucher@amd.com
109 files changed:
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
drivers/gpu/drm/amd/amdgpu/imu_v11_0.c
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
drivers/gpu/drm/amd/amdgpu/soc21.c
drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
drivers/gpu/drm/amd/display/dc/Makefile
drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c [deleted file]
drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dc_dp_types.h
drivers/gpu/drm/amd/display/dc/dc_link.h
drivers/gpu/drm/amd/display/dc/dc_stream.h
drivers/gpu/drm/amd/display/dc/dc_types.h
drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.h
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
drivers/gpu/drm/amd/display/dc/dm_helpers.h
drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h
drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h [deleted file]
drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
drivers/gpu/drm/amd/display/dc/inc/link.h
drivers/gpu/drm/amd/display/dc/link/Makefile
drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_trace.c with 95% similarity]
drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_trace.h with 91% similarity]
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c [moved from drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c with 99% similarity]
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.h [moved from drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h with 99% similarity]
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c [moved from drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.h [moved from drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.h with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c [moved from drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c with 99% similarity]
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.h [moved from drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.h with 98% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c [moved from drivers/gpu/drm/amd/display/dc/link/link_ddc.c with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h [moved from drivers/gpu/drm/amd/display/dc/link/link_ddc.h with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_capability.c with 98% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_capability.h with 85% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_dpia.c with 99% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.h [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_dpia.h with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.c with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.h with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.h [moved from drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.h with 80% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_phy.c with 98% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_phy.h with 93% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_training.c with 99% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_training.h with 98% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_training_128b_132b.c with 99% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.h [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_training_128b_132b.h with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_training_8b_10b.c with 99% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.h [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_training_8b_10b.h with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_training_auxless.c with 99% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.h [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_training_auxless.h with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_training_dpia.c with 99% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.h [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_training_dpia.h with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_training_fixed_vs_pe_retimer.c with 99% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.h [moved from drivers/gpu/drm/amd/display/dc/link/link_dp_training_fixed_vs_pe_retimer.h with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c [moved from drivers/gpu/drm/amd/display/dc/link/link_dpcd.c with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.h [moved from drivers/gpu/drm/amd/display/dc/link/link_dpcd.h with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c [moved from drivers/gpu/drm/amd/display/dc/link/link_hpd.c with 100% similarity]
drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h [moved from drivers/gpu/drm/amd/display/dc/link/link_hpd.h with 100% similarity]
drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
drivers/gpu/drm/amd/display/modules/power/power_helpers.h
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
drivers/gpu/drm/display/drm_dp_mst_topology.c
include/drm/drm_print.h

index 1257745fb202384a2ecb1986fbf824dd7e3b9fe6..5bee3ff623442e925cdf3c775598d1fb2a998791 100644 (file)
@@ -3038,6 +3038,18 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
                    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SDMA))
                        continue;
 
+               /* Once swPSP provides the IMU, RLC FW binaries to TOS during cold-boot.
+                * These are in TMR, hence are expected to be reused by PSP-TOS to reload
+                * from this location and RLC Autoload automatically also gets loaded
+                * from here based on PMFW -> PSP message during re-init sequence.
+                * Therefore, the psp suspend & resume should be skipped to avoid destroy
+                * the TMR and reload FWs again for IMU enabled APU ASICs.
+                */
+               if (amdgpu_in_reset(adev) &&
+                   (adev->flags & AMD_IS_APU) && adev->gfx.imu.funcs &&
+                   adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)
+                       continue;
+
                /* XXX handle errors */
                r = adev->ip_blocks[i].version->funcs->suspend(adev);
                /* XXX handle errors */
index 44c57f4a84c45c81e17eb1514f1afb9b0deeaa84..32fe05c810c6fcd3b89fe89ce7eba88f69c12aaf 100644 (file)
@@ -549,8 +549,8 @@ struct amdgpu_mst_connector {
 
        struct drm_dp_mst_topology_mgr mst_mgr;
        struct amdgpu_dm_dp_aux dm_dp_aux;
-       struct drm_dp_mst_port *port;
-       struct amdgpu_connector *mst_port;
+       struct drm_dp_mst_port *mst_output_port;
+       struct amdgpu_connector *mst_root;
        bool is_mst_connector;
        struct amdgpu_encoder *mst_encoder;
 };
index ed0d368149aae6a815df72df42d35c54076459a8..4ab90c7852c3ed3ee033828274997d0777c5cdd7 100644 (file)
@@ -35,6 +35,7 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_0_imu.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_1_imu.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_2_imu.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_3_imu.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_0_4_imu.bin");
 
 static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
 {
index bfa305079bfcf84d38da73a701ae3316fcbb9568..62cdd2113135fe80a5d706799d4a48daf520d00b 100644 (file)
@@ -40,6 +40,8 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_2_mes.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_2_mes1.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_3_mes.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_3_mes1.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_0_4_mes.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_0_4_mes1.bin");
 
 static int mes_v11_0_hw_fini(void *handle);
 static int mes_v11_0_kiq_hw_init(struct amdgpu_device *adev);
@@ -196,7 +198,6 @@ static int mes_v11_0_add_hw_queue(struct amdgpu_mes *mes,
        mes_add_queue_pkt.trap_handler_addr = input->tba_addr;
        mes_add_queue_pkt.tma_addr = input->tma_addr;
        mes_add_queue_pkt.is_kfd_process = input->is_kfd_process;
-       mes_add_queue_pkt.trap_en = 1;
 
        /* For KFD, gds_size is re-used for queue size (needed in MES for AQL queues) */
        mes_add_queue_pkt.is_aql_queue = input->is_aql_queue;
index 9c4a29d50f1cd79f68c565a107ad14d2df9a0c1f..e03cf7f766c58485f377653a139d16f91f8ada81 100644 (file)
@@ -52,6 +52,7 @@ static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_encode_array_
 {
        {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
        {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
 };
 
 static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_encode_array_vcn1[] =
index efb22d0975b34c46410627838d399108928afd60..22a41766a8c71cc7cbad317318bca108d82c1ba0 100644 (file)
@@ -1710,7 +1710,7 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
 
                create = ptr + addr + offset - start;
 
-               /* H246, HEVC and VP9 can run on any instance */
+               /* H264, HEVC and VP9 can run on any instance */
                if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
                        continue;
 
@@ -1724,7 +1724,29 @@ out:
        return r;
 }
 
-#define RADEON_VCN_ENGINE_TYPE_DECODE                                 (0x00000003)
+#define RADEON_VCN_ENGINE_TYPE_ENCODE                  (0x00000002)
+#define RADEON_VCN_ENGINE_TYPE_DECODE                  (0x00000003)
+
+#define RADEON_VCN_ENGINE_INFO                         (0x30000001)
+#define RADEON_VCN_ENGINE_INFO_MAX_OFFSET              16
+
+#define RENCODE_ENCODE_STANDARD_AV1                    2
+#define RENCODE_IB_PARAM_SESSION_INIT                  0x00000003
+#define RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET       64
+
+/* return the offset in ib if id is found, -1 otherwise
+ * to speed up the searching we only search upto max_offset
+ */
+static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int max_offset)
+{
+       int i;
+
+       for (i = 0; i < ib->length_dw && i < max_offset && ib->ptr[i] >= 8; i += ib->ptr[i]/4) {
+               if (ib->ptr[i + 1] == id)
+                       return i;
+       }
+       return -1;
+}
 
 static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
                                           struct amdgpu_job *job,
@@ -1734,27 +1756,35 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
        struct amdgpu_vcn_decode_buffer *decode_buffer;
        uint64_t addr;
        uint32_t val;
+       int idx;
 
        /* The first instance can decode anything */
        if (!ring->me)
                return 0;
 
-       /* unified queue ib header has 8 double words. */
-       if (ib->length_dw < 8)
-               return 0;
-
-       val = amdgpu_ib_get_value(ib, 6); //RADEON_VCN_ENGINE_TYPE
-       if (val != RADEON_VCN_ENGINE_TYPE_DECODE)
-               return 0;
-
-       decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[10];
-
-       if (!(decode_buffer->valid_buf_flag  & 0x1))
+       /* RADEON_VCN_ENGINE_INFO is at the top of ib block */
+       idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO,
+                       RADEON_VCN_ENGINE_INFO_MAX_OFFSET);
+       if (idx < 0) /* engine info is missing */
                return 0;
 
-       addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
-               decode_buffer->msg_buffer_address_lo;
-       return vcn_v4_0_dec_msg(p, job, addr);
+       val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
+       if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
+               decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
+
+               if (!(decode_buffer->valid_buf_flag  & 0x1))
+                       return 0;
+
+               addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
+                       decode_buffer->msg_buffer_address_lo;
+               return vcn_v4_0_dec_msg(p, job, addr);
+       } else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
+               idx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT,
+                       RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET);
+               if (idx >= 0 && ib->ptr[idx + 2] == RENCODE_ENCODE_STANDARD_AV1)
+                       return vcn_v4_0_limit_sched(p, job);
+       }
+       return 0;
 }
 
 static const struct amdgpu_ring_funcs vcn_v4_0_unified_ring_vm_funcs = {
index 8e4b668faa359b3e5cf8461fa981afc431d426ca..e1d63826927a85c9cadfb21db3ad970a8e667273 100644 (file)
@@ -28,7 +28,6 @@
 
 #include "dm_services_types.h"
 #include "dc.h"
-#include "dc_link_dp.h"
 #include "link_enc_cfg.h"
 #include "dc/inc/core_types.h"
 #include "dal_asic_id.h"
@@ -39,6 +38,9 @@
 #include "dc/dc_edid_parser.h"
 #include "dc/dc_stat.h"
 #include "amdgpu_dm_trace.h"
+#include "dpcd_defs.h"
+#include "link/protocols/link_dpcd.h"
+#include "link_service_types.h"
 
 #include "vid.h"
 #include "amdgpu.h"
@@ -1225,10 +1227,25 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
        pa_config->gart_config.page_table_end_addr = page_table_end.quad_part << 12;
        pa_config->gart_config.page_table_base_addr = page_table_base.quad_part;
 
-       pa_config->is_hvm_enabled = 0;
+       pa_config->is_hvm_enabled = adev->mode_info.gpu_vm_support;
 
 }
 
+static void force_connector_state(
+       struct amdgpu_dm_connector *aconnector,
+       enum drm_connector_force force_state)
+{
+       struct drm_connector *connector = &aconnector->base;
+
+       mutex_lock(&connector->dev->mode_config.mutex);
+       aconnector->base.force = force_state;
+       mutex_unlock(&connector->dev->mode_config.mutex);
+
+       mutex_lock(&aconnector->hpd_lock);
+       drm_kms_helper_connector_hotplug_event(connector);
+       mutex_unlock(&aconnector->hpd_lock);
+}
+
 static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
 {
        struct hpd_rx_irq_offload_work *offload_work;
@@ -1237,6 +1254,9 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
        struct amdgpu_device *adev;
        enum dc_connection_type new_connection_type = dc_connection_none;
        unsigned long flags;
+       union test_response test_response;
+
+       memset(&test_response, 0, sizeof(test_response));
 
        offload_work = container_of(work, struct hpd_rx_irq_offload_work, work);
        aconnector = offload_work->offload_wq->aconnector;
@@ -1261,10 +1281,26 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
                goto skip;
 
        mutex_lock(&adev->dm.dc_lock);
-       if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST)
+       if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
                dc_link_dp_handle_automated_test(dc_link);
+
+               if (aconnector->timing_changed) {
+                       /* force connector disconnect and reconnect */
+                       force_connector_state(aconnector, DRM_FORCE_OFF);
+                       msleep(100);
+                       force_connector_state(aconnector, DRM_FORCE_UNSPECIFIED);
+               }
+
+               test_response.bits.ACK = 1;
+
+               core_link_write_dpcd(
+               dc_link,
+               DP_TEST_RESPONSE,
+               &test_response.raw,
+               sizeof(test_response));
+       }
        else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
-                       hpd_rx_irq_check_link_loss_status(dc_link, &offload_work->data) &&
+                       dc_link_check_link_loss_status(dc_link, &offload_work->data) &&
                        dc_link_dp_allow_hpd_rx_irq(dc_link)) {
                dc_link_dp_handle_link_loss(dc_link);
                spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags);
@@ -2197,7 +2233,7 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
        drm_for_each_connector_iter(connector, &iter) {
                aconnector = to_amdgpu_dm_connector(connector);
                if (aconnector->dc_link->type != dc_connection_mst_branch ||
-                   aconnector->mst_port)
+                   aconnector->mst_root)
                        continue;
 
                mgr = &aconnector->mst_mgr;
@@ -2987,6 +3023,10 @@ void amdgpu_dm_update_connector_after_detect(
                                                    aconnector->edid);
                }
 
+               aconnector->timing_requested = kzalloc(sizeof(struct dc_crtc_timing), GFP_KERNEL);
+               if (!aconnector->timing_requested)
+                       dm_error("%s: failed to create aconnector->requested_timing\n", __func__);
+
                drm_connector_update_edid_property(connector, aconnector->edid);
                amdgpu_dm_update_freesync_caps(connector, aconnector->edid);
                update_connector_ext_caps(aconnector);
@@ -2998,6 +3038,8 @@ void amdgpu_dm_update_connector_after_detect(
                dc_sink_release(aconnector->dc_sink);
                aconnector->dc_sink = NULL;
                aconnector->edid = NULL;
+               kfree(aconnector->timing_requested);
+               aconnector->timing_requested = NULL;
 #ifdef CONFIG_DRM_AMD_DC_HDCP
                /* Set CP to DESIRED if it was ENABLED, so we can re-enable it again on hotplug */
                if (connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
@@ -3042,6 +3084,8 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
        if (aconnector->fake_enable)
                aconnector->fake_enable = false;
 
+       aconnector->timing_changed = false;
+
        if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
                DRM_ERROR("KMS: Failed to detect connector\n");
 
@@ -5888,6 +5932,14 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                        stream, &mode, &aconnector->base, con_state, old_stream,
                        requested_bpc);
 
+       if (aconnector->timing_changed) {
+               DC_LOG_DEBUG("%s: overriding timing for automated test, bpc %d, changing to %d\n",
+                               __func__,
+                               stream->timing.display_color_depth,
+                               aconnector->timing_requested->display_color_depth);
+               stream->timing = *aconnector->timing_requested;
+       }
+
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        /* SST DSC determination policy */
        update_dsc_caps(aconnector, sink, stream, &dsc_caps);
@@ -6580,11 +6632,11 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
        int clock, bpp = 0;
        bool is_y420 = false;
 
-       if (!aconnector->port || !aconnector->dc_sink)
+       if (!aconnector->mst_output_port || !aconnector->dc_sink)
                return 0;
 
-       mst_port = aconnector->port;
-       mst_mgr = &aconnector->mst_port->mst_mgr;
+       mst_port = aconnector->mst_output_port;
+       mst_mgr = &aconnector->mst_root->mst_mgr;
 
        if (!crtc_state->connectors_changed && !crtc_state->mode_changed)
                return 0;
@@ -6594,7 +6646,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
                return PTR_ERR(mst_state);
 
        if (!mst_state->pbn_div)
-               mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_port->dc_link);
+               mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_root->dc_link);
 
        if (!state->duplicated) {
                int max_bpc = conn_state->max_requested_bpc;
@@ -6640,7 +6692,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 
                aconnector = to_amdgpu_dm_connector(connector);
 
-               if (!aconnector->port)
+               if (!aconnector->mst_output_port)
                        continue;
 
                if (!new_con_state || !new_con_state->crtc)
@@ -6680,7 +6732,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
                        dm_conn_state->pbn = pbn;
                        dm_conn_state->vcpi_slots = slot_num;
 
-                       ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
+                       ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->mst_output_port,
                                                           dm_conn_state->pbn, false);
                        if (ret < 0)
                                return ret;
@@ -6688,7 +6740,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
                        continue;
                }
 
-               vcpi = drm_dp_mst_atomic_enable_dsc(state, aconnector->port, pbn, true);
+               vcpi = drm_dp_mst_atomic_enable_dsc(state, aconnector->mst_output_port, pbn, true);
                if (vcpi < 0)
                        return vcpi;
 
@@ -7102,7 +7154,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
                                adev->mode_info.underscan_vborder_property,
                                0);
 
-       if (!aconnector->mst_port)
+       if (!aconnector->mst_root)
                drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
 
        /* This defaults to the max in the range, but we want 8bpc for non-edp. */
@@ -7120,7 +7172,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
            connector_type == DRM_MODE_CONNECTOR_eDP) {
                drm_connector_attach_hdr_output_metadata_property(&aconnector->base);
 
-               if (!aconnector->mst_port)
+               if (!aconnector->mst_root)
                        drm_connector_attach_vrr_capable_property(&aconnector->base);
 
 #ifdef CONFIG_DRM_AMD_DC_HDCP
@@ -7604,6 +7656,7 @@ static void update_freesync_state_on_stream(
        new_crtc_state->vrr_infopacket = vrr_infopacket;
 
        new_stream->vrr_infopacket = vrr_infopacket;
+       new_stream->allow_freesync = mod_freesync_get_freesync_enabled(&vrr_params);
 
        if (new_crtc_state->freesync_vrr_info_changed)
                DRM_DEBUG_KMS("VRR packet update: crtc=%u enabled=%d state=%d",
@@ -8818,22 +8871,15 @@ static void get_freesync_config_for_crtc(
        struct drm_display_mode *mode = &new_crtc_state->base.mode;
        int vrefresh = drm_mode_vrefresh(mode);
        bool fs_vid_mode = false;
-       bool drr_active = false;
 
        new_crtc_state->vrr_supported = new_con_state->freesync_capable &&
                                        vrefresh >= aconnector->min_vfreq &&
                                        vrefresh <= aconnector->max_vfreq;
 
-       drr_active = new_crtc_state->vrr_supported &&
-               new_crtc_state->freesync_config.state != VRR_STATE_DISABLED &&
-               new_crtc_state->freesync_config.state != VRR_STATE_INACTIVE &&
-               new_crtc_state->freesync_config.state != VRR_STATE_UNSUPPORTED;
-
-       if (drr_active)
-               new_crtc_state->stream->ignore_msa_timing_param = true;
-
        if (new_crtc_state->vrr_supported) {
+               new_crtc_state->stream->ignore_msa_timing_param = true;
                fs_vid_mode = new_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
+
                config.min_refresh_in_uhz = aconnector->min_vfreq * 1000000;
                config.max_refresh_in_uhz = aconnector->max_vfreq * 1000000;
                config.vsif_supported = true;
@@ -9032,6 +9078,13 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                if (!dm_old_crtc_state->stream)
                        goto skip_modeset;
 
+               /* Unset freesync video if it was active before */
+               if (dm_old_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED) {
+                       dm_new_crtc_state->freesync_config.state = VRR_STATE_INACTIVE;
+                       dm_new_crtc_state->freesync_config.fixed_refresh_in_uhz = 0;
+               }
+
+               /* Now check if we should set freesync video mode */
                if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream &&
                    is_timing_unchanged_for_freesync(new_crtc_state,
                                                     old_crtc_state)) {
@@ -9593,7 +9646,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
                        continue;
 
                aconnector = to_amdgpu_dm_connector(connector);
-               if (!aconnector->port || !aconnector->mst_port)
+               if (!aconnector->mst_output_port || !aconnector->mst_root)
                        aconnector = NULL;
                else
                        break;
@@ -9602,7 +9655,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
        if (!aconnector)
                return 0;
 
-       return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_port->mst_mgr);
+       return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_root->mst_mgr);
 }
 #endif
 
@@ -9648,6 +9701,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        bool lock_and_validation_needed = false;
        struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
 #if defined(CONFIG_DRM_AMD_DC_DCN)
+       struct drm_dp_mst_topology_mgr *mgr;
+       struct drm_dp_mst_topology_state *mst_state;
        struct dsc_mst_fairness_vars vars[MAX_PIPES];
 #endif
 
@@ -9896,6 +9951,28 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                lock_and_validation_needed = true;
        }
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+       /* set the slot info for each mst_state based on the link encoding format */
+       for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
+               struct amdgpu_dm_connector *aconnector;
+               struct drm_connector *connector;
+               struct drm_connector_list_iter iter;
+               u8 link_coding_cap;
+
+               drm_connector_list_iter_begin(dev, &iter);
+               drm_for_each_connector_iter(connector, &iter) {
+                       if (connector->index == mst_state->mgr->conn_base_id) {
+                               aconnector = to_amdgpu_dm_connector(connector);
+                               link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link);
+                               drm_dp_mst_update_slots(mst_state, link_coding_cap);
+
+                               break;
+                       }
+               }
+               drm_connector_list_iter_end(&iter);
+       }
+#endif
+
        /**
         * Streams and planes are reset when there are changes that affect
         * bandwidth. Anything that affects bandwidth needs to go through
@@ -10165,11 +10242,15 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
                struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {
        struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
+       bool ret;
 
+       mutex_lock(&adev->dm.dc_lock);
        if (adev->dm.dmub_srv)
-               return parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info);
+               ret = parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info);
        else
-               return parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info);
+               ret = parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info);
+       mutex_unlock(&adev->dm.dc_lock);
+       return ret;
 }
 
 static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
@@ -10445,6 +10526,7 @@ int amdgpu_dm_process_dmub_aux_transfer_sync(
        ret = p_notify->aux_reply.length;
        *operation_result = p_notify->result;
 out:
+       reinit_completion(&adev->dm.dmub_aux_transfer_done);
        mutex_unlock(&adev->dm.dpia_aux_lock);
        return ret;
 }
@@ -10472,6 +10554,8 @@ int amdgpu_dm_process_dmub_set_config_sync(
                *operation_result = SET_CONFIG_UNKNOWN_ERROR;
        }
 
+       if (!is_cmd_complete)
+               reinit_completion(&adev->dm.dmub_aux_transfer_done);
        mutex_unlock(&adev->dm.dpia_aux_lock);
        return ret;
 }
index abbbb3813c1e7fa75277f1791011ca8bcf9d7cdd..d89f2eaf9117c0bf06fe13cb859c8c28ba754f5d 100644 (file)
@@ -31,6 +31,7 @@
 #include <drm/drm_connector.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_plane.h>
+#include "link_service_types.h"
 
 /*
  * This file contains the definition for amdgpu_display_manager
@@ -604,8 +605,8 @@ struct amdgpu_dm_connector {
        /* DM only */
        struct drm_dp_mst_topology_mgr mst_mgr;
        struct amdgpu_dm_dp_aux dm_dp_aux;
-       struct drm_dp_mst_port *port;
-       struct amdgpu_dm_connector *mst_port;
+       struct drm_dp_mst_port *mst_output_port;
+       struct amdgpu_dm_connector *mst_root;
        struct drm_dp_aux *dsc_aux;
        /* TODO see if we can merge with ddc_bus or make a dm_connector */
        struct amdgpu_i2c_adapter *i2c;
@@ -644,6 +645,10 @@ struct amdgpu_dm_connector {
 
        /* Record progress status of mst*/
        uint8_t mst_status;
+
+       /* Automated testing */
+       bool timing_changed;
+       struct dc_crtc_timing *timing_requested;
 };
 
 static inline void amdgpu_dm_set_mst_status(uint8_t *status,
index 8873ecada27c47a1af2127b942ffe81d6b0f8844..27711743c22ce6d7cfe1576d3a6e2903cf798920 100644 (file)
@@ -344,7 +344,7 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
                        goto cleanup;
                }
 
-               aux = (aconn->port) ? &aconn->port->aux : &aconn->dm_dp_aux.aux;
+               aux = (aconn->mst_output_port) ? &aconn->mst_output_port->aux : &aconn->dm_dp_aux.aux;
 
                if (!aux) {
                        DRM_DEBUG_DRIVER("No dp aux for amd connector\n");
index 704860e6ba84b68925b2687c930450fea4849f5b..e783082a4eef521c592f2790be2fabaeab6db70d 100644 (file)
@@ -34,8 +34,6 @@
 #include "dmub/dmub_srv.h"
 #include "resource.h"
 #include "dsc.h"
-#include "dc_link_dp.h"
-#include "dc_link.h"
 #include "link_hwss.h"
 #include "dc/dc_dmub_srv.h"
 
@@ -1193,7 +1191,7 @@ static int dp_dsc_fec_support_show(struct seq_file *m, void *data)
                        break;
                }
                dpcd_caps = aconnector->dc_link->dpcd_caps;
-               if (aconnector->port) {
+               if (aconnector->mst_output_port) {
                        /* aconnector sets dsc_aux during get_modes call
                         * if MST connector has it means it can either
                         * enable DSC on the sink device or on MST branch
@@ -1280,7 +1278,7 @@ static ssize_t trigger_hotplug(struct file *f, const char __user *buf,
        mutex_lock(&aconnector->hpd_lock);
 
        /* Don't support for mst end device*/
-       if (aconnector->mst_port) {
+       if (aconnector->mst_root) {
                mutex_unlock(&aconnector->hpd_lock);
                return -EINVAL;
        }
@@ -2539,13 +2537,13 @@ static int dp_is_mst_connector_show(struct seq_file *m, void *unused)
 
        if (aconnector->mst_mgr.mst_state) {
                role = "root";
-       } else if (aconnector->mst_port &&
-               aconnector->mst_port->mst_mgr.mst_state) {
+       } else if (aconnector->mst_root &&
+               aconnector->mst_root->mst_mgr.mst_state) {
 
                role = "end";
 
-               mgr = &aconnector->mst_port->mst_mgr;
-               port = aconnector->port;
+               mgr = &aconnector->mst_root->mst_mgr;
+               port = aconnector->mst_output_port;
 
                drm_modeset_lock(&mgr->base.lock, NULL);
                if (port->pdt == DP_PEER_DEVICE_MST_BRANCHING &&
@@ -3392,12 +3390,12 @@ static int trigger_hpd_mst_set(void *data, u64 val)
                        if (!aconnector->dc_link)
                                continue;
 
-                       if (!aconnector->mst_port)
+                       if (!aconnector->mst_root)
                                continue;
 
                        link = aconnector->dc_link;
                        dc_link_dp_receiver_power_ctrl(link, false);
-                       drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_port->mst_mgr, false);
+                       drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_root->mst_mgr, false);
                        link->mst_stream_alloc_table.stream_count = 0;
                        memset(link->mst_stream_alloc_table.stream_allocations, 0,
                                        sizeof(link->mst_stream_alloc_table.stream_allocations));
index 6994c9a1ed85885f6c0d531fedf5be1855bf4301..a50319fc42b11b90bb2ef1566af819384eb93a29 100644 (file)
@@ -38,6 +38,8 @@
 #include "amdgpu_dm.h"
 #include "amdgpu_dm_irq.h"
 #include "amdgpu_dm_mst_types.h"
+#include "dpcd_defs.h"
+#include "dc/inc/core_types.h"
 
 #include "dm_helpers.h"
 #include "ddc_service_types.h"
@@ -120,23 +122,50 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
 }
 
 static void
-fill_dc_mst_payload_table_from_drm(struct drm_dp_mst_topology_state *mst_state,
-                                  struct amdgpu_dm_connector *aconnector,
+fill_dc_mst_payload_table_from_drm(struct dc_link *link,
+                                  bool enable,
+                                  struct drm_dp_mst_atomic_payload *target_payload,
                                   struct dc_dp_mst_stream_allocation_table *table)
 {
        struct dc_dp_mst_stream_allocation_table new_table = { 0 };
        struct dc_dp_mst_stream_allocation *sa;
-       struct drm_dp_mst_atomic_payload *payload;
+       struct link_mst_stream_allocation_table copy_of_link_table =
+                                                                               link->mst_stream_alloc_table;
 
-       /* Fill payload info*/
-       list_for_each_entry(payload, &mst_state->payloads, next) {
-               if (payload->delete)
-                       continue;
+       int i;
+       int current_hw_table_stream_cnt = copy_of_link_table.stream_count;
+       struct link_mst_stream_allocation *dc_alloc;
 
-               sa = &new_table.stream_allocations[new_table.stream_count];
-               sa->slot_count = payload->time_slots;
-               sa->vcp_id = payload->vcpi;
-               new_table.stream_count++;
+       /* TODO: refactor to set link->mst_stream_alloc_table directly if possible.*/
+       if (enable) {
+               dc_alloc =
+               &copy_of_link_table.stream_allocations[current_hw_table_stream_cnt];
+               dc_alloc->vcp_id = target_payload->vcpi;
+               dc_alloc->slot_count = target_payload->time_slots;
+       } else {
+               for (i = 0; i < copy_of_link_table.stream_count; i++) {
+                       dc_alloc =
+                       &copy_of_link_table.stream_allocations[i];
+
+                       if (dc_alloc->vcp_id == target_payload->vcpi) {
+                               dc_alloc->vcp_id = 0;
+                               dc_alloc->slot_count = 0;
+                               break;
+                       }
+               }
+               ASSERT(i != copy_of_link_table.stream_count);
+       }
+
+       /* Fill payload info*/
+       for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
+               dc_alloc =
+                       &copy_of_link_table.stream_allocations[i];
+               if (dc_alloc->vcp_id > 0 && dc_alloc->slot_count > 0) {
+                       sa = &new_table.stream_allocations[new_table.stream_count];
+                       sa->slot_count = dc_alloc->slot_count;
+                       sa->vcp_id = dc_alloc->vcp_id;
+                       new_table.stream_count++;
+               }
        }
 
        /* Overwrite the old table */
@@ -168,14 +197,14 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
         * that blocks before commit guaranteeing that the state
         * is not gonna be swapped while still in use in commit tail */
 
-       if (!aconnector || !aconnector->mst_port)
+       if (!aconnector || !aconnector->mst_root)
                return false;
 
-       mst_mgr = &aconnector->mst_port->mst_mgr;
+       mst_mgr = &aconnector->mst_root->mst_mgr;
        mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);
 
        /* It's OK for this to fail */
-       payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port);
+       payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port);
        if (enable)
                drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
        else
@@ -185,7 +214,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
         * AUX message. The sequence is slot 1-63 allocated sequence for each
         * stream. AMD ASIC stream slot allocation should follow the same
         * sequence. copy DRM MST allocation to dc */
-       fill_dc_mst_payload_table_from_drm(mst_state, aconnector, proposed_table);
+       fill_dc_mst_payload_table_from_drm(stream->link, enable, payload, proposed_table);
 
        return true;
 }
@@ -220,10 +249,10 @@ enum act_return_status dm_helpers_dp_mst_poll_for_allocation_change_trigger(
 
        aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
-       if (!aconnector || !aconnector->mst_port)
+       if (!aconnector || !aconnector->mst_root)
                return ACT_FAILED;
 
-       mst_mgr = &aconnector->mst_port->mst_mgr;
+       mst_mgr = &aconnector->mst_root->mst_mgr;
 
        if (!mst_mgr->mst_state)
                return ACT_FAILED;
@@ -247,22 +276,27 @@ bool dm_helpers_dp_mst_send_payload_allocation(
        struct drm_dp_mst_atomic_payload *payload;
        enum mst_progress_status set_flag = MST_ALLOCATE_NEW_PAYLOAD;
        enum mst_progress_status clr_flag = MST_CLEAR_ALLOCATED_PAYLOAD;
+       int ret = 0;
 
        aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
-       if (!aconnector || !aconnector->mst_port)
+       if (!aconnector || !aconnector->mst_root)
                return false;
 
-       mst_mgr = &aconnector->mst_port->mst_mgr;
+       mst_mgr = &aconnector->mst_root->mst_mgr;
        mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);
 
-       payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port);
+       payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port);
+
        if (!enable) {
                set_flag = MST_CLEAR_ALLOCATED_PAYLOAD;
                clr_flag = MST_ALLOCATE_NEW_PAYLOAD;
        }
 
-       if (enable && drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, payload)) {
+       if (enable)
+               ret = drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, payload);
+
+       if (ret) {
                amdgpu_dm_set_mst_status(&aconnector->mst_status,
                        set_flag, false);
        } else {
@@ -683,7 +717,7 @@ bool dm_helpers_dp_write_dsc_enable(
                                aconnector->dsc_aux, stream, enable_dsc);
 #endif
 
-               port = aconnector->port;
+               port = aconnector->mst_output_port;
 
                if (enable) {
                        if (port->passthrough_aux) {
@@ -960,6 +994,128 @@ void dm_helpers_mst_enable_stream_features(const struct dc_stream_state *stream)
                                         sizeof(new_downspread));
 }
 
+bool dm_helpers_dp_handle_test_pattern_request(
+               struct dc_context *ctx,
+               const struct dc_link *link,
+               union link_test_pattern dpcd_test_pattern,
+               union test_misc dpcd_test_params)
+{
+       enum dp_test_pattern test_pattern;
+       enum dp_test_pattern_color_space test_pattern_color_space =
+                       DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
+       enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
+       enum dc_pixel_encoding requestPixelEncoding = PIXEL_ENCODING_UNDEFINED;
+       struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
+       struct pipe_ctx *pipe_ctx = NULL;
+       struct amdgpu_dm_connector *aconnector = link->priv;
+       int i;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               if (pipes[i].stream == NULL)
+                       continue;
+
+               if (pipes[i].stream->link == link && !pipes[i].top_pipe &&
+                       !pipes[i].prev_odm_pipe) {
+                       pipe_ctx = &pipes[i];
+                       break;
+               }
+       }
+
+       if (pipe_ctx == NULL)
+               return false;
+
+       switch (dpcd_test_pattern.bits.PATTERN) {
+       case LINK_TEST_PATTERN_COLOR_RAMP:
+               test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
+       break;
+       case LINK_TEST_PATTERN_VERTICAL_BARS:
+               test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
+       break; /* black and white */
+       case LINK_TEST_PATTERN_COLOR_SQUARES:
+               test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
+                               TEST_DYN_RANGE_VESA ?
+                               DP_TEST_PATTERN_COLOR_SQUARES :
+                               DP_TEST_PATTERN_COLOR_SQUARES_CEA);
+       break;
+       default:
+               test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
+       break;
+       }
+
+       if (dpcd_test_params.bits.CLR_FORMAT == 0)
+               test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
+       else
+               test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
+                               DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
+                               DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
+
+       switch (dpcd_test_params.bits.BPC) {
+       case 0: // 6 bits
+               requestColorDepth = COLOR_DEPTH_666;
+               break;
+       case 1: // 8 bits
+               requestColorDepth = COLOR_DEPTH_888;
+               break;
+       case 2: // 10 bits
+               requestColorDepth = COLOR_DEPTH_101010;
+               break;
+       case 3: // 12 bits
+               requestColorDepth = COLOR_DEPTH_121212;
+               break;
+       default:
+               break;
+       }
+
+       switch (dpcd_test_params.bits.CLR_FORMAT) {
+       case 0:
+               requestPixelEncoding = PIXEL_ENCODING_RGB;
+               break;
+       case 1:
+               requestPixelEncoding = PIXEL_ENCODING_YCBCR422;
+               break;
+       case 2:
+               requestPixelEncoding = PIXEL_ENCODING_YCBCR444;
+               break;
+       default:
+               requestPixelEncoding = PIXEL_ENCODING_RGB;
+               break;
+       }
+
+       if ((requestColorDepth != COLOR_DEPTH_UNDEFINED
+               && pipe_ctx->stream->timing.display_color_depth != requestColorDepth)
+               || (requestPixelEncoding != PIXEL_ENCODING_UNDEFINED
+               && pipe_ctx->stream->timing.pixel_encoding != requestPixelEncoding)) {
+               DC_LOG_DEBUG("%s: original bpc %d pix encoding %d, changing to %d  %d\n",
+                               __func__,
+                               pipe_ctx->stream->timing.display_color_depth,
+                               pipe_ctx->stream->timing.pixel_encoding,
+                               requestColorDepth,
+                               requestPixelEncoding);
+               pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
+               pipe_ctx->stream->timing.pixel_encoding = requestPixelEncoding;
+
+               dp_update_dsc_config(pipe_ctx);
+
+               aconnector->timing_changed = true;
+               /* store current timing */
+               if (aconnector->timing_requested)
+                       *aconnector->timing_requested = pipe_ctx->stream->timing;
+               else
+                       DC_LOG_ERROR("%s: timing storage failed\n", __func__);
+
+       }
+
+       dc_link_dp_set_test_pattern(
+               (struct dc_link *) link,
+               test_pattern,
+               test_pattern_color_space,
+               NULL,
+               NULL,
+               0);
+
+       return false;
+}
+
 void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz)
 {
        // TODO
index 5fa9bab95038461a36f140b792b7427d1071007f..0bff2cc20b02e19f52639ceb37e2e284b3896145 100644 (file)
@@ -39,7 +39,6 @@
 #include "dc.h"
 #include "dm_helpers.h"
 
-#include "dc_link_dp.h"
 #include "ddc_service_types.h"
 #include "dpcd_defs.h"
 
@@ -134,7 +133,7 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector)
        kfree(aconnector->edid);
 
        drm_connector_cleanup(connector);
-       drm_dp_mst_put_port_malloc(aconnector->port);
+       drm_dp_mst_put_port_malloc(aconnector->mst_output_port);
        kfree(aconnector);
 }
 
@@ -146,7 +145,7 @@ amdgpu_dm_mst_connector_late_register(struct drm_connector *connector)
        int r;
 
        r = drm_dp_mst_connector_late_register(connector,
-                                              amdgpu_dm_connector->port);
+                                              amdgpu_dm_connector->mst_output_port);
        if (r < 0)
                return r;
 
@@ -162,8 +161,8 @@ amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
 {
        struct amdgpu_dm_connector *aconnector =
                to_amdgpu_dm_connector(connector);
-       struct drm_dp_mst_port *port = aconnector->port;
-       struct amdgpu_dm_connector *root = aconnector->mst_port;
+       struct drm_dp_mst_port *port = aconnector->mst_output_port;
+       struct amdgpu_dm_connector *root = aconnector->mst_root;
        struct dc_link *dc_link = aconnector->dc_link;
        struct dc_sink *dc_sink = aconnector->dc_sink;
 
@@ -213,7 +212,7 @@ bool needs_dsc_aux_workaround(struct dc_link *link)
 static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnector)
 {
        struct dc_sink *dc_sink = aconnector->dc_sink;
-       struct drm_dp_mst_port *port = aconnector->port;
+       struct drm_dp_mst_port *port = aconnector->mst_output_port;
        u8 dsc_caps[16] = { 0 };
        u8 dsc_branch_dec_caps_raw[3] = { 0 };  // DSC branch decoder caps 0xA0 ~ 0xA2
        u8 *dsc_branch_dec_caps = NULL;
@@ -231,7 +230,7 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto
         */
        if (!aconnector->dsc_aux && !port->parent->port_parent &&
            needs_dsc_aux_workaround(aconnector->dc_link))
-               aconnector->dsc_aux = &aconnector->mst_port->dm_dp_aux.aux;
+               aconnector->dsc_aux = &aconnector->mst_root->dm_dp_aux.aux;
 
        if (!aconnector->dsc_aux)
                return false;
@@ -281,7 +280,7 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
 
        if (!aconnector->edid) {
                struct edid *edid;
-               edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port);
+               edid = drm_dp_mst_get_edid(connector, &aconnector->mst_root->mst_mgr, aconnector->mst_output_port);
 
                if (!edid) {
                        amdgpu_dm_set_mst_status(&aconnector->mst_status,
@@ -410,15 +409,15 @@ dm_dp_mst_detect(struct drm_connector *connector,
                 struct drm_modeset_acquire_ctx *ctx, bool force)
 {
        struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
-       struct amdgpu_dm_connector *master = aconnector->mst_port;
-       struct drm_dp_mst_port *port = aconnector->port;
+       struct amdgpu_dm_connector *master = aconnector->mst_root;
+       struct drm_dp_mst_port *port = aconnector->mst_output_port;
        int connection_status;
 
        if (drm_connector_is_unregistered(connector))
                return connector_status_disconnected;
 
        connection_status = drm_dp_mst_detect_port(connector, ctx, &master->mst_mgr,
-                                                       aconnector->port);
+                                                       aconnector->mst_output_port);
 
        if (port->pdt != DP_PEER_DEVICE_NONE && !port->dpcd_rev) {
                uint8_t dpcd_rev;
@@ -475,8 +474,8 @@ static int dm_dp_mst_atomic_check(struct drm_connector *connector,
                                  struct drm_atomic_state *state)
 {
        struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
-       struct drm_dp_mst_topology_mgr *mst_mgr = &aconnector->mst_port->mst_mgr;
-       struct drm_dp_mst_port *mst_port = aconnector->port;
+       struct drm_dp_mst_topology_mgr *mst_mgr = &aconnector->mst_root->mst_mgr;
+       struct drm_dp_mst_port *mst_port = aconnector->mst_output_port;
 
        return drm_dp_atomic_release_time_slots(state, mst_mgr, mst_port);
 }
@@ -538,8 +537,8 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
                return NULL;
 
        connector = &aconnector->base;
-       aconnector->port = port;
-       aconnector->mst_port = master;
+       aconnector->mst_output_port = port;
+       aconnector->mst_root = master;
        amdgpu_dm_set_mst_status(&aconnector->mst_status,
                        MST_PROBE, true);
 
@@ -927,11 +926,6 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
        if (IS_ERR(mst_state))
                return PTR_ERR(mst_state);
 
-       mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
-#if defined(CONFIG_DRM_AMD_DC_DCN)
-       drm_dp_mst_update_slots(mst_state, dc_link_dp_mst_decide_link_encoding_format(dc_link));
-#endif
-
        /* Set up params */
        for (i = 0; i < dc_state->stream_count; i++) {
                struct dc_dsc_policy dsc_policy = {0};
@@ -945,7 +939,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
                if (!aconnector)
                        continue;
 
-               if (!aconnector->port)
+               if (!aconnector->mst_output_port)
                        continue;
 
                stream->timing.flags.DSC = 0;
@@ -953,7 +947,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
                params[count].timing = &stream->timing;
                params[count].sink = stream->sink;
                params[count].aconnector = aconnector;
-               params[count].port = aconnector->port;
+               params[count].port = aconnector->mst_output_port;
                params[count].clock_force_enable = aconnector->dsc_settings.dsc_force_enable;
                if (params[count].clock_force_enable == DSC_CLK_FORCE_ENABLE)
                        debugfs_overwrite = true;
@@ -1162,7 +1156,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
                aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
-               if (!aconnector || !aconnector->dc_sink || !aconnector->port)
+               if (!aconnector || !aconnector->dc_sink || !aconnector->mst_output_port)
                        continue;
 
                if (!aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported)
@@ -1177,7 +1171,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
                if (!is_dsc_need_re_compute(state, dc_state, stream->link))
                        continue;
 
-               mst_mgr = aconnector->port->mgr;
+               mst_mgr = aconnector->mst_output_port->mgr;
                ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
                                                       &link_vars_start_index);
                if (ret != 0)
@@ -1223,7 +1217,7 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
                aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
-               if (!aconnector || !aconnector->dc_sink || !aconnector->port)
+               if (!aconnector || !aconnector->dc_sink || !aconnector->mst_output_port)
                        continue;
 
                if (!aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported)
@@ -1235,7 +1229,7 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
                if (!is_dsc_need_re_compute(state, dc_state, stream->link))
                        continue;
 
-               mst_mgr = aconnector->port->mgr;
+               mst_mgr = aconnector->mst_output_port->mgr;
                ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
                                                       &link_vars_start_index);
                if (ret != 0)
@@ -1450,8 +1444,8 @@ enum dc_status dm_dp_mst_is_port_support_mode(
         * with DSC enabled.
         */
        if (is_dsc_common_config_possible(stream, &bw_range) &&
-           aconnector->port->passthrough_aux) {
-               mst_mgr = aconnector->port->mgr;
+           aconnector->mst_output_port->passthrough_aux) {
+               mst_mgr = aconnector->mst_output_port->mgr;
                mutex_lock(&mst_mgr->lock);
 
                cur_link_settings = stream->link->verified_link_cap;
@@ -1459,7 +1453,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
                upper_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link,
                                                               &cur_link_settings
                                                               );
-               down_link_bw_in_kbps = kbps_from_pbn(aconnector->port->full_pbn);
+               down_link_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn);
 
                /* pick the bottleneck */
                end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps,
@@ -1483,7 +1477,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
                bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3;
                pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false);
 
-               if (pbn > aconnector->port->full_pbn)
+               if (pbn > aconnector->mst_output_port->full_pbn)
                        return DC_FAIL_BANDWIDTH_VALIDATE;
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        }
index 872d06fe14364ad1baa9fc706511e980b7ed9874..d647f68fd5630e9609c27dabe2890f6776ef821a 100644 (file)
@@ -122,7 +122,7 @@ bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream)
                psr_config.allow_multi_disp_optimizations =
                        (amdgpu_dc_feature_mask & DC_PSR_ALLOW_MULTI_DISP_OPT);
 
-               if (!psr_su_set_y_granularity(dc, link, stream, &psr_config))
+               if (!psr_su_set_dsc_slice_height(dc, link, stream, &psr_config))
                        return false;
 
                ret = dc_link_setup_psr(link, stream, &psr_config, &psr_context);
index 98c508313350ac6ec80e2c843428eee3c88904d2..fec32e20f8548c23ee38ad19705ccacd8abe8da9 100644 (file)
@@ -65,8 +65,7 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI
 include $(AMD_DC)
 
 DISPLAY_CORE = dc.o dc_stat.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \
-dc_surface.o dc_link_dp.o dc_debug.o dc_stream.o \
-dc_link_enc_cfg.o
+dc_surface.o dc_debug.o dc_stream.o dc_link_enc_cfg.o
 
 DISPLAY_CORE += dc_vm_helper.o
 
index f276abb63bcd7ce4ea2a0e3d7e6beea1581b9d98..69691daf4dbbd12f82b54649c2489335fd55a506 100644 (file)
@@ -29,6 +29,7 @@
 #include "dc_types.h"
 #include "dccg.h"
 #include "clk_mgr_internal.h"
+#include "link.h"
 
 #include "dce100/dce_clk_mgr.h"
 #include "dce110/dce110_clk_mgr.h"
index 1c0569b1dc8f0c8df9076032b39a89e862f31e4d..f9e2e0c3095e7c652fae5c70823a8531a15218e3 100644 (file)
@@ -47,6 +47,7 @@
 #include "dcn30/dcn30_clk_mgr.h"
 
 #include "dc_dmub_srv.h"
+#include "link.h"
 
 #include "logger_types.h"
 #undef DC_LOGGER
index 20a06c04e4a1d63f9d710c8f424a67956b154aed..89df7244b272863b97151172f853fce66f7e06c1 100644 (file)
@@ -48,7 +48,7 @@
 #include "dcn31/dcn31_clk_mgr.h"
 
 #include "dc_dmub_srv.h"
-#include "dc_link_dp.h"
+#include "link.h"
 #include "dcn314_smu.h"
 
 
index 07edd9777edfb11eded1c711346ae793ed599b24..8c368bcc8e7e7a543b28507f5bed01a2dc862c26 100644 (file)
@@ -46,7 +46,7 @@
 #define DC_LOGGER \
        clk_mgr->base.base.ctx->logger
 
-#include "dc_link_dp.h"
+#include "link.h"
 
 #define TO_CLK_MGR_DCN315(clk_mgr)\
        container_of(clk_mgr, struct clk_mgr_dcn315, base)
@@ -87,6 +87,16 @@ static int dcn315_get_active_display_cnt_wa(
        return display_count;
 }
 
+bool should_disable_otg(struct pipe_ctx *pipe)
+{
+       bool ret = true;
+
+       if (pipe->stream->link->link_enc && pipe->stream->link->link_enc->funcs->is_dig_enabled &&
+                       pipe->stream->link->link_enc->funcs->is_dig_enabled(pipe->stream->link->link_enc))
+               ret = false;
+       return ret;
+}
+
 static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable)
 {
        struct dc *dc = clk_mgr_base->ctx->dc;
@@ -98,12 +108,16 @@ static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state
                if (pipe->top_pipe || pipe->prev_odm_pipe)
                        continue;
                if (pipe->stream && (pipe->stream->dpms_off || pipe->plane_state == NULL ||
-                                    dc_is_virtual_signal(pipe->stream->signal))) {
-                       if (disable) {
-                               pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
-                               reset_sync_context_for_pipe(dc, context, i);
-                       } else
-                               pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
+                                       dc_is_virtual_signal(pipe->stream->signal))) {
+
+                       /* This w/a should not trigger when we have a dig active */
+                       if (should_disable_otg(pipe)) {
+                               if (disable) {
+                                       pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
+                                       reset_sync_context_for_pipe(dc, context, i);
+                               } else
+                                       pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
+                       }
                }
        }
 }
index 3edc81e2d417ad99bdd23539d69c415418815458..93db4dbee713e5f1de73571777b37053d1a8f386 100644 (file)
@@ -39,7 +39,7 @@
 #include "dcn316_smu.h"
 #include "dm_helpers.h"
 #include "dc_dmub_srv.h"
-#include "dc_link_dp.h"
+#include "link.h"
 
 // DCN316 this is CLK1 instance
 #define MAX_INSTANCE                                        7
index 352c977d1495a39f821725683521f53e103e51de..61768bf726f8cb91e2b26c660899622fe9abe9e1 100644 (file)
@@ -33,7 +33,6 @@
 #include "reg_helper.h"
 #include "core_types.h"
 #include "dm_helpers.h"
-#include "dc_link_dp.h"
 #include "link.h"
 
 #include "atomfirmware.h"
index 53e586fc150102bb0613e52d83ddebc03e0603fa..f11bc8d9d0c4035e3bec711e36cf1ebae1346cf8 100644 (file)
@@ -58,7 +58,6 @@
 #include "dm_helpers.h"
 #include "mem_input.h"
 
-#include "dc_link_dp.h"
 #include "dc_dmub_srv.h"
 
 #include "dsc.h"
@@ -1659,7 +1658,7 @@ bool dc_validate_boot_timing(const struct dc *dc,
                return false;
        }
 
-       if (is_edp_ilr_optimization_required(link, crtc_timing)) {
+       if (link_is_edp_ilr_optimization_required(link, crtc_timing)) {
                DC_LOG_EVENT_LINK_TRAINING("Seamless boot disabled to optimize eDP link rate\n");
                return false;
        }
@@ -2960,6 +2959,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
        if (update->vsp_infopacket)
                stream->vsp_infopacket = *update->vsp_infopacket;
 
+       if (update->adaptive_sync_infopacket)
+               stream->adaptive_sync_infopacket = *update->adaptive_sync_infopacket;
+
        if (update->dither_option)
                stream->dither_option = *update->dither_option;
 
@@ -3165,6 +3167,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
                                        stream_update->vsc_infopacket ||
                                        stream_update->vsp_infopacket ||
                                        stream_update->hfvsif_infopacket ||
+                                       stream_update->adaptive_sync_infopacket ||
                                        stream_update->vtem_infopacket) {
                                resource_build_info_frame(pipe_ctx);
                                dc->hwss.update_info_frame(pipe_ctx);
index d9e490eca10f41b203c77a41c16d572fd9158486..6475664baa8a2ec17412ae0eeaf63c3126316027 100644 (file)
@@ -32,9 +32,8 @@
 #include "grph_object_id.h"
 #include "gpio_service_interface.h"
 #include "core_status.h"
-#include "dc_link_dp.h"
-#include "link/link_dp_dpia.h"
-#include "link/link_ddc.h"
+#include "link/protocols/link_dp_dpia.h"
+#include "link/protocols/link_ddc.h"
 #include "link_hwss.h"
 #include "link.h"
 #include "opp.h"
 #include "fixed31_32.h"
 #include "dpcd_defs.h"
 #include "dmcu.h"
+#include "dsc.h"
+#include "opp.h"
 #include "hw/clk_mgr.h"
 #include "dce/dmub_psr.h"
 #include "dmub/dmub_srv.h"
 #include "inc/hw/panel_cntl.h"
 #include "inc/link_enc_cfg.h"
-#include "link/link_dpcd.h"
-#include "link/link_dp_trace.h"
-#include "link/link_hpd.h"
-#include "link/link_dp_training.h"
-#include "link/link_dp_phy.h"
-#include "link/link_dp_capability.h"
+#include "link/protocols/link_dpcd.h"
+#include "link/accessories/link_dp_trace.h"
+#include "link/protocols/link_hpd.h"
+#include "link/protocols/link_dp_training.h"
+#include "link/protocols/link_dp_phy.h"
+#include "link/protocols/link_dp_capability.h"
+#include "link/protocols/link_edp_panel_control.h"
 
 #include "dc/dcn30/dcn30_vpg.h"
 
@@ -107,17 +109,6 @@ static void dc_link_destruct(struct dc_link *link)
                dc_sink_release(link->remote_sinks[i]);
 }
 
-bool dc_link_wait_for_t12(struct dc_link *link)
-{
-       if (link->connector_signal == SIGNAL_TYPE_EDP && link->dc->hwss.edp_wait_for_T12) {
-               link->dc->hwss.edp_wait_for_T12(link);
-
-               return true;
-       }
-
-       return false;
-}
-
 /**
  * dc_link_detect_sink() - Determine if there is a sink connected
  *
@@ -1094,7 +1085,7 @@ static bool detect_link_and_local_sink(struct dc_link *link,
                        (link->dpcd_sink_ext_caps.bits.oled == 1)) {
                        dpcd_set_source_specific_data(link);
                        msleep(post_oui_delay);
-                       dc_link_set_default_brightness_aux(link);
+                       set_default_brightness_aux(link);
                        //TODO: use cached
                }
 
@@ -2067,10 +2058,10 @@ static enum dc_status enable_link_dp(struct dc_state *state,
        if (link->dpcd_sink_ext_caps.bits.oled == 1 ||
                link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1 ||
                link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1) {
-               dc_link_set_default_brightness_aux(link); // TODO: use cached if known
+               set_default_brightness_aux(link); // TODO: use cached if known
                if (link->dpcd_sink_ext_caps.bits.oled == 1)
                        msleep(bl_oled_enable_delay);
-               dc_link_backlight_enable_aux(link, true);
+               link_backlight_enable_aux(link, true);
        }
 
        return status;
@@ -2740,22 +2731,6 @@ static void enable_link_lvds(struct pipe_ctx *pipe_ctx)
 
 }
 
-bool dc_power_alpm_dpcd_enable(struct dc_link *link, bool enable)
-{
-       bool ret = false;
-       union dpcd_alpm_configuration alpm_config;
-
-       if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
-               memset(&alpm_config, 0, sizeof(alpm_config));
-
-               alpm_config.bits.ENABLE = (enable ? true : false);
-               ret = dm_helpers_dp_write_dpcd(link->ctx, link,
-                               DP_RECEIVER_ALPM_CONFIG, &alpm_config.raw,
-                               sizeof(alpm_config.raw));
-       }
-       return ret;
-}
-
 /****************************enable_link***********************************/
 static enum dc_status enable_link(
                struct dc_state *state,
@@ -3035,436 +3010,6 @@ enum dc_status dc_link_validate_mode_timing(
        return DC_OK;
 }
 
-static struct abm *get_abm_from_stream_res(const struct dc_link *link)
-{
-       int i;
-       struct dc *dc = NULL;
-       struct abm *abm = NULL;
-
-       if (!link || !link->ctx)
-               return NULL;
-
-       dc = link->ctx->dc;
-
-       for (i = 0; i < MAX_PIPES; i++) {
-               struct pipe_ctx pipe_ctx = dc->current_state->res_ctx.pipe_ctx[i];
-               struct dc_stream_state *stream = pipe_ctx.stream;
-
-               if (stream && stream->link == link) {
-                       abm = pipe_ctx.stream_res.abm;
-                       break;
-               }
-       }
-       return abm;
-}
-
-int dc_link_get_backlight_level(const struct dc_link *link)
-{
-       struct abm *abm = get_abm_from_stream_res(link);
-       struct panel_cntl *panel_cntl = link->panel_cntl;
-       struct dc  *dc = link->ctx->dc;
-       struct dmcu *dmcu = dc->res_pool->dmcu;
-       bool fw_set_brightness = true;
-
-       if (dmcu)
-               fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
-
-       if (!fw_set_brightness && panel_cntl->funcs->get_current_backlight)
-               return panel_cntl->funcs->get_current_backlight(panel_cntl);
-       else if (abm != NULL && abm->funcs->get_current_backlight != NULL)
-               return (int) abm->funcs->get_current_backlight(abm);
-       else
-               return DC_ERROR_UNEXPECTED;
-}
-
-int dc_link_get_target_backlight_pwm(const struct dc_link *link)
-{
-       struct abm *abm = get_abm_from_stream_res(link);
-
-       if (abm == NULL || abm->funcs->get_target_backlight == NULL)
-               return DC_ERROR_UNEXPECTED;
-
-       return (int) abm->funcs->get_target_backlight(abm);
-}
-
-static struct pipe_ctx *get_pipe_from_link(const struct dc_link *link)
-{
-       int i;
-       struct dc *dc = link->ctx->dc;
-       struct pipe_ctx *pipe_ctx = NULL;
-
-       for (i = 0; i < MAX_PIPES; i++) {
-               if (dc->current_state->res_ctx.pipe_ctx[i].stream) {
-                       if (dc->current_state->res_ctx.pipe_ctx[i].stream->link == link) {
-                               pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
-                               break;
-                       }
-               }
-       }
-
-       return pipe_ctx;
-}
-
-bool dc_link_set_backlight_level(const struct dc_link *link,
-               uint32_t backlight_pwm_u16_16,
-               uint32_t frame_ramp)
-{
-       struct dc  *dc = link->ctx->dc;
-
-       DC_LOGGER_INIT(link->ctx->logger);
-       DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
-                       backlight_pwm_u16_16, backlight_pwm_u16_16);
-
-       if (dc_is_embedded_signal(link->connector_signal)) {
-               struct pipe_ctx *pipe_ctx = get_pipe_from_link(link);
-
-               if (pipe_ctx) {
-                       /* Disable brightness ramping when the display is blanked
-                        * as it can hang the DMCU
-                        */
-                       if (pipe_ctx->plane_state == NULL)
-                               frame_ramp = 0;
-               } else {
-                       return false;
-               }
-
-               dc->hwss.set_backlight_level(
-                               pipe_ctx,
-                               backlight_pwm_u16_16,
-                               frame_ramp);
-       }
-       return true;
-}
-
-bool dc_link_set_psr_allow_active(struct dc_link *link, const bool *allow_active,
-               bool wait, bool force_static, const unsigned int *power_opts)
-{
-       struct dc  *dc = link->ctx->dc;
-       struct dmcu *dmcu = dc->res_pool->dmcu;
-       struct dmub_psr *psr = dc->res_pool->psr;
-       unsigned int panel_inst;
-
-       if (psr == NULL && force_static)
-               return false;
-
-       if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
-               return false;
-
-       if ((allow_active != NULL) && (*allow_active == true) && (link->type == dc_connection_none)) {
-               // Don't enter PSR if panel is not connected
-               return false;
-       }
-
-       /* Set power optimization flag */
-       if (power_opts && link->psr_settings.psr_power_opt != *power_opts) {
-               link->psr_settings.psr_power_opt = *power_opts;
-
-               if (psr != NULL && link->psr_settings.psr_feature_enabled && psr->funcs->psr_set_power_opt)
-                       psr->funcs->psr_set_power_opt(psr, link->psr_settings.psr_power_opt, panel_inst);
-       }
-
-       if (psr != NULL && link->psr_settings.psr_feature_enabled &&
-                       force_static && psr->funcs->psr_force_static)
-               psr->funcs->psr_force_static(psr, panel_inst);
-
-       /* Enable or Disable PSR */
-       if (allow_active && link->psr_settings.psr_allow_active != *allow_active) {
-               link->psr_settings.psr_allow_active = *allow_active;
-
-               if (!link->psr_settings.psr_allow_active)
-                       dc_z10_restore(dc);
-
-               if (psr != NULL && link->psr_settings.psr_feature_enabled) {
-                       psr->funcs->psr_enable(psr, link->psr_settings.psr_allow_active, wait, panel_inst);
-               } else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) &&
-                       link->psr_settings.psr_feature_enabled)
-                       dmcu->funcs->set_psr_enable(dmcu, link->psr_settings.psr_allow_active, wait);
-               else
-                       return false;
-       }
-
-       return true;
-}
-
-bool dc_link_get_psr_state(const struct dc_link *link, enum dc_psr_state *state)
-{
-       struct dc  *dc = link->ctx->dc;
-       struct dmcu *dmcu = dc->res_pool->dmcu;
-       struct dmub_psr *psr = dc->res_pool->psr;
-       unsigned int panel_inst;
-
-       if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
-               return false;
-
-       if (psr != NULL && link->psr_settings.psr_feature_enabled)
-               psr->funcs->psr_get_state(psr, state, panel_inst);
-       else if (dmcu != NULL && link->psr_settings.psr_feature_enabled)
-               dmcu->funcs->get_psr_state(dmcu, state);
-
-       return true;
-}
-
-static inline enum physical_phy_id
-transmitter_to_phy_id(enum transmitter transmitter_value)
-{
-       switch (transmitter_value) {
-       case TRANSMITTER_UNIPHY_A:
-               return PHYLD_0;
-       case TRANSMITTER_UNIPHY_B:
-               return PHYLD_1;
-       case TRANSMITTER_UNIPHY_C:
-               return PHYLD_2;
-       case TRANSMITTER_UNIPHY_D:
-               return PHYLD_3;
-       case TRANSMITTER_UNIPHY_E:
-               return PHYLD_4;
-       case TRANSMITTER_UNIPHY_F:
-               return PHYLD_5;
-       case TRANSMITTER_NUTMEG_CRT:
-               return PHYLD_6;
-       case TRANSMITTER_TRAVIS_CRT:
-               return PHYLD_7;
-       case TRANSMITTER_TRAVIS_LCD:
-               return PHYLD_8;
-       case TRANSMITTER_UNIPHY_G:
-               return PHYLD_9;
-       case TRANSMITTER_COUNT:
-               return PHYLD_COUNT;
-       case TRANSMITTER_UNKNOWN:
-               return PHYLD_UNKNOWN;
-       default:
-               WARN_ONCE(1, "Unknown transmitter value %d\n",
-                         transmitter_value);
-               return PHYLD_UNKNOWN;
-       }
-}
-
-bool dc_link_setup_psr(struct dc_link *link,
-               const struct dc_stream_state *stream, struct psr_config *psr_config,
-               struct psr_context *psr_context)
-{
-       struct dc *dc;
-       struct dmcu *dmcu;
-       struct dmub_psr *psr;
-       int i;
-       unsigned int panel_inst;
-       /* updateSinkPsrDpcdConfig*/
-       union dpcd_psr_configuration psr_configuration;
-       union dpcd_sink_active_vtotal_control_mode vtotal_control = {0};
-
-       psr_context->controllerId = CONTROLLER_ID_UNDEFINED;
-
-       if (!link)
-               return false;
-
-       dc = link->ctx->dc;
-       dmcu = dc->res_pool->dmcu;
-       psr = dc->res_pool->psr;
-
-       if (!dmcu && !psr)
-               return false;
-
-       if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
-               return false;
-
-
-       memset(&psr_configuration, 0, sizeof(psr_configuration));
-
-       psr_configuration.bits.ENABLE                    = 1;
-       psr_configuration.bits.CRC_VERIFICATION          = 1;
-       psr_configuration.bits.FRAME_CAPTURE_INDICATION  =
-                       psr_config->psr_frame_capture_indication_req;
-
-       /* Check for PSR v2*/
-       if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
-               /* For PSR v2 selective update.
-                * Indicates whether sink should start capturing
-                * immediately following active scan line,
-                * or starting with the 2nd active scan line.
-                */
-               psr_configuration.bits.LINE_CAPTURE_INDICATION = 0;
-               /*For PSR v2, determines whether Sink should generate
-                * IRQ_HPD when CRC mismatch is detected.
-                */
-               psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR    = 1;
-               /* For PSR v2, set the bit when the Source device will
-                * be enabling PSR2 operation.
-                */
-               psr_configuration.bits.ENABLE_PSR2    = 1;
-               /* For PSR v2, the Sink device must be able to receive
-                * SU region updates early in the frame time.
-                */
-               psr_configuration.bits.EARLY_TRANSPORT_ENABLE    = 1;
-       }
-
-       dm_helpers_dp_write_dpcd(
-               link->ctx,
-               link,
-               368,
-               &psr_configuration.raw,
-               sizeof(psr_configuration.raw));
-
-       if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
-               dc_power_alpm_dpcd_enable(link, true);
-               psr_context->su_granularity_required =
-                       psr_config->su_granularity_required;
-               psr_context->su_y_granularity =
-                       psr_config->su_y_granularity;
-               psr_context->line_time_in_us =
-                       psr_config->line_time_in_us;
-
-               if (link->psr_settings.psr_vtotal_control_support) {
-                       psr_context->rate_control_caps = psr_config->rate_control_caps;
-                       vtotal_control.bits.ENABLE = true;
-                       core_link_write_dpcd(link, DP_SINK_PSR_ACTIVE_VTOTAL_CONTROL_MODE,
-                                                       &vtotal_control.raw, sizeof(vtotal_control.raw));
-               }
-       }
-
-       psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel;
-       psr_context->transmitterId = link->link_enc->transmitter;
-       psr_context->engineId = link->link_enc->preferred_engine;
-
-       for (i = 0; i < MAX_PIPES; i++) {
-               if (dc->current_state->res_ctx.pipe_ctx[i].stream
-                               == stream) {
-                       /* dmcu -1 for all controller id values,
-                        * therefore +1 here
-                        */
-                       psr_context->controllerId =
-                               dc->current_state->res_ctx.
-                               pipe_ctx[i].stream_res.tg->inst + 1;
-                       break;
-               }
-       }
-
-       /* Hardcoded for now.  Can be Pcie or Uniphy (or Unknown)*/
-       psr_context->phyType = PHY_TYPE_UNIPHY;
-       /*PhyId is associated with the transmitter id*/
-       psr_context->smuPhyId =
-               transmitter_to_phy_id(link->link_enc->transmitter);
-
-       psr_context->crtcTimingVerticalTotal = stream->timing.v_total;
-       psr_context->vsync_rate_hz = div64_u64(div64_u64((stream->
-                                       timing.pix_clk_100hz * 100),
-                                       stream->timing.v_total),
-                                       stream->timing.h_total);
-
-       psr_context->psrSupportedDisplayConfig = true;
-       psr_context->psrExitLinkTrainingRequired =
-               psr_config->psr_exit_link_training_required;
-       psr_context->sdpTransmitLineNumDeadline =
-               psr_config->psr_sdp_transmit_line_num_deadline;
-       psr_context->psrFrameCaptureIndicationReq =
-               psr_config->psr_frame_capture_indication_req;
-
-       psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */
-
-       psr_context->numberOfControllers =
-                       link->dc->res_pool->timing_generator_count;
-
-       psr_context->rfb_update_auto_en = true;
-
-       /* 2 frames before enter PSR. */
-       psr_context->timehyst_frames = 2;
-       /* half a frame
-        * (units in 100 lines, i.e. a value of 1 represents 100 lines)
-        */
-       psr_context->hyst_lines = stream->timing.v_total / 2 / 100;
-       psr_context->aux_repeats = 10;
-
-       psr_context->psr_level.u32all = 0;
-
-       /*skip power down the single pipe since it blocks the cstate*/
-#if defined(CONFIG_DRM_AMD_DC_DCN)
-       if (link->ctx->asic_id.chip_family >= FAMILY_RV) {
-               switch(link->ctx->asic_id.chip_family) {
-               case FAMILY_YELLOW_CARP:
-               case AMDGPU_FAMILY_GC_10_3_6:
-               case AMDGPU_FAMILY_GC_11_0_1:
-                       if (dc->debug.disable_z10 || dc->debug.psr_skip_crtc_disable)
-                               psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
-                       break;
-               default:
-                       psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
-                       break;
-               }
-       }
-#else
-       if (link->ctx->asic_id.chip_family >= FAMILY_RV)
-               psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
-#endif
-
-       /* SMU will perform additional powerdown sequence.
-        * For unsupported ASICs, set psr_level flag to skip PSR
-        *  static screen notification to SMU.
-        *  (Always set for DAL2, did not check ASIC)
-        */
-       psr_context->allow_smu_optimizations = psr_config->allow_smu_optimizations;
-       psr_context->allow_multi_disp_optimizations = psr_config->allow_multi_disp_optimizations;
-
-       /* Complete PSR entry before aborting to prevent intermittent
-        * freezes on certain eDPs
-        */
-       psr_context->psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1;
-
-       /* enable ALPM */
-       psr_context->psr_level.bits.DISABLE_ALPM = 0;
-       psr_context->psr_level.bits.ALPM_DEFAULT_PD_MODE = 1;
-
-       /* Controls additional delay after remote frame capture before
-        * continuing power down, default = 0
-        */
-       psr_context->frame_delay = 0;
-
-       if (psr) {
-               link->psr_settings.psr_feature_enabled = psr->funcs->psr_copy_settings(psr,
-                       link, psr_context, panel_inst);
-               link->psr_settings.psr_power_opt = 0;
-               link->psr_settings.psr_allow_active = 0;
-       }
-       else
-               link->psr_settings.psr_feature_enabled = dmcu->funcs->setup_psr(dmcu, link, psr_context);
-
-       /* psr_enabled == 0 indicates setup_psr did not succeed, but this
-        * should not happen since firmware should be running at this point
-        */
-       if (link->psr_settings.psr_feature_enabled == 0)
-               ASSERT(0);
-
-       return true;
-
-}
-
-void dc_link_get_psr_residency(const struct dc_link *link, uint32_t *residency)
-{
-       struct dc  *dc = link->ctx->dc;
-       struct dmub_psr *psr = dc->res_pool->psr;
-       unsigned int panel_inst;
-
-       if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
-               return;
-
-       /* PSR residency measurements only supported on DMCUB */
-       if (psr != NULL && link->psr_settings.psr_feature_enabled)
-               psr->funcs->psr_get_residency(psr, residency, panel_inst);
-       else
-               *residency = 0;
-}
-
-bool dc_link_set_sink_vtotal_in_psr_active(const struct dc_link *link, uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su)
-{
-       struct dc *dc = link->ctx->dc;
-       struct dmub_psr *psr = dc->res_pool->psr;
-
-       if (psr == NULL || !link->psr_settings.psr_feature_enabled || !link->psr_settings.psr_vtotal_control_support)
-               return false;
-
-       psr->funcs->psr_set_sink_vtotal_in_psr_active(psr, psr_vtotal_idle, psr_vtotal_su);
-
-       return true;
-}
-
 const struct dc_link_status *dc_link_get_status(const struct dc_link *link)
 {
        return &link->link_status;
@@ -3999,10 +3544,13 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
        struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
        int i;
        bool mst_mode = (link->type == dc_connection_mst_branch);
+       /* adjust for drm changes*/
+       bool update_drm_mst_state = true;
        const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
        const struct dc_link_settings empty_link_settings = {0};
        DC_LOGGER_INIT(link->ctx->logger);
 
+
        /* deallocate_mst_payload is called before disable link. When mode or
         * disable/enable monitor, new stream is created which is not in link
         * stream[] yet. For this, payload is not allocated yet, so de-alloc
@@ -4018,7 +3566,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
                                &empty_link_settings,
                                avg_time_slots_per_mtp);
 
-       if (mst_mode) {
+       if (mst_mode || update_drm_mst_state) {
                /* when link is in mst mode, reply on mst manager to remove
                 * payload
                 */
@@ -4081,11 +3629,18 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
                        stream->ctx,
                        stream);
 
+               if (!update_drm_mst_state)
+                       dm_helpers_dp_mst_send_payload_allocation(
+                               stream->ctx,
+                               stream,
+                               false);
+       }
+
+       if (update_drm_mst_state)
                dm_helpers_dp_mst_send_payload_allocation(
                        stream->ctx,
                        stream,
                        false);
-       }
 
        return DC_OK;
 }
@@ -4541,110 +4096,6 @@ void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
        dc->hwss.set_avmute(pipe_ctx, enable);
 }
 
-void dc_link_set_drive_settings(struct dc *dc,
-                               struct link_training_settings *lt_settings,
-                               const struct dc_link *link)
-{
-
-       int i;
-       struct link_resource link_res;
-
-       for (i = 0; i < dc->link_count; i++)
-               if (dc->links[i] == link)
-                       break;
-
-       if (i >= dc->link_count)
-               ASSERT_CRITICAL(false);
-
-       dc_link_get_cur_link_res(link, &link_res);
-       dc_link_dp_set_drive_settings(dc->links[i], &link_res, lt_settings);
-}
-
-void dc_link_set_preferred_link_settings(struct dc *dc,
-                                        struct dc_link_settings *link_setting,
-                                        struct dc_link *link)
-{
-       int i;
-       struct pipe_ctx *pipe;
-       struct dc_stream_state *link_stream;
-       struct dc_link_settings store_settings = *link_setting;
-
-       link->preferred_link_setting = store_settings;
-
-       /* Retrain with preferred link settings only relevant for
-        * DP signal type
-        * Check for non-DP signal or if passive dongle present
-        */
-       if (!dc_is_dp_signal(link->connector_signal) ||
-               link->dongle_max_pix_clk > 0)
-               return;
-
-       for (i = 0; i < MAX_PIPES; i++) {
-               pipe = &dc->current_state->res_ctx.pipe_ctx[i];
-               if (pipe->stream && pipe->stream->link) {
-                       if (pipe->stream->link == link) {
-                               link_stream = pipe->stream;
-                               break;
-                       }
-               }
-       }
-
-       /* Stream not found */
-       if (i == MAX_PIPES)
-               return;
-
-       /* Cannot retrain link if backend is off */
-       if (link_stream->dpms_off)
-               return;
-
-       if (link_decide_link_settings(link_stream, &store_settings))
-               dp_retrain_link_dp_test(link, &store_settings, false);
-}
-
-void dc_link_set_preferred_training_settings(struct dc *dc,
-                                                struct dc_link_settings *link_setting,
-                                                struct dc_link_training_overrides *lt_overrides,
-                                                struct dc_link *link,
-                                                bool skip_immediate_retrain)
-{
-       if (lt_overrides != NULL)
-               link->preferred_training_settings = *lt_overrides;
-       else
-               memset(&link->preferred_training_settings, 0, sizeof(link->preferred_training_settings));
-
-       if (link_setting != NULL) {
-               link->preferred_link_setting = *link_setting;
-       } else {
-               link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN;
-               link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN;
-       }
-
-       if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
-                       link->type == dc_connection_mst_branch)
-               dm_helpers_dp_mst_update_branch_bandwidth(dc->ctx, link);
-
-       /* Retrain now, or wait until next stream update to apply */
-       if (skip_immediate_retrain == false)
-               dc_link_set_preferred_link_settings(dc, &link->preferred_link_setting, link);
-}
-
-void dc_link_set_test_pattern(struct dc_link *link,
-                             enum dp_test_pattern test_pattern,
-                             enum dp_test_pattern_color_space test_pattern_color_space,
-                             const struct link_training_settings *p_link_settings,
-                             const unsigned char *p_custom_pattern,
-                             unsigned int cust_pattern_size)
-{
-       if (link != NULL)
-               dc_link_dp_set_test_pattern(
-                       link,
-                       test_pattern,
-                       test_pattern_color_space,
-                       p_link_settings,
-                       p_custom_pattern,
-                       cust_pattern_size);
-}
-
 uint32_t dc_link_bandwidth_kbps(
        const struct dc_link *link,
        const struct dc_link_settings *link_setting)
@@ -4854,3 +4305,591 @@ void dc_restore_link_res_map(const struct dc *dc, uint32_t *map)
                }
        }
 }
+
+bool dp_validate_mode_timing(
+       struct dc_link *link,
+       const struct dc_crtc_timing *timing)
+{
+       uint32_t req_bw;
+       uint32_t max_bw;
+
+       const struct dc_link_settings *link_setting;
+
+       /* According to spec, VSC SDP should be used if pixel format is YCbCr420 */
+       if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 &&
+                       !link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED &&
+                       dal_graphics_object_id_get_connector_id(link->link_id) != CONNECTOR_ID_VIRTUAL)
+               return false;
+
+       /*always DP fail safe mode*/
+       if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 &&
+               timing->h_addressable == (uint32_t) 640 &&
+               timing->v_addressable == (uint32_t) 480)
+               return true;
+
+       link_setting = dc_link_get_link_cap(link);
+
+       /* TODO: DYNAMIC_VALIDATION needs to be implemented */
+       /*if (flags.DYNAMIC_VALIDATION == 1 &&
+               link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
+               link_setting = &link->verified_link_cap;
+       */
+
+       req_bw = dc_bandwidth_in_kbps_from_timing(timing);
+       max_bw = dc_link_bandwidth_kbps(link, link_setting);
+
+       if (req_bw <= max_bw) {
+               /* remember the biggest mode here, during
+                * initial link training (to get
+                * verified_link_cap), LS sends event about
+                * cannot train at reported cap to upper
+                * layer and upper layer will re-enumerate modes.
+                * this is not necessary if the lower
+                * verified_link_cap is enough to drive
+                * all the modes */
+
+               /* TODO: DYNAMIC_VALIDATION needs to be implemented */
+               /* if (flags.DYNAMIC_VALIDATION == 1)
+                       dpsst->max_req_bw_for_verified_linkcap = dal_max(
+                               dpsst->max_req_bw_for_verified_linkcap, req_bw); */
+               return true;
+       } else
+               return false;
+}
+
+void dp_enable_mst_on_sink(struct dc_link *link, bool enable)
+{
+       unsigned char mstmCntl;
+
+       core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
+       if (enable)
+               mstmCntl |= DP_MST_EN;
+       else
+               mstmCntl &= (~DP_MST_EN);
+
+       core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
+}
+
+enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready)
+{
+       /* FEC has to be "set ready" before the link training.
+        * The policy is to always train with FEC
+        * if the sink supports it and leave it enabled on link.
+        * If FEC is not supported, disable it.
+        */
+       struct link_encoder *link_enc = NULL;
+       enum dc_status status = DC_OK;
+       uint8_t fec_config = 0;
+
+       link_enc = link_enc_cfg_get_link_enc(link);
+       ASSERT(link_enc);
+
+       if (!dc_link_should_enable_fec(link))
+               return status;
+
+       if (link_enc->funcs->fec_set_ready &&
+                       link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
+               if (ready) {
+                       fec_config = 1;
+                       status = core_link_write_dpcd(link,
+                                       DP_FEC_CONFIGURATION,
+                                       &fec_config,
+                                       sizeof(fec_config));
+                       if (status == DC_OK) {
+                               link_enc->funcs->fec_set_ready(link_enc, true);
+                               link->fec_state = dc_link_fec_ready;
+                       } else {
+                               link_enc->funcs->fec_set_ready(link_enc, false);
+                               link->fec_state = dc_link_fec_not_ready;
+                               dm_error("dpcd write failed to set fec_ready");
+                       }
+               } else if (link->fec_state == dc_link_fec_ready) {
+                       fec_config = 0;
+                       status = core_link_write_dpcd(link,
+                                       DP_FEC_CONFIGURATION,
+                                       &fec_config,
+                                       sizeof(fec_config));
+                       link_enc->funcs->fec_set_ready(link_enc, false);
+                       link->fec_state = dc_link_fec_not_ready;
+               }
+       }
+
+       return status;
+}
+
+void dp_set_fec_enable(struct dc_link *link, bool enable)
+{
+       struct link_encoder *link_enc = NULL;
+
+       link_enc = link_enc_cfg_get_link_enc(link);
+       ASSERT(link_enc);
+
+       if (!dc_link_should_enable_fec(link))
+               return;
+
+       if (link_enc->funcs->fec_set_enable &&
+                       link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
+               if (link->fec_state == dc_link_fec_ready && enable) {
+                       /* Accord to DP spec, FEC enable sequence can first
+                        * be transmitted anytime after 1000 LL codes have
+                        * been transmitted on the link after link training
+                        * completion. Using 1 lane RBR should have the maximum
+                        * time for transmitting 1000 LL codes which is 6.173 us.
+                        * So use 7 microseconds delay instead.
+                        */
+                       udelay(7);
+                       link_enc->funcs->fec_set_enable(link_enc, true);
+                       link->fec_state = dc_link_fec_enabled;
+               } else if (link->fec_state == dc_link_fec_enabled && !enable) {
+                       link_enc->funcs->fec_set_enable(link_enc, false);
+                       link->fec_state = dc_link_fec_ready;
+               }
+       }
+}
+
+// TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST)
+static void get_lane_status(
+       struct dc_link *link,
+       uint32_t lane_count,
+       union lane_status *status,
+       union lane_align_status_updated *status_updated)
+{
+       unsigned int lane;
+       uint8_t dpcd_buf[3] = {0};
+
+       if (status == NULL || status_updated == NULL) {
+               return;
+       }
+
+       core_link_read_dpcd(
+                       link,
+                       DP_LANE0_1_STATUS,
+                       dpcd_buf,
+                       sizeof(dpcd_buf));
+
+       for (lane = 0; lane < lane_count; lane++) {
+               status[lane].raw = dp_get_nibble_at_index(&dpcd_buf[0], lane);
+       }
+
+       status_updated->raw = dpcd_buf[2];
+}
+
+bool dpcd_write_128b_132b_sst_payload_allocation_table(
+               const struct dc_stream_state *stream,
+               struct dc_link *link,
+               struct link_mst_stream_allocation_table *proposed_table,
+               bool allocate)
+{
+       const uint8_t vc_id = 1; /// VC ID always 1 for SST
+       const uint8_t start_time_slot = 0; /// Always start at time slot 0 for SST
+       bool result = false;
+       uint8_t req_slot_count = 0;
+       struct fixed31_32 avg_time_slots_per_mtp = { 0 };
+       union payload_table_update_status update_status = { 0 };
+       const uint32_t max_retries = 30;
+       uint32_t retries = 0;
+       DC_LOGGER_INIT(link->ctx->logger);
+
+       if (allocate)   {
+               avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link);
+               req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);
+               /// Validation should filter out modes that exceed link BW
+               ASSERT(req_slot_count <= MAX_MTP_SLOT_COUNT);
+               if (req_slot_count > MAX_MTP_SLOT_COUNT)
+                       return false;
+       } else {
+               /// Leave req_slot_count = 0 if allocate is false.
+       }
+
+       proposed_table->stream_count = 1; /// Always 1 stream for SST
+       proposed_table->stream_allocations[0].slot_count = req_slot_count;
+       proposed_table->stream_allocations[0].vcp_id = vc_id;
+
+       if (link->aux_access_disabled)
+               return true;
+
+       /// Write DPCD 2C0 = 1 to start updating
+       update_status.bits.VC_PAYLOAD_TABLE_UPDATED = 1;
+       core_link_write_dpcd(
+                       link,
+                       DP_PAYLOAD_TABLE_UPDATE_STATUS,
+                       &update_status.raw,
+                       1);
+
+       /// Program the changes in DPCD 1C0 - 1C2
+       ASSERT(vc_id == 1);
+       core_link_write_dpcd(
+                       link,
+                       DP_PAYLOAD_ALLOCATE_SET,
+                       &vc_id,
+                       1);
+
+       ASSERT(start_time_slot == 0);
+       core_link_write_dpcd(
+                       link,
+                       DP_PAYLOAD_ALLOCATE_START_TIME_SLOT,
+                       &start_time_slot,
+                       1);
+
+       core_link_write_dpcd(
+                       link,
+                       DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT,
+                       &req_slot_count,
+                       1);
+
+       /// Poll till DPCD 2C0 read 1
+       /// Try for at least 150ms (30 retries, with 5ms delay after each attempt)
+
+       while (retries < max_retries) {
+               if (core_link_read_dpcd(
+                               link,
+                               DP_PAYLOAD_TABLE_UPDATE_STATUS,
+                               &update_status.raw,
+                               1) == DC_OK) {
+                       if (update_status.bits.VC_PAYLOAD_TABLE_UPDATED == 1) {
+                               DC_LOG_DP2("SST Update Payload: downstream payload table updated.");
+                               result = true;
+                               break;
+                       }
+               } else {
+                       union dpcd_rev dpcdRev;
+
+                       if (core_link_read_dpcd(
+                                       link,
+                                       DP_DPCD_REV,
+                                       &dpcdRev.raw,
+                                       1) != DC_OK) {
+                               DC_LOG_ERROR("SST Update Payload: Unable to read DPCD revision "
+                                               "of sink while polling payload table "
+                                               "updated status bit.");
+                               break;
+                       }
+               }
+               retries++;
+               msleep(5);
+       }
+
+       if (!result && retries == max_retries) {
+               DC_LOG_ERROR("SST Update Payload: Payload table not updated after retries, "
+                               "continue on. Something is wrong with the branch.");
+               // TODO - DP2.0 Payload: Read and log the payload table from downstream branch
+       }
+
+       return result;
+}
+
+bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link)
+{
+       /*
+        * wait for ACT handled
+        */
+       int i;
+       const int act_retries = 30;
+       enum act_return_status result = ACT_FAILED;
+       union payload_table_update_status update_status = {0};
+       union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
+       union lane_align_status_updated lane_status_updated;
+       DC_LOGGER_INIT(link->ctx->logger);
+
+       if (link->aux_access_disabled)
+               return true;
+       for (i = 0; i < act_retries; i++) {
+               get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated);
+
+               if (!dp_is_cr_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
+                               !dp_is_ch_eq_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
+                               !dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) ||
+                               !dp_is_interlane_aligned(lane_status_updated)) {
+                       DC_LOG_ERROR("SST Update Payload: Link loss occurred while "
+                                       "polling for ACT handled.");
+                       result = ACT_LINK_LOST;
+                       break;
+               }
+               core_link_read_dpcd(
+                               link,
+                               DP_PAYLOAD_TABLE_UPDATE_STATUS,
+                               &update_status.raw,
+                               1);
+
+               if (update_status.bits.ACT_HANDLED == 1) {
+                       DC_LOG_DP2("SST Update Payload: ACT handled by downstream.");
+                       result = ACT_SUCCESS;
+                       break;
+               }
+
+               msleep(5);
+       }
+
+       if (result == ACT_FAILED) {
+               DC_LOG_ERROR("SST Update Payload: ACT still not handled after retries, "
+                               "continue on. Something is wrong with the branch.");
+       }
+
+       return (result == ACT_SUCCESS);
+}
+
+struct fixed31_32 calculate_sst_avg_time_slots_per_mtp(
+               const struct dc_stream_state *stream,
+               const struct dc_link *link)
+{
+       struct fixed31_32 link_bw_effective =
+                       dc_fixpt_from_int(
+                                       dc_link_bandwidth_kbps(link, &link->cur_link_settings));
+       struct fixed31_32 timeslot_bw_effective =
+                       dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT);
+       struct fixed31_32 timing_bw =
+                       dc_fixpt_from_int(
+                                       dc_bandwidth_in_kbps_from_timing(&stream->timing));
+       struct fixed31_32 avg_time_slots_per_mtp =
+                       dc_fixpt_div(timing_bw, timeslot_bw_effective);
+
+       return avg_time_slots_per_mtp;
+}
+
+void dc_link_clear_dprx_states(struct dc_link *link)
+{
+       memset(&link->dprx_states, 0, sizeof(link->dprx_states));
+}
+
+void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode)
+{
+       if (link != NULL && link->dc->debug.enable_driver_sequence_debug)
+               core_link_write_dpcd(link, DP_SOURCE_SEQUENCE,
+                                       &dp_test_mode, sizeof(dp_test_mode));
+}
+
+static void dsc_optc_config_log(struct display_stream_compressor *dsc,
+               struct dsc_optc_config *config)
+{
+       uint32_t precision = 1 << 28;
+       uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision;
+       uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision;
+       uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod;
+       DC_LOGGER_INIT(dsc->ctx->logger);
+
+       /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC
+        * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is
+        * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal
+        */
+       ll_bytes_per_pix_fraq *= 10000000;
+       ll_bytes_per_pix_fraq /= precision;
+
+       DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)",
+                       config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq);
+       DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444);
+       DC_LOG_DSC("\tslice_width %d", config->slice_width);
+}
+
+bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
+{
+       struct dc *dc = pipe_ctx->stream->ctx->dc;
+       struct dc_stream_state *stream = pipe_ctx->stream;
+       bool result = false;
+
+       if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
+               result = true;
+       else
+               result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable);
+       return result;
+}
+
+/* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first,
+ * i.e. after dp_enable_dsc_on_rx() had been called
+ */
+void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
+{
+       struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
+       struct dc *dc = pipe_ctx->stream->ctx->dc;
+       struct dc_stream_state *stream = pipe_ctx->stream;
+       struct pipe_ctx *odm_pipe;
+       int opp_cnt = 1;
+       DC_LOGGER_INIT(dsc->ctx->logger);
+
+       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
+               opp_cnt++;
+
+       if (enable) {
+               struct dsc_config dsc_cfg;
+               struct dsc_optc_config dsc_optc_cfg;
+               enum optc_dsc_mode optc_dsc_mode;
+
+               /* Enable DSC hw block */
+               dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
+               dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
+               dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
+               dsc_cfg.color_depth = stream->timing.display_color_depth;
+               dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
+               dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
+               ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
+               dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
+
+               dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
+               dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
+               for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+                       struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
+
+                       odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
+                       odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
+               }
+               dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
+               dsc_cfg.pic_width *= opp_cnt;
+
+               optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
+
+               /* Enable DSC in encoder */
+               if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)
+                               && !link_is_dp_128b_132b_signal(pipe_ctx)) {
+                       DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
+                       dsc_optc_config_log(dsc, &dsc_optc_cfg);
+                       pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
+                                                                       optc_dsc_mode,
+                                                                       dsc_optc_cfg.bytes_per_pixel,
+                                                                       dsc_optc_cfg.slice_width);
+
+                       /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */
+               }
+
+               /* Enable DSC in OPTC */
+               DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);
+               dsc_optc_config_log(dsc, &dsc_optc_cfg);
+               pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
+                                                       optc_dsc_mode,
+                                                       dsc_optc_cfg.bytes_per_pixel,
+                                                       dsc_optc_cfg.slice_width);
+       } else {
+               /* disable DSC in OPTC */
+               pipe_ctx->stream_res.tg->funcs->set_dsc_config(
+                               pipe_ctx->stream_res.tg,
+                               OPTC_DSC_DISABLED, 0, 0);
+
+               /* disable DSC in stream encoder */
+               if (dc_is_dp_signal(stream->signal)) {
+                       if (link_is_dp_128b_132b_signal(pipe_ctx))
+                               pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
+                                                                               pipe_ctx->stream_res.hpo_dp_stream_enc,
+                                                                               false,
+                                                                               NULL,
+                                                                               true);
+                       else if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
+                               pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
+                                               pipe_ctx->stream_res.stream_enc,
+                                               OPTC_DSC_DISABLED, 0, 0);
+                               pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
+                                                       pipe_ctx->stream_res.stream_enc, false, NULL, true);
+                       }
+               }
+
+               /* disable DSC block */
+               pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
+               for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
+                       odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
+       }
+}
+
+bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)
+{
+       struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
+       bool result = false;
+
+       if (!pipe_ctx->stream->timing.flags.DSC)
+               goto out;
+       if (!dsc)
+               goto out;
+
+       if (enable) {
+               {
+                       dp_set_dsc_on_stream(pipe_ctx, true);
+                       result = true;
+               }
+       } else {
+               dp_set_dsc_on_rx(pipe_ctx, false);
+               dp_set_dsc_on_stream(pipe_ctx, false);
+               result = true;
+       }
+out:
+       return result;
+}
+
+/*
+ * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled;
+ * hence PPS info packet update need to use frame update instead of immediate update.
+ * Added parameter immediate_update for this purpose.
+ * The decision to use frame update is hard-coded in function dp_update_dsc_config(),
+ * which is the only place where a "false" would be passed in for param immediate_update.
+ *
+ * immediate_update is only applicable when DSC is enabled.
+ */
+bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update)
+{
+       struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
+       struct dc_stream_state *stream = pipe_ctx->stream;
+       DC_LOGGER_INIT(dsc->ctx->logger);
+
+       if (!pipe_ctx->stream->timing.flags.DSC || !dsc)
+               return false;
+
+       if (enable) {
+               struct dsc_config dsc_cfg;
+               uint8_t dsc_packed_pps[128];
+
+               memset(&dsc_cfg, 0, sizeof(dsc_cfg));
+               memset(dsc_packed_pps, 0, 128);
+
+               /* Enable DSC hw block */
+               dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
+               dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
+               dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
+               dsc_cfg.color_depth = stream->timing.display_color_depth;
+               dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
+               dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
+
+               dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);
+               memcpy(&stream->dsc_packed_pps[0], &dsc_packed_pps[0], sizeof(stream->dsc_packed_pps));
+               if (dc_is_dp_signal(stream->signal)) {
+                       DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);
+                       if (link_is_dp_128b_132b_signal(pipe_ctx))
+                               pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
+                                                                               pipe_ctx->stream_res.hpo_dp_stream_enc,
+                                                                               true,
+                                                                               &dsc_packed_pps[0],
+                                                                               immediate_update);
+                       else
+                               pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
+                                               pipe_ctx->stream_res.stream_enc,
+                                               true,
+                                               &dsc_packed_pps[0],
+                                               immediate_update);
+               }
+       } else {
+               /* disable DSC PPS in stream encoder */
+               memset(&stream->dsc_packed_pps[0], 0, sizeof(stream->dsc_packed_pps));
+               if (dc_is_dp_signal(stream->signal)) {
+                       if (link_is_dp_128b_132b_signal(pipe_ctx))
+                               pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
+                                                                               pipe_ctx->stream_res.hpo_dp_stream_enc,
+                                                                               false,
+                                                                               NULL,
+                                                                               true);
+                       else
+                               pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
+                                               pipe_ctx->stream_res.stream_enc, false, NULL, true);
+               }
+       }
+
+       return true;
+}
+
+
+bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx)
+{
+       struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
+
+       if (!pipe_ctx->stream->timing.flags.DSC)
+               return false;
+       if (!dsc)
+               return false;
+
+       dp_set_dsc_on_stream(pipe_ctx, true);
+       dp_set_dsc_pps_sdp(pipe_ctx, true, false);
+       return true;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
deleted file mode 100644 (file)
index 6747e4b..0000000
+++ /dev/null
@@ -1,2375 +0,0 @@
-/*
- * Copyright 2015 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- */
-#include "dm_services.h"
-#include "dc.h"
-#include "dc_link_dp.h"
-#include "dm_helpers.h"
-#include "opp.h"
-#include "dsc.h"
-#include "resource.h"
-
-#include "inc/core_types.h"
-#include "link_hwss.h"
-#include "link/link_ddc.h"
-#include "core_status.h"
-#include "dpcd_defs.h"
-
-#include "dc_dmub_srv.h"
-#include "dce/dmub_hw_lock_mgr.h"
-#include "link/link_dp_dpia.h"
-#include "inc/link_enc_cfg.h"
-#include "clk_mgr.h"
-#include "link/link_dp_trace.h"
-#include "link/link_dp_training.h"
-#include "link/link_dp_training_fixed_vs_pe_retimer.h"
-#include "link/link_dp_training_dpia.h"
-#include "link/link_dp_training_auxless.h"
-#include "link/link_dp_phy.h"
-#include "link/link_dp_capability.h"
-#define DC_LOGGER \
-       link->ctx->logger
-
-#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
-#include "link/link_dpcd.h"
-
-static uint8_t get_nibble_at_index(const uint8_t *buf,
-       uint32_t index)
-{
-       uint8_t nibble;
-       nibble = buf[index / 2];
-
-       if (index % 2)
-               nibble >>= 4;
-       else
-               nibble &= 0x0F;
-
-       return nibble;
-}
-
-enum dc_status read_hpd_rx_irq_data(
-       struct dc_link *link,
-       union hpd_irq_data *irq_data)
-{
-       static enum dc_status retval;
-
-       /* The HW reads 16 bytes from 200h on HPD,
-        * but if we get an AUX_DEFER, the HW cannot retry
-        * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
-        * fail, so we now explicitly read 6 bytes which is
-        * the req from the above mentioned test cases.
-        *
-        * For DP 1.4 we need to read those from 2002h range.
-        */
-       if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14)
-               retval = core_link_read_dpcd(
-                       link,
-                       DP_SINK_COUNT,
-                       irq_data->raw,
-                       sizeof(union hpd_irq_data));
-       else {
-               /* Read 14 bytes in a single read and then copy only the required fields.
-                * This is more efficient than doing it in two separate AUX reads. */
-
-               uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1];
-
-               retval = core_link_read_dpcd(
-                       link,
-                       DP_SINK_COUNT_ESI,
-                       tmp,
-                       sizeof(tmp));
-
-               if (retval != DC_OK)
-                       return retval;
-
-               irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI];
-               irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI];
-               irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI];
-               irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI];
-               irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI];
-               irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI];
-       }
-
-       return retval;
-}
-
-bool hpd_rx_irq_check_link_loss_status(
-       struct dc_link *link,
-       union hpd_irq_data *hpd_irq_dpcd_data)
-{
-       uint8_t irq_reg_rx_power_state = 0;
-       enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
-       union lane_status lane_status;
-       uint32_t lane;
-       bool sink_status_changed;
-       bool return_code;
-
-       sink_status_changed = false;
-       return_code = false;
-
-       if (link->cur_link_settings.lane_count == 0)
-               return return_code;
-
-       /*1. Check that Link Status changed, before re-training.*/
-
-       /*parse lane status*/
-       for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
-               /* check status of lanes 0,1
-                * changed DpcdAddress_Lane01Status (0x202)
-                */
-               lane_status.raw = get_nibble_at_index(
-                       &hpd_irq_dpcd_data->bytes.lane01_status.raw,
-                       lane);
-
-               if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
-                       !lane_status.bits.CR_DONE_0 ||
-                       !lane_status.bits.SYMBOL_LOCKED_0) {
-                       /* if one of the channel equalization, clock
-                        * recovery or symbol lock is dropped
-                        * consider it as (link has been
-                        * dropped) dp sink status has changed
-                        */
-                       sink_status_changed = true;
-                       break;
-               }
-       }
-
-       /* Check interlane align.*/
-       if (sink_status_changed ||
-               !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
-
-               DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
-
-               return_code = true;
-
-               /*2. Check that we can handle interrupt: Not in FS DOS,
-                *  Not in "Display Timeout" state, Link is trained.
-                */
-               dpcd_result = core_link_read_dpcd(link,
-                       DP_SET_POWER,
-                       &irq_reg_rx_power_state,
-                       sizeof(irq_reg_rx_power_state));
-
-               if (dpcd_result != DC_OK) {
-                       DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",
-                               __func__);
-               } else {
-                       if (irq_reg_rx_power_state != DP_SET_POWER_D0)
-                               return_code = false;
-               }
-       }
-
-       return return_code;
-}
-
-bool dp_validate_mode_timing(
-       struct dc_link *link,
-       const struct dc_crtc_timing *timing)
-{
-       uint32_t req_bw;
-       uint32_t max_bw;
-
-       const struct dc_link_settings *link_setting;
-
-       /* According to spec, VSC SDP should be used if pixel format is YCbCr420 */
-       if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 &&
-                       !link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED &&
-                       dal_graphics_object_id_get_connector_id(link->link_id) != CONNECTOR_ID_VIRTUAL)
-               return false;
-
-       /*always DP fail safe mode*/
-       if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 &&
-               timing->h_addressable == (uint32_t) 640 &&
-               timing->v_addressable == (uint32_t) 480)
-               return true;
-
-       link_setting = dc_link_get_link_cap(link);
-
-       /* TODO: DYNAMIC_VALIDATION needs to be implemented */
-       /*if (flags.DYNAMIC_VALIDATION == 1 &&
-               link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
-               link_setting = &link->verified_link_cap;
-       */
-
-       req_bw = dc_bandwidth_in_kbps_from_timing(timing);
-       max_bw = dc_link_bandwidth_kbps(link, link_setting);
-
-       if (req_bw <= max_bw) {
-               /* remember the biggest mode here, during
-                * initial link training (to get
-                * verified_link_cap), LS sends event about
-                * cannot train at reported cap to upper
-                * layer and upper layer will re-enumerate modes.
-                * this is not necessary if the lower
-                * verified_link_cap is enough to drive
-                * all the modes */
-
-               /* TODO: DYNAMIC_VALIDATION needs to be implemented */
-               /* if (flags.DYNAMIC_VALIDATION == 1)
-                       dpsst->max_req_bw_for_verified_linkcap = dal_max(
-                               dpsst->max_req_bw_for_verified_linkcap, req_bw); */
-               return true;
-       } else
-               return false;
-}
-
-/*************************Short Pulse IRQ***************************/
-bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link)
-{
-       /*
-        * Don't handle RX IRQ unless one of following is met:
-        * 1) The link is established (cur_link_settings != unknown)
-        * 2) We know we're dealing with a branch device, SST or MST
-        */
-
-       if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
-               is_dp_branch_device(link))
-               return true;
-
-       return false;
-}
-
-static bool handle_hpd_irq_psr_sink(struct dc_link *link)
-{
-       union dpcd_psr_configuration psr_configuration;
-
-       if (!link->psr_settings.psr_feature_enabled)
-               return false;
-
-       dm_helpers_dp_read_dpcd(
-               link->ctx,
-               link,
-               368,/*DpcdAddress_PSR_Enable_Cfg*/
-               &psr_configuration.raw,
-               sizeof(psr_configuration.raw));
-
-       if (psr_configuration.bits.ENABLE) {
-               unsigned char dpcdbuf[3] = {0};
-               union psr_error_status psr_error_status;
-               union psr_sink_psr_status psr_sink_psr_status;
-
-               dm_helpers_dp_read_dpcd(
-                       link->ctx,
-                       link,
-                       0x2006, /*DpcdAddress_PSR_Error_Status*/
-                       (unsigned char *) dpcdbuf,
-                       sizeof(dpcdbuf));
-
-               /*DPCD 2006h   ERROR STATUS*/
-               psr_error_status.raw = dpcdbuf[0];
-               /*DPCD 2008h   SINK PANEL SELF REFRESH STATUS*/
-               psr_sink_psr_status.raw = dpcdbuf[2];
-
-               if (psr_error_status.bits.LINK_CRC_ERROR ||
-                               psr_error_status.bits.RFB_STORAGE_ERROR ||
-                               psr_error_status.bits.VSC_SDP_ERROR) {
-                       bool allow_active;
-
-                       /* Acknowledge and clear error bits */
-                       dm_helpers_dp_write_dpcd(
-                               link->ctx,
-                               link,
-                               8198,/*DpcdAddress_PSR_Error_Status*/
-                               &psr_error_status.raw,
-                               sizeof(psr_error_status.raw));
-
-                       /* PSR error, disable and re-enable PSR */
-                       if (link->psr_settings.psr_allow_active) {
-                               allow_active = false;
-                               dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
-                               allow_active = true;
-                               dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
-                       }
-
-                       return true;
-               } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
-                               PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){
-                       /* No error is detect, PSR is active.
-                        * We should return with IRQ_HPD handled without
-                        * checking for loss of sync since PSR would have
-                        * powered down main link.
-                        */
-                       return true;
-               }
-       }
-       return false;
-}
-
-static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate)
-{
-       switch (test_rate) {
-       case DP_TEST_LINK_RATE_RBR:
-               return LINK_RATE_LOW;
-       case DP_TEST_LINK_RATE_HBR:
-               return LINK_RATE_HIGH;
-       case DP_TEST_LINK_RATE_HBR2:
-               return LINK_RATE_HIGH2;
-       case DP_TEST_LINK_RATE_HBR3:
-               return LINK_RATE_HIGH3;
-       case DP_TEST_LINK_RATE_UHBR10:
-               return LINK_RATE_UHBR10;
-       case DP_TEST_LINK_RATE_UHBR20:
-               return LINK_RATE_UHBR20;
-       case DP_TEST_LINK_RATE_UHBR13_5:
-               return LINK_RATE_UHBR13_5;
-       default:
-               return LINK_RATE_UNKNOWN;
-       }
-}
-
-static void dp_test_send_link_training(struct dc_link *link)
-{
-       struct dc_link_settings link_settings = {0};
-       uint8_t test_rate = 0;
-
-       core_link_read_dpcd(
-                       link,
-                       DP_TEST_LANE_COUNT,
-                       (unsigned char *)(&link_settings.lane_count),
-                       1);
-       core_link_read_dpcd(
-                       link,
-                       DP_TEST_LINK_RATE,
-                       &test_rate,
-                       1);
-       link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate);
-
-       /* Set preferred link settings */
-       link->verified_link_cap.lane_count = link_settings.lane_count;
-       link->verified_link_cap.link_rate = link_settings.link_rate;
-
-       dp_retrain_link_dp_test(link, &link_settings, false);
-}
-
-static bool is_dp_phy_sqaure_pattern(enum dp_test_pattern test_pattern)
-{
-       return (DP_TEST_PATTERN_SQUARE_BEGIN <= test_pattern &&
-                       test_pattern <= DP_TEST_PATTERN_SQUARE_END);
-}
-
-/* TODO Raven hbr2 compliance eye output is unstable
- * (toggling on and off) with debugger break
- * This caueses intermittent PHY automation failure
- * Need to look into the root cause */
-static void dp_test_send_phy_test_pattern(struct dc_link *link)
-{
-       union phy_test_pattern dpcd_test_pattern;
-       union lane_adjust dpcd_lane_adjustment[2];
-       unsigned char dpcd_post_cursor_2_adjustment = 0;
-       unsigned char test_pattern_buffer[
-                       (DP_TEST_264BIT_CUSTOM_PATTERN_263_256 -
-                       DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0};
-       unsigned int test_pattern_size = 0;
-       enum dp_test_pattern test_pattern;
-       union lane_adjust dpcd_lane_adjust;
-       unsigned int lane;
-       struct link_training_settings link_training_settings;
-       unsigned char no_preshoot = 0;
-       unsigned char no_deemphasis = 0;
-
-       dpcd_test_pattern.raw = 0;
-       memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
-       memset(&link_training_settings, 0, sizeof(link_training_settings));
-
-       /* get phy test pattern and pattern parameters from DP receiver */
-       core_link_read_dpcd(
-                       link,
-                       DP_PHY_TEST_PATTERN,
-                       &dpcd_test_pattern.raw,
-                       sizeof(dpcd_test_pattern));
-       core_link_read_dpcd(
-                       link,
-                       DP_ADJUST_REQUEST_LANE0_1,
-                       &dpcd_lane_adjustment[0].raw,
-                       sizeof(dpcd_lane_adjustment));
-
-       /* prepare link training settings */
-       link_training_settings.link_settings = link->cur_link_settings;
-
-       link_training_settings.lttpr_mode = dc_link_decide_lttpr_mode(link, &link->cur_link_settings);
-
-       if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
-                       link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT)
-               dp_fixed_vs_pe_read_lane_adjust(
-                               link,
-                               link_training_settings.dpcd_lane_settings);
-
-       /*get post cursor 2 parameters
-        * For DP 1.1a or eariler, this DPCD register's value is 0
-        * For DP 1.2 or later:
-        * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
-        * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
-        */
-       core_link_read_dpcd(
-                       link,
-                       DP_ADJUST_REQUEST_POST_CURSOR2,
-                       &dpcd_post_cursor_2_adjustment,
-                       sizeof(dpcd_post_cursor_2_adjustment));
-
-       /* translate request */
-       switch (dpcd_test_pattern.bits.PATTERN) {
-       case PHY_TEST_PATTERN_D10_2:
-               test_pattern = DP_TEST_PATTERN_D102;
-               break;
-       case PHY_TEST_PATTERN_SYMBOL_ERROR:
-               test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
-               break;
-       case PHY_TEST_PATTERN_PRBS7:
-               test_pattern = DP_TEST_PATTERN_PRBS7;
-               break;
-       case PHY_TEST_PATTERN_80BIT_CUSTOM:
-               test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
-               break;
-       case PHY_TEST_PATTERN_CP2520_1:
-               /* CP2520 pattern is unstable, temporarily use TPS4 instead */
-               test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
-                               DP_TEST_PATTERN_TRAINING_PATTERN4 :
-                               DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
-               break;
-       case PHY_TEST_PATTERN_CP2520_2:
-               /* CP2520 pattern is unstable, temporarily use TPS4 instead */
-               test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
-                               DP_TEST_PATTERN_TRAINING_PATTERN4 :
-                               DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
-               break;
-       case PHY_TEST_PATTERN_CP2520_3:
-               test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
-               break;
-       case PHY_TEST_PATTERN_128b_132b_TPS1:
-               test_pattern = DP_TEST_PATTERN_128b_132b_TPS1;
-               break;
-       case PHY_TEST_PATTERN_128b_132b_TPS2:
-               test_pattern = DP_TEST_PATTERN_128b_132b_TPS2;
-               break;
-       case PHY_TEST_PATTERN_PRBS9:
-               test_pattern = DP_TEST_PATTERN_PRBS9;
-               break;
-       case PHY_TEST_PATTERN_PRBS11:
-               test_pattern = DP_TEST_PATTERN_PRBS11;
-               break;
-       case PHY_TEST_PATTERN_PRBS15:
-               test_pattern = DP_TEST_PATTERN_PRBS15;
-               break;
-       case PHY_TEST_PATTERN_PRBS23:
-               test_pattern = DP_TEST_PATTERN_PRBS23;
-               break;
-       case PHY_TEST_PATTERN_PRBS31:
-               test_pattern = DP_TEST_PATTERN_PRBS31;
-               break;
-       case PHY_TEST_PATTERN_264BIT_CUSTOM:
-               test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM;
-               break;
-       case PHY_TEST_PATTERN_SQUARE:
-               test_pattern = DP_TEST_PATTERN_SQUARE;
-               break;
-       case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED:
-               test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED;
-               no_preshoot = 1;
-               break;
-       case PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED:
-               test_pattern = DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED;
-               no_deemphasis = 1;
-               break;
-       case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED:
-               test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED;
-               no_preshoot = 1;
-               no_deemphasis = 1;
-               break;
-       default:
-               test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
-       break;
-       }
-
-       if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
-               test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
-                               DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1;
-               core_link_read_dpcd(
-                               link,
-                               DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
-                               test_pattern_buffer,
-                               test_pattern_size);
-       }
-
-       if (is_dp_phy_sqaure_pattern(test_pattern)) {
-               test_pattern_size = 1; // Square pattern data is 1 byte (DP spec)
-               core_link_read_dpcd(
-                               link,
-                               DP_PHY_SQUARE_PATTERN,
-                               test_pattern_buffer,
-                               test_pattern_size);
-       }
-
-       if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) {
-               test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256-
-                               DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1;
-               core_link_read_dpcd(
-                               link,
-                               DP_TEST_264BIT_CUSTOM_PATTERN_7_0,
-                               test_pattern_buffer,
-                               test_pattern_size);
-       }
-
-       for (lane = 0; lane <
-               (unsigned int)(link->cur_link_settings.lane_count);
-               lane++) {
-               dpcd_lane_adjust.raw =
-                       get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
-               if (link_dp_get_encoding_format(&link->cur_link_settings) ==
-                               DP_8b_10b_ENCODING) {
-                       link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING =
-                               (enum dc_voltage_swing)
-                               (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
-                       link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS =
-                               (enum dc_pre_emphasis)
-                               (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
-                       link_training_settings.hw_lane_settings[lane].POST_CURSOR2 =
-                               (enum dc_post_cursor2)
-                               ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
-               } else if (link_dp_get_encoding_format(&link->cur_link_settings) ==
-                               DP_128b_132b_ENCODING) {
-                       link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.level =
-                                       dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
-                       link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_preshoot = no_preshoot;
-                       link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_deemphasis = no_deemphasis;
-               }
-       }
-
-       dp_hw_to_dpcd_lane_settings(&link_training_settings,
-                       link_training_settings.hw_lane_settings,
-                       link_training_settings.dpcd_lane_settings);
-       /*Usage: Measure DP physical lane signal
-        * by DP SI test equipment automatically.
-        * PHY test pattern request is generated by equipment via HPD interrupt.
-        * HPD needs to be active all the time. HPD should be active
-        * all the time. Do not touch it.
-        * forward request to DS
-        */
-       dc_link_dp_set_test_pattern(
-               link,
-               test_pattern,
-               DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
-               &link_training_settings,
-               test_pattern_buffer,
-               test_pattern_size);
-}
-
-static void dp_test_send_link_test_pattern(struct dc_link *link)
-{
-       union link_test_pattern dpcd_test_pattern;
-       union test_misc dpcd_test_params;
-       enum dp_test_pattern test_pattern;
-       enum dp_test_pattern_color_space test_pattern_color_space =
-                       DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
-       enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
-       struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
-       struct pipe_ctx *pipe_ctx = NULL;
-       int i;
-
-       memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
-       memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
-
-       for (i = 0; i < MAX_PIPES; i++) {
-               if (pipes[i].stream == NULL)
-                       continue;
-
-               if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
-                       pipe_ctx = &pipes[i];
-                       break;
-               }
-       }
-
-       if (pipe_ctx == NULL)
-               return;
-
-       /* get link test pattern and pattern parameters */
-       core_link_read_dpcd(
-                       link,
-                       DP_TEST_PATTERN,
-                       &dpcd_test_pattern.raw,
-                       sizeof(dpcd_test_pattern));
-       core_link_read_dpcd(
-                       link,
-                       DP_TEST_MISC0,
-                       &dpcd_test_params.raw,
-                       sizeof(dpcd_test_params));
-
-       switch (dpcd_test_pattern.bits.PATTERN) {
-       case LINK_TEST_PATTERN_COLOR_RAMP:
-               test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
-       break;
-       case LINK_TEST_PATTERN_VERTICAL_BARS:
-               test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
-       break; /* black and white */
-       case LINK_TEST_PATTERN_COLOR_SQUARES:
-               test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
-                               TEST_DYN_RANGE_VESA ?
-                               DP_TEST_PATTERN_COLOR_SQUARES :
-                               DP_TEST_PATTERN_COLOR_SQUARES_CEA);
-       break;
-       default:
-               test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
-       break;
-       }
-
-       if (dpcd_test_params.bits.CLR_FORMAT == 0)
-               test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
-       else
-               test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
-                               DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
-                               DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
-
-       switch (dpcd_test_params.bits.BPC) {
-       case 0: // 6 bits
-               requestColorDepth = COLOR_DEPTH_666;
-               break;
-       case 1: // 8 bits
-               requestColorDepth = COLOR_DEPTH_888;
-               break;
-       case 2: // 10 bits
-               requestColorDepth = COLOR_DEPTH_101010;
-               break;
-       case 3: // 12 bits
-               requestColorDepth = COLOR_DEPTH_121212;
-               break;
-       default:
-               break;
-       }
-
-       switch (dpcd_test_params.bits.CLR_FORMAT) {
-       case 0:
-               pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
-               break;
-       case 1:
-               pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR422;
-               break;
-       case 2:
-               pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR444;
-               break;
-       default:
-               pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
-               break;
-       }
-
-
-       if (requestColorDepth != COLOR_DEPTH_UNDEFINED
-                       && pipe_ctx->stream->timing.display_color_depth != requestColorDepth) {
-               DC_LOG_DEBUG("%s: original bpc %d, changing to %d\n",
-                               __func__,
-                               pipe_ctx->stream->timing.display_color_depth,
-                               requestColorDepth);
-               pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
-       }
-
-       dp_update_dsc_config(pipe_ctx);
-
-       dc_link_dp_set_test_pattern(
-                       link,
-                       test_pattern,
-                       test_pattern_color_space,
-                       NULL,
-                       NULL,
-                       0);
-}
-
-static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
-{
-       union audio_test_mode            dpcd_test_mode = {0};
-       struct audio_test_pattern_type   dpcd_pattern_type = {0};
-       union audio_test_pattern_period  dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
-       enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
-
-       struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
-       struct pipe_ctx *pipe_ctx = &pipes[0];
-       unsigned int channel_count;
-       unsigned int channel = 0;
-       unsigned int modes = 0;
-       unsigned int sampling_rate_in_hz = 0;
-
-       // get audio test mode and test pattern parameters
-       core_link_read_dpcd(
-               link,
-               DP_TEST_AUDIO_MODE,
-               &dpcd_test_mode.raw,
-               sizeof(dpcd_test_mode));
-
-       core_link_read_dpcd(
-               link,
-               DP_TEST_AUDIO_PATTERN_TYPE,
-               &dpcd_pattern_type.value,
-               sizeof(dpcd_pattern_type));
-
-       channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT);
-
-       // read pattern periods for requested channels when sawTooth pattern is requested
-       if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
-                       dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
-
-               test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
-                               DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
-               // read period for each channel
-               for (channel = 0; channel < channel_count; channel++) {
-                       core_link_read_dpcd(
-                                                       link,
-                                                       DP_TEST_AUDIO_PERIOD_CH1 + channel,
-                                                       &dpcd_pattern_period[channel].raw,
-                                                       sizeof(dpcd_pattern_period[channel]));
-               }
-       }
-
-       // translate sampling rate
-       switch (dpcd_test_mode.bits.sampling_rate) {
-       case AUDIO_SAMPLING_RATE_32KHZ:
-               sampling_rate_in_hz = 32000;
-               break;
-       case AUDIO_SAMPLING_RATE_44_1KHZ:
-               sampling_rate_in_hz = 44100;
-               break;
-       case AUDIO_SAMPLING_RATE_48KHZ:
-               sampling_rate_in_hz = 48000;
-               break;
-       case AUDIO_SAMPLING_RATE_88_2KHZ:
-               sampling_rate_in_hz = 88200;
-               break;
-       case AUDIO_SAMPLING_RATE_96KHZ:
-               sampling_rate_in_hz = 96000;
-               break;
-       case AUDIO_SAMPLING_RATE_176_4KHZ:
-               sampling_rate_in_hz = 176400;
-               break;
-       case AUDIO_SAMPLING_RATE_192KHZ:
-               sampling_rate_in_hz = 192000;
-               break;
-       default:
-               sampling_rate_in_hz = 0;
-               break;
-       }
-
-       link->audio_test_data.flags.test_requested = 1;
-       link->audio_test_data.flags.disable_video = disable_video;
-       link->audio_test_data.sampling_rate = sampling_rate_in_hz;
-       link->audio_test_data.channel_count = channel_count;
-       link->audio_test_data.pattern_type = test_pattern;
-
-       if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
-               for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
-                       link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
-               }
-       }
-}
-
-void dc_link_dp_handle_automated_test(struct dc_link *link)
-{
-       union test_request test_request;
-       union test_response test_response;
-
-       memset(&test_request, 0, sizeof(test_request));
-       memset(&test_response, 0, sizeof(test_response));
-
-       core_link_read_dpcd(
-               link,
-               DP_TEST_REQUEST,
-               &test_request.raw,
-               sizeof(union test_request));
-       if (test_request.bits.LINK_TRAINING) {
-               /* ACK first to let DP RX test box monitor LT sequence */
-               test_response.bits.ACK = 1;
-               core_link_write_dpcd(
-                       link,
-                       DP_TEST_RESPONSE,
-                       &test_response.raw,
-                       sizeof(test_response));
-               dp_test_send_link_training(link);
-               /* no acknowledge request is needed again */
-               test_response.bits.ACK = 0;
-       }
-       if (test_request.bits.LINK_TEST_PATTRN) {
-               dp_test_send_link_test_pattern(link);
-               test_response.bits.ACK = 1;
-       }
-
-       if (test_request.bits.AUDIO_TEST_PATTERN) {
-               dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
-               test_response.bits.ACK = 1;
-       }
-
-       if (test_request.bits.PHY_TEST_PATTERN) {
-               dp_test_send_phy_test_pattern(link);
-               test_response.bits.ACK = 1;
-       }
-
-       /* send request acknowledgment */
-       if (test_response.bits.ACK)
-               core_link_write_dpcd(
-                       link,
-                       DP_TEST_RESPONSE,
-                       &test_response.raw,
-                       sizeof(test_response));
-}
-
-void dc_link_dp_handle_link_loss(struct dc_link *link)
-{
-       int i;
-       struct pipe_ctx *pipe_ctx;
-
-       for (i = 0; i < MAX_PIPES; i++) {
-               pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
-               if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
-                       break;
-       }
-
-       if (pipe_ctx == NULL || pipe_ctx->stream == NULL)
-               return;
-
-       for (i = 0; i < MAX_PIPES; i++) {
-               pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
-               if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
-                               pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
-                       core_link_disable_stream(pipe_ctx);
-       }
-
-       for (i = 0; i < MAX_PIPES; i++) {
-               pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
-               if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off
-                               && pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
-                       // Always use max settings here for DP 1.4a LL Compliance CTS
-                       if (link->is_automated) {
-                               pipe_ctx->link_config.dp_link_settings.lane_count =
-                                               link->verified_link_cap.lane_count;
-                               pipe_ctx->link_config.dp_link_settings.link_rate =
-                                               link->verified_link_cap.link_rate;
-                               pipe_ctx->link_config.dp_link_settings.link_spread =
-                                               link->verified_link_cap.link_spread;
-                       }
-                       core_link_enable_stream(link->dc->current_state, pipe_ctx);
-               }
-       }
-}
-
-bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss,
-                                                       bool defer_handling, bool *has_left_work)
-{
-       union hpd_irq_data hpd_irq_dpcd_data = {0};
-       union device_service_irq device_service_clear = {0};
-       enum dc_status result;
-       bool status = false;
-
-       if (out_link_loss)
-               *out_link_loss = false;
-
-       if (has_left_work)
-               *has_left_work = false;
-       /* For use cases related to down stream connection status change,
-        * PSR and device auto test, refer to function handle_sst_hpd_irq
-        * in DAL2.1*/
-
-       DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",
-               __func__, link->link_index);
-
-
-        /* All the "handle_hpd_irq_xxx()" methods
-                * should be called only after
-                * dal_dpsst_ls_read_hpd_irq_data
-                * Order of calls is important too
-                */
-       result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
-       if (out_hpd_irq_dpcd_data)
-               *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
-
-       if (result != DC_OK) {
-               DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n",
-                       __func__);
-               return false;
-       }
-
-       if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
-               // Workaround for DP 1.4a LL Compliance CTS as USB4 has to share encoders unlike DP and USBC
-               link->is_automated = true;
-               device_service_clear.bits.AUTOMATED_TEST = 1;
-               core_link_write_dpcd(
-                       link,
-                       DP_DEVICE_SERVICE_IRQ_VECTOR,
-                       &device_service_clear.raw,
-                       sizeof(device_service_clear.raw));
-               device_service_clear.raw = 0;
-               if (defer_handling && has_left_work)
-                       *has_left_work = true;
-               else
-                       dc_link_dp_handle_automated_test(link);
-               return false;
-       }
-
-       if (!dc_link_dp_allow_hpd_rx_irq(link)) {
-               DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",
-                       __func__, link->link_index);
-               return false;
-       }
-
-       if (handle_hpd_irq_psr_sink(link))
-               /* PSR-related error was detected and handled */
-               return true;
-
-       /* If PSR-related error handled, Main link may be off,
-        * so do not handle as a normal sink status change interrupt.
-        */
-
-       if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) {
-               if (defer_handling && has_left_work)
-                       *has_left_work = true;
-               return true;
-       }
-
-       /* check if we have MST msg and return since we poll for it */
-       if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
-               if (defer_handling && has_left_work)
-                       *has_left_work = true;
-               return false;
-       }
-
-       /* For now we only handle 'Downstream port status' case.
-        * If we got sink count changed it means
-        * Downstream port status changed,
-        * then DM should call DC to do the detection.
-        * NOTE: Do not handle link loss on eDP since it is internal link*/
-       if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
-               hpd_rx_irq_check_link_loss_status(
-                       link,
-                       &hpd_irq_dpcd_data)) {
-               /* Connectivity log: link loss */
-               CONN_DATA_LINK_LOSS(link,
-                                       hpd_irq_dpcd_data.raw,
-                                       sizeof(hpd_irq_dpcd_data),
-                                       "Status: ");
-
-               if (defer_handling && has_left_work)
-                       *has_left_work = true;
-               else
-                       dc_link_dp_handle_link_loss(link);
-
-               status = false;
-               if (out_link_loss)
-                       *out_link_loss = true;
-
-               dp_trace_link_loss_increment(link);
-       }
-
-       if (link->type == dc_connection_sst_branch &&
-               hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
-                       != link->dpcd_sink_count)
-               status = true;
-
-       /* reasons for HPD RX:
-        * 1. Link Loss - ie Re-train the Link
-        * 2. MST sideband message
-        * 3. Automated Test - ie. Internal Commit
-        * 4. CP (copy protection) - (not interesting for DM???)
-        * 5. DRR
-        * 6. Downstream Port status changed
-        * -ie. Detect - this the only one
-        * which is interesting for DM because
-        * it must call dc_link_detect.
-        */
-       return status;
-}
-
-static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
-{
-       if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern &&
-                       test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) ||
-                       test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
-               return true;
-       else
-               return false;
-}
-
-static void set_crtc_test_pattern(struct dc_link *link,
-                               struct pipe_ctx *pipe_ctx,
-                               enum dp_test_pattern test_pattern,
-                               enum dp_test_pattern_color_space test_pattern_color_space)
-{
-       enum controller_dp_test_pattern controller_test_pattern;
-       enum dc_color_depth color_depth = pipe_ctx->
-               stream->timing.display_color_depth;
-       struct bit_depth_reduction_params params;
-       struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
-       int width = pipe_ctx->stream->timing.h_addressable +
-               pipe_ctx->stream->timing.h_border_left +
-               pipe_ctx->stream->timing.h_border_right;
-       int height = pipe_ctx->stream->timing.v_addressable +
-               pipe_ctx->stream->timing.v_border_bottom +
-               pipe_ctx->stream->timing.v_border_top;
-
-       memset(&params, 0, sizeof(params));
-
-       switch (test_pattern) {
-       case DP_TEST_PATTERN_COLOR_SQUARES:
-               controller_test_pattern =
-                               CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
-       break;
-       case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
-               controller_test_pattern =
-                               CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
-       break;
-       case DP_TEST_PATTERN_VERTICAL_BARS:
-               controller_test_pattern =
-                               CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
-       break;
-       case DP_TEST_PATTERN_HORIZONTAL_BARS:
-               controller_test_pattern =
-                               CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
-       break;
-       case DP_TEST_PATTERN_COLOR_RAMP:
-               controller_test_pattern =
-                               CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
-       break;
-       default:
-               controller_test_pattern =
-                               CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
-       break;
-       }
-
-       switch (test_pattern) {
-       case DP_TEST_PATTERN_COLOR_SQUARES:
-       case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
-       case DP_TEST_PATTERN_VERTICAL_BARS:
-       case DP_TEST_PATTERN_HORIZONTAL_BARS:
-       case DP_TEST_PATTERN_COLOR_RAMP:
-       {
-               /* disable bit depth reduction */
-               pipe_ctx->stream->bit_depth_params = params;
-               opp->funcs->opp_program_bit_depth_reduction(opp, &params);
-               if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
-                       pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
-                               controller_test_pattern, color_depth);
-               else if (link->dc->hwss.set_disp_pattern_generator) {
-                       struct pipe_ctx *odm_pipe;
-                       enum controller_dp_color_space controller_color_space;
-                       int opp_cnt = 1;
-                       int offset = 0;
-                       int dpg_width = width;
-
-                       switch (test_pattern_color_space) {
-                       case DP_TEST_PATTERN_COLOR_SPACE_RGB:
-                               controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
-                               break;
-                       case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
-                               controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
-                               break;
-                       case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
-                               controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
-                               break;
-                       case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
-                       default:
-                               controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
-                               DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
-                               ASSERT(0);
-                               break;
-                       }
-
-                       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
-                               opp_cnt++;
-                       dpg_width = width / opp_cnt;
-                       offset = dpg_width;
-
-                       link->dc->hwss.set_disp_pattern_generator(link->dc,
-                                       pipe_ctx,
-                                       controller_test_pattern,
-                                       controller_color_space,
-                                       color_depth,
-                                       NULL,
-                                       dpg_width,
-                                       height,
-                                       0);
-
-                       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
-                               struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
-
-                               odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
-                               link->dc->hwss.set_disp_pattern_generator(link->dc,
-                                               odm_pipe,
-                                               controller_test_pattern,
-                                               controller_color_space,
-                                               color_depth,
-                                               NULL,
-                                               dpg_width,
-                                               height,
-                                               offset);
-                               offset += offset;
-                       }
-               }
-       }
-       break;
-       case DP_TEST_PATTERN_VIDEO_MODE:
-       {
-               /* restore bitdepth reduction */
-               resource_build_bit_depth_reduction_params(pipe_ctx->stream, &params);
-               pipe_ctx->stream->bit_depth_params = params;
-               opp->funcs->opp_program_bit_depth_reduction(opp, &params);
-               if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
-                       pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
-                               CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
-                               color_depth);
-               else if (link->dc->hwss.set_disp_pattern_generator) {
-                       struct pipe_ctx *odm_pipe;
-                       int opp_cnt = 1;
-                       int dpg_width;
-
-                       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
-                               opp_cnt++;
-
-                       dpg_width = width / opp_cnt;
-                       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
-                               struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
-
-                               odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
-                               link->dc->hwss.set_disp_pattern_generator(link->dc,
-                                               odm_pipe,
-                                               CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
-                                               CONTROLLER_DP_COLOR_SPACE_UDEFINED,
-                                               color_depth,
-                                               NULL,
-                                               dpg_width,
-                                               height,
-                                               0);
-                       }
-                       link->dc->hwss.set_disp_pattern_generator(link->dc,
-                                       pipe_ctx,
-                                       CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
-                                       CONTROLLER_DP_COLOR_SPACE_UDEFINED,
-                                       color_depth,
-                                       NULL,
-                                       dpg_width,
-                                       height,
-                                       0);
-               }
-       }
-       break;
-
-       default:
-       break;
-       }
-}
-
-bool dc_link_dp_set_test_pattern(
-       struct dc_link *link,
-       enum dp_test_pattern test_pattern,
-       enum dp_test_pattern_color_space test_pattern_color_space,
-       const struct link_training_settings *p_link_settings,
-       const unsigned char *p_custom_pattern,
-       unsigned int cust_pattern_size)
-{
-       struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
-       struct pipe_ctx *pipe_ctx = NULL;
-       unsigned int lane;
-       unsigned int i;
-       unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
-       union dpcd_training_pattern training_pattern;
-       enum dpcd_phy_test_patterns pattern;
-
-       memset(&training_pattern, 0, sizeof(training_pattern));
-
-       for (i = 0; i < MAX_PIPES; i++) {
-               if (pipes[i].stream == NULL)
-                       continue;
-
-               if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
-                       pipe_ctx = &pipes[i];
-                       break;
-               }
-       }
-
-       if (pipe_ctx == NULL)
-               return false;
-
-       /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
-       if (link->test_pattern_enabled && test_pattern ==
-                       DP_TEST_PATTERN_VIDEO_MODE) {
-               /* Set CRTC Test Pattern */
-               set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
-               dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
-                               (uint8_t *)p_custom_pattern,
-                               (uint32_t)cust_pattern_size);
-
-               /* Unblank Stream */
-               link->dc->hwss.unblank_stream(
-                       pipe_ctx,
-                       &link->verified_link_cap);
-               /* TODO:m_pHwss->MuteAudioEndpoint
-                * (pPathMode->pDisplayPath, false);
-                */
-
-               /* Reset Test Pattern state */
-               link->test_pattern_enabled = false;
-
-               return true;
-       }
-
-       /* Check for PHY Test Patterns */
-       if (is_dp_phy_pattern(test_pattern)) {
-               /* Set DPCD Lane Settings before running test pattern */
-               if (p_link_settings != NULL) {
-                       if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
-                                       p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
-                               dp_fixed_vs_pe_set_retimer_lane_settings(
-                                               link,
-                                               p_link_settings->dpcd_lane_settings,
-                                               p_link_settings->link_settings.lane_count);
-                       } else {
-                               dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX);
-                       }
-                       dpcd_set_lane_settings(link, p_link_settings, DPRX);
-               }
-
-               /* Blank stream if running test pattern */
-               if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
-                       /*TODO:
-                        * m_pHwss->
-                        * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
-                        */
-                       /* Blank stream */
-                       link->dc->hwss.blank_stream(pipe_ctx);
-               }
-
-               dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
-                               (uint8_t *)p_custom_pattern,
-                               (uint32_t)cust_pattern_size);
-
-               if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
-                       /* Set Test Pattern state */
-                       link->test_pattern_enabled = true;
-                       if (p_link_settings != NULL)
-                               dpcd_set_link_settings(link,
-                                               p_link_settings);
-               }
-
-               switch (test_pattern) {
-               case DP_TEST_PATTERN_VIDEO_MODE:
-                       pattern = PHY_TEST_PATTERN_NONE;
-                       break;
-               case DP_TEST_PATTERN_D102:
-                       pattern = PHY_TEST_PATTERN_D10_2;
-                       break;
-               case DP_TEST_PATTERN_SYMBOL_ERROR:
-                       pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
-                       break;
-               case DP_TEST_PATTERN_PRBS7:
-                       pattern = PHY_TEST_PATTERN_PRBS7;
-                       break;
-               case DP_TEST_PATTERN_80BIT_CUSTOM:
-                       pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
-                       break;
-               case DP_TEST_PATTERN_CP2520_1:
-                       pattern = PHY_TEST_PATTERN_CP2520_1;
-                       break;
-               case DP_TEST_PATTERN_CP2520_2:
-                       pattern = PHY_TEST_PATTERN_CP2520_2;
-                       break;
-               case DP_TEST_PATTERN_CP2520_3:
-                       pattern = PHY_TEST_PATTERN_CP2520_3;
-                       break;
-               case DP_TEST_PATTERN_128b_132b_TPS1:
-                       pattern = PHY_TEST_PATTERN_128b_132b_TPS1;
-                       break;
-               case DP_TEST_PATTERN_128b_132b_TPS2:
-                       pattern = PHY_TEST_PATTERN_128b_132b_TPS2;
-                       break;
-               case DP_TEST_PATTERN_PRBS9:
-                       pattern = PHY_TEST_PATTERN_PRBS9;
-                       break;
-               case DP_TEST_PATTERN_PRBS11:
-                       pattern = PHY_TEST_PATTERN_PRBS11;
-                       break;
-               case DP_TEST_PATTERN_PRBS15:
-                       pattern = PHY_TEST_PATTERN_PRBS15;
-                       break;
-               case DP_TEST_PATTERN_PRBS23:
-                       pattern = PHY_TEST_PATTERN_PRBS23;
-                       break;
-               case DP_TEST_PATTERN_PRBS31:
-                       pattern = PHY_TEST_PATTERN_PRBS31;
-                       break;
-               case DP_TEST_PATTERN_264BIT_CUSTOM:
-                       pattern = PHY_TEST_PATTERN_264BIT_CUSTOM;
-                       break;
-               case DP_TEST_PATTERN_SQUARE:
-                       pattern = PHY_TEST_PATTERN_SQUARE;
-                       break;
-               case DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED:
-                       pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED;
-                       break;
-               case DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED:
-                       pattern = PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED;
-                       break;
-               case DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED:
-                       pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED;
-                       break;
-               default:
-                       return false;
-               }
-
-               if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
-               /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
-                       return false;
-
-               if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
-                       if (is_dp_phy_sqaure_pattern(test_pattern))
-                               core_link_write_dpcd(link,
-                                               DP_LINK_SQUARE_PATTERN,
-                                               p_custom_pattern,
-                                               1);
-
-                       /* tell receiver that we are sending qualification
-                        * pattern DP 1.2 or later - DP receiver's link quality
-                        * pattern is set using DPCD LINK_QUAL_LANEx_SET
-                        * register (0x10B~0x10E)\
-                        */
-                       for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
-                               link_qual_pattern[lane] =
-                                               (unsigned char)(pattern);
-
-                       core_link_write_dpcd(link,
-                                       DP_LINK_QUAL_LANE0_SET,
-                                       link_qual_pattern,
-                                       sizeof(link_qual_pattern));
-               } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
-                          link->dpcd_caps.dpcd_rev.raw == 0) {
-                       /* tell receiver that we are sending qualification
-                        * pattern DP 1.1a or earlier - DP receiver's link
-                        * quality pattern is set using
-                        * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
-                        * register (0x102). We will use v_1.3 when we are
-                        * setting test pattern for DP 1.1.
-                        */
-                       core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
-                                           &training_pattern.raw,
-                                           sizeof(training_pattern));
-                       training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
-                       core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
-                                            &training_pattern.raw,
-                                            sizeof(training_pattern));
-               }
-       } else {
-               enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
-
-               switch (test_pattern_color_space) {
-               case DP_TEST_PATTERN_COLOR_SPACE_RGB:
-                       color_space = COLOR_SPACE_SRGB;
-                       if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
-                               color_space = COLOR_SPACE_SRGB_LIMITED;
-                       break;
-
-               case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
-                       color_space = COLOR_SPACE_YCBCR601;
-                       if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
-                               color_space = COLOR_SPACE_YCBCR601_LIMITED;
-                       break;
-               case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
-                       color_space = COLOR_SPACE_YCBCR709;
-                       if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
-                               color_space = COLOR_SPACE_YCBCR709_LIMITED;
-                       break;
-               default:
-                       break;
-               }
-
-               if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) {
-                       if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
-                               union dmub_hw_lock_flags hw_locks = { 0 };
-                               struct dmub_hw_lock_inst_flags inst_flags = { 0 };
-
-                               hw_locks.bits.lock_dig = 1;
-                               inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
-
-                               dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
-                                                       true,
-                                                       &hw_locks,
-                                                       &inst_flags);
-                       } else
-                               pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable(
-                                               pipe_ctx->stream_res.tg);
-               }
-
-               pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
-               /* update MSA to requested color space */
-               pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc,
-                               &pipe_ctx->stream->timing,
-                               color_space,
-                               pipe_ctx->stream->use_vsc_sdp_for_colorimetry,
-                               link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
-
-               if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) {
-                       if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
-                               pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range
-                       else
-                               pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7);
-                       resource_build_info_frame(pipe_ctx);
-                       link->dc->hwss.update_info_frame(pipe_ctx);
-               }
-
-               /* CRTC Patterns */
-               set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
-               pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
-               pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
-                               CRTC_STATE_VACTIVE);
-               pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
-                               CRTC_STATE_VBLANK);
-               pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
-                               CRTC_STATE_VACTIVE);
-
-               if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) {
-                       if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
-                               union dmub_hw_lock_flags hw_locks = { 0 };
-                               struct dmub_hw_lock_inst_flags inst_flags = { 0 };
-
-                               hw_locks.bits.lock_dig = 1;
-                               inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
-
-                               dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
-                                                       false,
-                                                       &hw_locks,
-                                                       &inst_flags);
-                       } else
-                               pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable(
-                                               pipe_ctx->stream_res.tg);
-               }
-
-               /* Set Test Pattern state */
-               link->test_pattern_enabled = true;
-       }
-
-       return true;
-}
-
-void dp_enable_mst_on_sink(struct dc_link *link, bool enable)
-{
-       unsigned char mstmCntl;
-
-       core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
-       if (enable)
-               mstmCntl |= DP_MST_EN;
-       else
-               mstmCntl &= (~DP_MST_EN);
-
-       core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
-}
-
-void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode)
-{
-       union dpcd_edp_config edp_config_set;
-       bool panel_mode_edp = false;
-
-       memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
-
-       if (panel_mode != DP_PANEL_MODE_DEFAULT) {
-
-               switch (panel_mode) {
-               case DP_PANEL_MODE_EDP:
-               case DP_PANEL_MODE_SPECIAL:
-                       panel_mode_edp = true;
-                       break;
-
-               default:
-                               break;
-               }
-
-               /*set edp panel mode in receiver*/
-               core_link_read_dpcd(
-                       link,
-                       DP_EDP_CONFIGURATION_SET,
-                       &edp_config_set.raw,
-                       sizeof(edp_config_set.raw));
-
-               if (edp_config_set.bits.PANEL_MODE_EDP
-                       != panel_mode_edp) {
-                       enum dc_status result;
-
-                       edp_config_set.bits.PANEL_MODE_EDP =
-                       panel_mode_edp;
-                       result = core_link_write_dpcd(
-                               link,
-                               DP_EDP_CONFIGURATION_SET,
-                               &edp_config_set.raw,
-                               sizeof(edp_config_set.raw));
-
-                       ASSERT(result == DC_OK);
-               }
-       }
-       DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
-                "eDP panel mode enabled: %d \n",
-                link->link_index,
-                link->dpcd_caps.panel_mode_edp,
-                panel_mode_edp);
-}
-
-enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
-{
-       /* We need to explicitly check that connector
-        * is not DP. Some Travis_VGA get reported
-        * by video bios as DP.
-        */
-       if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
-
-               switch (link->dpcd_caps.branch_dev_id) {
-               case DP_BRANCH_DEVICE_ID_0022B9:
-                       /* alternate scrambler reset is required for Travis
-                        * for the case when external chip does not
-                        * provide sink device id, alternate scrambler
-                        * scheme will  be overriden later by querying
-                        * Encoder features
-                        */
-                       if (strncmp(
-                               link->dpcd_caps.branch_dev_name,
-                               DP_VGA_LVDS_CONVERTER_ID_2,
-                               sizeof(
-                               link->dpcd_caps.
-                               branch_dev_name)) == 0) {
-                                       return DP_PANEL_MODE_SPECIAL;
-                       }
-                       break;
-               case DP_BRANCH_DEVICE_ID_00001A:
-                       /* alternate scrambler reset is required for Travis
-                        * for the case when external chip does not provide
-                        * sink device id, alternate scrambler scheme will
-                        * be overriden later by querying Encoder feature
-                        */
-                       if (strncmp(link->dpcd_caps.branch_dev_name,
-                               DP_VGA_LVDS_CONVERTER_ID_3,
-                               sizeof(
-                               link->dpcd_caps.
-                               branch_dev_name)) == 0) {
-                                       return DP_PANEL_MODE_SPECIAL;
-                       }
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       if (link->dpcd_caps.panel_mode_edp &&
-               (link->connector_signal == SIGNAL_TYPE_EDP ||
-                (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
-                 link->is_internal_display))) {
-               return DP_PANEL_MODE_EDP;
-       }
-
-       return DP_PANEL_MODE_DEFAULT;
-}
-
-enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready)
-{
-       /* FEC has to be "set ready" before the link training.
-        * The policy is to always train with FEC
-        * if the sink supports it and leave it enabled on link.
-        * If FEC is not supported, disable it.
-        */
-       struct link_encoder *link_enc = NULL;
-       enum dc_status status = DC_OK;
-       uint8_t fec_config = 0;
-
-       link_enc = link_enc_cfg_get_link_enc(link);
-       ASSERT(link_enc);
-
-       if (!dc_link_should_enable_fec(link))
-               return status;
-
-       if (link_enc->funcs->fec_set_ready &&
-                       link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
-               if (ready) {
-                       fec_config = 1;
-                       status = core_link_write_dpcd(link,
-                                       DP_FEC_CONFIGURATION,
-                                       &fec_config,
-                                       sizeof(fec_config));
-                       if (status == DC_OK) {
-                               link_enc->funcs->fec_set_ready(link_enc, true);
-                               link->fec_state = dc_link_fec_ready;
-                       } else {
-                               link_enc->funcs->fec_set_ready(link_enc, false);
-                               link->fec_state = dc_link_fec_not_ready;
-                               dm_error("dpcd write failed to set fec_ready");
-                       }
-               } else if (link->fec_state == dc_link_fec_ready) {
-                       fec_config = 0;
-                       status = core_link_write_dpcd(link,
-                                       DP_FEC_CONFIGURATION,
-                                       &fec_config,
-                                       sizeof(fec_config));
-                       link_enc->funcs->fec_set_ready(link_enc, false);
-                       link->fec_state = dc_link_fec_not_ready;
-               }
-       }
-
-       return status;
-}
-
-void dp_set_fec_enable(struct dc_link *link, bool enable)
-{
-       struct link_encoder *link_enc = NULL;
-
-       link_enc = link_enc_cfg_get_link_enc(link);
-       ASSERT(link_enc);
-
-       if (!dc_link_should_enable_fec(link))
-               return;
-
-       if (link_enc->funcs->fec_set_enable &&
-                       link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
-               if (link->fec_state == dc_link_fec_ready && enable) {
-                       /* Accord to DP spec, FEC enable sequence can first
-                        * be transmitted anytime after 1000 LL codes have
-                        * been transmitted on the link after link training
-                        * completion. Using 1 lane RBR should have the maximum
-                        * time for transmitting 1000 LL codes which is 6.173 us.
-                        * So use 7 microseconds delay instead.
-                        */
-                       udelay(7);
-                       link_enc->funcs->fec_set_enable(link_enc, true);
-                       link->fec_state = dc_link_fec_enabled;
-               } else if (link->fec_state == dc_link_fec_enabled && !enable) {
-                       link_enc->funcs->fec_set_enable(link_enc, false);
-                       link->fec_state = dc_link_fec_ready;
-               }
-       }
-}
-
-bool dc_link_set_backlight_level_nits(struct dc_link *link,
-               bool isHDR,
-               uint32_t backlight_millinits,
-               uint32_t transition_time_in_ms)
-{
-       struct dpcd_source_backlight_set dpcd_backlight_set;
-       uint8_t backlight_control = isHDR ? 1 : 0;
-
-       if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
-                       link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
-               return false;
-
-       // OLEDs have no PWM, they can only use AUX
-       if (link->dpcd_sink_ext_caps.bits.oled == 1)
-               backlight_control = 1;
-
-       *(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits;
-       *(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms;
-
-
-       if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
-                       (uint8_t *)(&dpcd_backlight_set),
-                       sizeof(dpcd_backlight_set)) != DC_OK)
-               return false;
-
-       if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL,
-                       &backlight_control, 1) != DC_OK)
-               return false;
-
-       return true;
-}
-
-bool dc_link_get_backlight_level_nits(struct dc_link *link,
-               uint32_t *backlight_millinits_avg,
-               uint32_t *backlight_millinits_peak)
-{
-       union dpcd_source_backlight_get dpcd_backlight_get;
-
-       memset(&dpcd_backlight_get, 0, sizeof(union dpcd_source_backlight_get));
-
-       if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
-                       link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
-               return false;
-
-       if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK,
-                       dpcd_backlight_get.raw,
-                       sizeof(union dpcd_source_backlight_get)))
-               return false;
-
-       *backlight_millinits_avg =
-               dpcd_backlight_get.bytes.backlight_millinits_avg;
-       *backlight_millinits_peak =
-               dpcd_backlight_get.bytes.backlight_millinits_peak;
-
-       /* On non-supported panels dpcd_read usually succeeds with 0 returned */
-       if (*backlight_millinits_avg == 0 ||
-                       *backlight_millinits_avg > *backlight_millinits_peak)
-               return false;
-
-       return true;
-}
-
-bool dc_link_backlight_enable_aux(struct dc_link *link, bool enable)
-{
-       uint8_t backlight_enable = enable ? 1 : 0;
-
-       if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
-               link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
-               return false;
-
-       if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
-               &backlight_enable, 1) != DC_OK)
-               return false;
-
-       return true;
-}
-
-// we read default from 0x320 because we expect BIOS wrote it there
-// regular get_backlight_nit reads from panel set at 0x326
-bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits)
-{
-       if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
-               link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
-               return false;
-
-       if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
-               (uint8_t *) backlight_millinits,
-               sizeof(uint32_t)))
-               return false;
-
-       return true;
-}
-
-bool dc_link_set_default_brightness_aux(struct dc_link *link)
-{
-       uint32_t default_backlight;
-
-       if (link && link->dpcd_sink_ext_caps.bits.oled == 1) {
-               if (!dc_link_read_default_bl_aux(link, &default_backlight))
-                       default_backlight = 150000;
-               // if < 5 nits or > 5000, it might be wrong readback
-               if (default_backlight < 5000 || default_backlight > 5000000)
-                       default_backlight = 150000; //
-
-               return dc_link_set_backlight_level_nits(link, true,
-                               default_backlight, 0);
-       }
-       return false;
-}
-
-bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timing *crtc_timing)
-{
-       struct dc_link_settings link_setting;
-       uint8_t link_bw_set;
-       uint8_t link_rate_set;
-       uint32_t req_bw;
-       union lane_count_set lane_count_set = {0};
-
-       ASSERT(link || crtc_timing); // invalid input
-
-       if (link->dpcd_caps.edp_supported_link_rates_count == 0 ||
-                       !link->panel_config.ilr.optimize_edp_link_rate)
-               return false;
-
-
-       // Read DPCD 00100h to find if standard link rates are set
-       core_link_read_dpcd(link, DP_LINK_BW_SET,
-                               &link_bw_set, sizeof(link_bw_set));
-
-       if (link_bw_set) {
-               DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS used link_bw_set\n");
-               return true;
-       }
-
-       // Read DPCD 00115h to find the edp link rate set used
-       core_link_read_dpcd(link, DP_LINK_RATE_SET,
-                           &link_rate_set, sizeof(link_rate_set));
-
-       // Read DPCD 00101h to find out the number of lanes currently set
-       core_link_read_dpcd(link, DP_LANE_COUNT_SET,
-                               &lane_count_set.raw, sizeof(lane_count_set));
-
-       req_bw = dc_bandwidth_in_kbps_from_timing(crtc_timing);
-
-       if (!crtc_timing->flags.DSC)
-               dc_link_decide_edp_link_settings(link, &link_setting, req_bw);
-       else
-               decide_edp_link_settings_with_dsc(link, &link_setting, req_bw, LINK_RATE_UNKNOWN);
-
-       if (link->dpcd_caps.edp_supported_link_rates[link_rate_set] != link_setting.link_rate ||
-                       lane_count_set.bits.LANE_COUNT_SET != link_setting.lane_count) {
-               DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS link_rate_set not optimal\n");
-               return true;
-       }
-
-       DC_LOG_EVENT_LINK_TRAINING("eDP ILR: No optimization required, VBIOS set optimal link_rate_set\n");
-       return false;
-}
-
-
-// TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST)
-static void get_lane_status(
-       struct dc_link *link,
-       uint32_t lane_count,
-       union lane_status *status,
-       union lane_align_status_updated *status_updated)
-{
-       unsigned int lane;
-       uint8_t dpcd_buf[3] = {0};
-
-       if (status == NULL || status_updated == NULL) {
-               return;
-       }
-
-       core_link_read_dpcd(
-                       link,
-                       DP_LANE0_1_STATUS,
-                       dpcd_buf,
-                       sizeof(dpcd_buf));
-
-       for (lane = 0; lane < lane_count; lane++) {
-               status[lane].raw = get_nibble_at_index(&dpcd_buf[0], lane);
-       }
-
-       status_updated->raw = dpcd_buf[2];
-}
-
-bool dpcd_write_128b_132b_sst_payload_allocation_table(
-               const struct dc_stream_state *stream,
-               struct dc_link *link,
-               struct link_mst_stream_allocation_table *proposed_table,
-               bool allocate)
-{
-       const uint8_t vc_id = 1; /// VC ID always 1 for SST
-       const uint8_t start_time_slot = 0; /// Always start at time slot 0 for SST
-       bool result = false;
-       uint8_t req_slot_count = 0;
-       struct fixed31_32 avg_time_slots_per_mtp = { 0 };
-       union payload_table_update_status update_status = { 0 };
-       const uint32_t max_retries = 30;
-       uint32_t retries = 0;
-
-       if (allocate)   {
-               avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link);
-               req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);
-               /// Validation should filter out modes that exceed link BW
-               ASSERT(req_slot_count <= MAX_MTP_SLOT_COUNT);
-               if (req_slot_count > MAX_MTP_SLOT_COUNT)
-                       return false;
-       } else {
-               /// Leave req_slot_count = 0 if allocate is false.
-       }
-
-       proposed_table->stream_count = 1; /// Always 1 stream for SST
-       proposed_table->stream_allocations[0].slot_count = req_slot_count;
-       proposed_table->stream_allocations[0].vcp_id = vc_id;
-
-       if (link->aux_access_disabled)
-               return true;
-
-       /// Write DPCD 2C0 = 1 to start updating
-       update_status.bits.VC_PAYLOAD_TABLE_UPDATED = 1;
-       core_link_write_dpcd(
-                       link,
-                       DP_PAYLOAD_TABLE_UPDATE_STATUS,
-                       &update_status.raw,
-                       1);
-
-       /// Program the changes in DPCD 1C0 - 1C2
-       ASSERT(vc_id == 1);
-       core_link_write_dpcd(
-                       link,
-                       DP_PAYLOAD_ALLOCATE_SET,
-                       &vc_id,
-                       1);
-
-       ASSERT(start_time_slot == 0);
-       core_link_write_dpcd(
-                       link,
-                       DP_PAYLOAD_ALLOCATE_START_TIME_SLOT,
-                       &start_time_slot,
-                       1);
-
-       core_link_write_dpcd(
-                       link,
-                       DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT,
-                       &req_slot_count,
-                       1);
-
-       /// Poll till DPCD 2C0 read 1
-       /// Try for at least 150ms (30 retries, with 5ms delay after each attempt)
-
-       while (retries < max_retries) {
-               if (core_link_read_dpcd(
-                               link,
-                               DP_PAYLOAD_TABLE_UPDATE_STATUS,
-                               &update_status.raw,
-                               1) == DC_OK) {
-                       if (update_status.bits.VC_PAYLOAD_TABLE_UPDATED == 1) {
-                               DC_LOG_DP2("SST Update Payload: downstream payload table updated.");
-                               result = true;
-                               break;
-                       }
-               } else {
-                       union dpcd_rev dpcdRev;
-
-                       if (core_link_read_dpcd(
-                                       link,
-                                       DP_DPCD_REV,
-                                       &dpcdRev.raw,
-                                       1) != DC_OK) {
-                               DC_LOG_ERROR("SST Update Payload: Unable to read DPCD revision "
-                                               "of sink while polling payload table "
-                                               "updated status bit.");
-                               break;
-                       }
-               }
-               retries++;
-               msleep(5);
-       }
-
-       if (!result && retries == max_retries) {
-               DC_LOG_ERROR("SST Update Payload: Payload table not updated after retries, "
-                               "continue on. Something is wrong with the branch.");
-               // TODO - DP2.0 Payload: Read and log the payload table from downstream branch
-       }
-
-       return result;
-}
-
-bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link)
-{
-       /*
-        * wait for ACT handled
-        */
-       int i;
-       const int act_retries = 30;
-       enum act_return_status result = ACT_FAILED;
-       union payload_table_update_status update_status = {0};
-       union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
-       union lane_align_status_updated lane_status_updated;
-
-       if (link->aux_access_disabled)
-               return true;
-       for (i = 0; i < act_retries; i++) {
-               get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated);
-
-               if (!dp_is_cr_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
-                               !dp_is_ch_eq_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
-                               !dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) ||
-                               !dp_is_interlane_aligned(lane_status_updated)) {
-                       DC_LOG_ERROR("SST Update Payload: Link loss occurred while "
-                                       "polling for ACT handled.");
-                       result = ACT_LINK_LOST;
-                       break;
-               }
-               core_link_read_dpcd(
-                               link,
-                               DP_PAYLOAD_TABLE_UPDATE_STATUS,
-                               &update_status.raw,
-                               1);
-
-               if (update_status.bits.ACT_HANDLED == 1) {
-                       DC_LOG_DP2("SST Update Payload: ACT handled by downstream.");
-                       result = ACT_SUCCESS;
-                       break;
-               }
-
-               msleep(5);
-       }
-
-       if (result == ACT_FAILED) {
-               DC_LOG_ERROR("SST Update Payload: ACT still not handled after retries, "
-                               "continue on. Something is wrong with the branch.");
-       }
-
-       return (result == ACT_SUCCESS);
-}
-
-struct fixed31_32 calculate_sst_avg_time_slots_per_mtp(
-               const struct dc_stream_state *stream,
-               const struct dc_link *link)
-{
-       struct fixed31_32 link_bw_effective =
-                       dc_fixpt_from_int(
-                                       dc_link_bandwidth_kbps(link, &link->cur_link_settings));
-       struct fixed31_32 timeslot_bw_effective =
-                       dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT);
-       struct fixed31_32 timing_bw =
-                       dc_fixpt_from_int(
-                                       dc_bandwidth_in_kbps_from_timing(&stream->timing));
-       struct fixed31_32 avg_time_slots_per_mtp =
-                       dc_fixpt_div(timing_bw, timeslot_bw_effective);
-
-       return avg_time_slots_per_mtp;
-}
-
-void edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd)
-{
-       if (link->connector_signal != SIGNAL_TYPE_EDP)
-               return;
-
-       link->dc->hwss.edp_power_control(link, true);
-       if (wait_for_hpd)
-               link->dc->hwss.edp_wait_for_hpd_ready(link, true);
-       if (link->dc->hwss.edp_backlight_control)
-               link->dc->hwss.edp_backlight_control(link, true);
-}
-
-void dc_link_clear_dprx_states(struct dc_link *link)
-{
-       memset(&link->dprx_states, 0, sizeof(link->dprx_states));
-}
-
-void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode)
-{
-       if (link != NULL && link->dc->debug.enable_driver_sequence_debug)
-               core_link_write_dpcd(link, DP_SOURCE_SEQUENCE,
-                                       &dp_test_mode, sizeof(dp_test_mode));
-}
-
-void edp_add_delay_for_T9(struct dc_link *link)
-{
-       if (link && link->panel_config.pps.extra_delay_backlight_off > 0)
-               udelay(link->panel_config.pps.extra_delay_backlight_off * 1000);
-}
-
-bool edp_receiver_ready_T9(struct dc_link *link)
-{
-       unsigned int tries = 0;
-       unsigned char sinkstatus = 0;
-       unsigned char edpRev = 0;
-       enum dc_status result = DC_OK;
-
-       result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
-
-       /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
-       if (result == DC_OK && edpRev >= DP_EDP_12) {
-               do {
-                       sinkstatus = 1;
-                       result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
-                       if (sinkstatus == 0)
-                               break;
-                       if (result != DC_OK)
-                               break;
-                       udelay(100); //MAx T9
-               } while (++tries < 50);
-       }
-
-       return result;
-}
-bool edp_receiver_ready_T7(struct dc_link *link)
-{
-       unsigned char sinkstatus = 0;
-       unsigned char edpRev = 0;
-       enum dc_status result = DC_OK;
-
-       /* use absolute time stamp to constrain max T7*/
-       unsigned long long enter_timestamp = 0;
-       unsigned long long finish_timestamp = 0;
-       unsigned long long time_taken_in_ns = 0;
-
-       result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
-
-       if (result == DC_OK && edpRev >= DP_EDP_12) {
-               /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
-               enter_timestamp = dm_get_timestamp(link->ctx);
-               do {
-                       sinkstatus = 0;
-                       result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
-                       if (sinkstatus == 1)
-                               break;
-                       if (result != DC_OK)
-                               break;
-                       udelay(25);
-                       finish_timestamp = dm_get_timestamp(link->ctx);
-                       time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp);
-               } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms
-       }
-
-       if (link && link->panel_config.pps.extra_t7_ms > 0)
-               udelay(link->panel_config.pps.extra_t7_ms * 1000);
-
-       return result;
-}
-
-void dp_retrain_link_dp_test(struct dc_link *link,
-                       struct dc_link_settings *link_setting,
-                       bool skip_video_pattern)
-{
-       struct pipe_ctx *pipe;
-       unsigned int i;
-
-       udelay(100);
-
-       for (i = 0; i < MAX_PIPES; i++) {
-               pipe = &link->dc->current_state->res_ctx.pipe_ctx[i];
-               if (pipe->stream != NULL &&
-                               pipe->stream->link == link &&
-                               !pipe->stream->dpms_off &&
-                               !pipe->top_pipe && !pipe->prev_odm_pipe) {
-                       core_link_disable_stream(pipe);
-                       pipe->link_config.dp_link_settings = *link_setting;
-                       update_dp_encoder_resources_for_test_harness(
-                                       link->dc,
-                                       pipe->stream->ctx->dc->current_state,
-                                       pipe);
-               }
-       }
-
-       for (i = 0; i < MAX_PIPES; i++) {
-               pipe = &link->dc->current_state->res_ctx.pipe_ctx[i];
-               if (pipe->stream != NULL &&
-                               pipe->stream->link == link &&
-                               !pipe->stream->dpms_off &&
-                               !pipe->top_pipe && !pipe->prev_odm_pipe) {
-                       core_link_enable_stream(
-                                       pipe->stream->ctx->dc->current_state,
-                                       pipe);
-               }
-       }
-}
-
-#undef DC_LOGGER
-#define DC_LOGGER \
-       dsc->ctx->logger
-static void dsc_optc_config_log(struct display_stream_compressor *dsc,
-               struct dsc_optc_config *config)
-{
-       uint32_t precision = 1 << 28;
-       uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision;
-       uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision;
-       uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod;
-
-       /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC
-        * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is
-        * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal
-        */
-       ll_bytes_per_pix_fraq *= 10000000;
-       ll_bytes_per_pix_fraq /= precision;
-
-       DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)",
-                       config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq);
-       DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444);
-       DC_LOG_DSC("\tslice_width %d", config->slice_width);
-}
-
-bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
-{
-       struct dc *dc = pipe_ctx->stream->ctx->dc;
-       struct dc_stream_state *stream = pipe_ctx->stream;
-       bool result = false;
-
-       if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
-               result = true;
-       else
-               result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable);
-       return result;
-}
-
-/* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first,
- * i.e. after dp_enable_dsc_on_rx() had been called
- */
-void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
-{
-       struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
-       struct dc *dc = pipe_ctx->stream->ctx->dc;
-       struct dc_stream_state *stream = pipe_ctx->stream;
-       struct pipe_ctx *odm_pipe;
-       int opp_cnt = 1;
-
-       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
-               opp_cnt++;
-
-       if (enable) {
-               struct dsc_config dsc_cfg;
-               struct dsc_optc_config dsc_optc_cfg;
-               enum optc_dsc_mode optc_dsc_mode;
-
-               /* Enable DSC hw block */
-               dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
-               dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
-               dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
-               dsc_cfg.color_depth = stream->timing.display_color_depth;
-               dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
-               dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
-               ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
-               dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
-
-               dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
-               dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
-               for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
-                       struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
-
-                       odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
-                       odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
-               }
-               dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
-               dsc_cfg.pic_width *= opp_cnt;
-
-               optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
-
-               /* Enable DSC in encoder */
-               if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)
-                               && !link_is_dp_128b_132b_signal(pipe_ctx)) {
-                       DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
-                       dsc_optc_config_log(dsc, &dsc_optc_cfg);
-                       pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
-                                                                       optc_dsc_mode,
-                                                                       dsc_optc_cfg.bytes_per_pixel,
-                                                                       dsc_optc_cfg.slice_width);
-
-                       /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */
-               }
-
-               /* Enable DSC in OPTC */
-               DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);
-               dsc_optc_config_log(dsc, &dsc_optc_cfg);
-               pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
-                                                       optc_dsc_mode,
-                                                       dsc_optc_cfg.bytes_per_pixel,
-                                                       dsc_optc_cfg.slice_width);
-       } else {
-               /* disable DSC in OPTC */
-               pipe_ctx->stream_res.tg->funcs->set_dsc_config(
-                               pipe_ctx->stream_res.tg,
-                               OPTC_DSC_DISABLED, 0, 0);
-
-               /* disable DSC in stream encoder */
-               if (dc_is_dp_signal(stream->signal)) {
-                       if (link_is_dp_128b_132b_signal(pipe_ctx))
-                               pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
-                                                                               pipe_ctx->stream_res.hpo_dp_stream_enc,
-                                                                               false,
-                                                                               NULL,
-                                                                               true);
-                       else if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
-                               pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
-                                               pipe_ctx->stream_res.stream_enc,
-                                               OPTC_DSC_DISABLED, 0, 0);
-                               pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
-                                                       pipe_ctx->stream_res.stream_enc, false, NULL, true);
-                       }
-               }
-
-               /* disable DSC block */
-               pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
-               for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
-                       odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
-       }
-}
-
-bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)
-{
-       struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
-       bool result = false;
-
-       if (!pipe_ctx->stream->timing.flags.DSC)
-               goto out;
-       if (!dsc)
-               goto out;
-
-       if (enable) {
-               {
-                       dp_set_dsc_on_stream(pipe_ctx, true);
-                       result = true;
-               }
-       } else {
-               dp_set_dsc_on_rx(pipe_ctx, false);
-               dp_set_dsc_on_stream(pipe_ctx, false);
-               result = true;
-       }
-out:
-       return result;
-}
-
-/*
- * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled;
- * hence PPS info packet update need to use frame update instead of immediate update.
- * Added parameter immediate_update for this purpose.
- * The decision to use frame update is hard-coded in function dp_update_dsc_config(),
- * which is the only place where a "false" would be passed in for param immediate_update.
- *
- * immediate_update is only applicable when DSC is enabled.
- */
-bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update)
-{
-       struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
-       struct dc_stream_state *stream = pipe_ctx->stream;
-
-       if (!pipe_ctx->stream->timing.flags.DSC || !dsc)
-               return false;
-
-       if (enable) {
-               struct dsc_config dsc_cfg;
-               uint8_t dsc_packed_pps[128];
-
-               memset(&dsc_cfg, 0, sizeof(dsc_cfg));
-               memset(dsc_packed_pps, 0, 128);
-
-               /* Enable DSC hw block */
-               dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
-               dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
-               dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
-               dsc_cfg.color_depth = stream->timing.display_color_depth;
-               dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
-               dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
-
-               dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);
-               memcpy(&stream->dsc_packed_pps[0], &dsc_packed_pps[0], sizeof(stream->dsc_packed_pps));
-               if (dc_is_dp_signal(stream->signal)) {
-                       DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);
-                       if (link_is_dp_128b_132b_signal(pipe_ctx))
-                               pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
-                                                                               pipe_ctx->stream_res.hpo_dp_stream_enc,
-                                                                               true,
-                                                                               &dsc_packed_pps[0],
-                                                                               immediate_update);
-                       else
-                               pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
-                                               pipe_ctx->stream_res.stream_enc,
-                                               true,
-                                               &dsc_packed_pps[0],
-                                               immediate_update);
-               }
-       } else {
-               /* disable DSC PPS in stream encoder */
-               memset(&stream->dsc_packed_pps[0], 0, sizeof(stream->dsc_packed_pps));
-               if (dc_is_dp_signal(stream->signal)) {
-                       if (link_is_dp_128b_132b_signal(pipe_ctx))
-                               pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
-                                                                               pipe_ctx->stream_res.hpo_dp_stream_enc,
-                                                                               false,
-                                                                               NULL,
-                                                                               true);
-                       else
-                               pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
-                                               pipe_ctx->stream_res.stream_enc, false, NULL, true);
-               }
-       }
-
-       return true;
-}
-
-
-bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx)
-{
-       struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
-
-       if (!pipe_ctx->stream->timing.flags.DSC)
-               return false;
-       if (!dsc)
-               return false;
-
-       dp_set_dsc_on_stream(pipe_ctx, true);
-       dp_set_dsc_pps_sdp(pipe_ctx, true, false);
-       return true;
-}
-
-#undef DC_LOGGER
-#define DC_LOGGER \
-       link->ctx->logger
index fa2ba3fc683b4125aadaec58394134f71efae32f..74e465ba158d2c03504d3e1c6d697f29a06867ed 100644 (file)
@@ -24,7 +24,6 @@
 
 #include "link_enc_cfg.h"
 #include "resource.h"
-#include "dc_link_dp.h"
 #include "link.h"
 
 #define DC_LOGGER dc->ctx->logger
index a5b5f8592c1b80b8d0ce1ef44b016954d0e1a892..e41bbcbc71460f02fd512a7e91a34864e1c36bca 100644 (file)
 #include "virtual/virtual_stream_encoder.h"
 #include "dpcd_defs.h"
 #include "link_enc_cfg.h"
-#include "dc_link_dp.h"
 #include "link.h"
 #include "virtual/virtual_link_hwss.h"
-#include "link/link_hwss_dio.h"
-#include "link/link_hwss_dpia.h"
-#include "link/link_hwss_hpo_dp.h"
+#include "link/hwss/link_hwss_dio.h"
+#include "link/hwss/link_hwss_dpia.h"
+#include "link/hwss/link_hwss_hpo_dp.h"
 
 #if defined(CONFIG_DRM_AMD_DC_SI)
 #include "dce60/dce60_resource.h"
@@ -3270,6 +3269,50 @@ static void set_hfvs_info_packet(
        *info_packet = stream->hfvsif_infopacket;
 }
 
+static void adaptive_sync_override_dp_info_packets_sdp_line_num(
+               const struct dc_crtc_timing *timing,
+               struct enc_sdp_line_num *sdp_line_num,
+               struct _vcs_dpi_display_pipe_dest_params_st *pipe_dlg_param)
+{
+       uint32_t asic_blank_start = 0;
+       uint32_t asic_blank_end   = 0;
+       uint32_t v_update = 0;
+
+       const struct dc_crtc_timing *tg = timing;
+
+       /* blank_start = frame end - front porch */
+       asic_blank_start = tg->v_total - tg->v_front_porch;
+
+       /* blank_end = blank_start - active */
+       asic_blank_end = (asic_blank_start - tg->v_border_bottom -
+                                               tg->v_addressable - tg->v_border_top);
+
+       if (pipe_dlg_param->vstartup_start > asic_blank_end) {
+               v_update = (tg->v_total - (pipe_dlg_param->vstartup_start - asic_blank_end));
+               sdp_line_num->adaptive_sync_line_num_valid = true;
+               sdp_line_num->adaptive_sync_line_num = (tg->v_total - v_update - 1);
+       } else {
+               sdp_line_num->adaptive_sync_line_num_valid = false;
+               sdp_line_num->adaptive_sync_line_num = 0;
+       }
+}
+
+static void set_adaptive_sync_info_packet(
+               struct dc_info_packet *info_packet,
+               const struct dc_stream_state *stream,
+               struct encoder_info_frame *info_frame,
+               struct _vcs_dpi_display_pipe_dest_params_st *pipe_dlg_param)
+{
+       if (!stream->adaptive_sync_infopacket.valid)
+               return;
+
+       adaptive_sync_override_dp_info_packets_sdp_line_num(
+                       &stream->timing,
+                       &info_frame->sdp_line_num,
+                       pipe_dlg_param);
+
+       *info_packet = stream->adaptive_sync_infopacket;
+}
 
 static void set_vtem_info_packet(
                struct dc_info_packet *info_packet,
@@ -3362,6 +3405,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
        info->vsc.valid = false;
        info->hfvsif.valid = false;
        info->vtem.valid = false;
+       info->adaptive_sync.valid = false;
        signal = pipe_ctx->stream->signal;
 
        /* HDMi and DP have different info packets*/
@@ -3382,6 +3426,10 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
                set_spd_info_packet(&info->spd, pipe_ctx->stream);
 
                set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream);
+               set_adaptive_sync_info_packet(&info->adaptive_sync,
+                                                                               pipe_ctx->stream,
+                                                                               info,
+                                                                               &pipe_ctx->pipe_dlg_param);
        }
 
        patch_gamut_packet_checksum(&info->gamut);
index 22e754ad22c834bdc634fb326af0ac1428dfe27a..42ce453064838be1f7f90f99dc1da51c54131cb9 100644 (file)
@@ -47,7 +47,7 @@ struct aux_payload;
 struct set_config_cmd_payload;
 struct dmub_notification;
 
-#define DC_VER "3.2.218"
+#define DC_VER "3.2.220"
 
 #define MAX_SURFACES 3
 #define MAX_PLANES 6
@@ -1414,6 +1414,7 @@ struct dpcd_caps {
        union dpcd_fec_capability fec_cap;
        struct dpcd_dsc_capabilities dsc_caps;
        struct dc_lttpr_caps lttpr_caps;
+       struct adaptive_sync_caps adaptive_sync_caps;
        struct dpcd_usb4_dp_tunneling_info usb4_dp_tun_info;
 
        union dp_128b_132b_supported_link_rates dp_128b_132b_supported_link_rates;
index 84da54358922996043a3831082162a900aa2cb79..184583807d45db806f64bb02ab6270055112062b 100644 (file)
@@ -502,7 +502,11 @@ union down_spread_ctrl {
        1 = Main link signal is downspread <= 0.5%
        with frequency in the range of 30kHz ~ 33kHz*/
                uint8_t SPREAD_AMP:1;
-               uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/
+               uint8_t RESERVED2:1;/*Bit 5 = RESERVED. Read all 0s*/
+       /* Bit 6 = FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE.
+       0 = FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE is not enabled by the Source device (default)
+       1 = FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE is enabled by Source device */
+               uint8_t FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE:1;
        /*Bit 7 = MSA_TIMING_PAR_IGNORE_EN
        0 = Source device will send valid data for the MSA Timing Params
        1 = Source device may send invalid data for these MSA Timing Params*/
@@ -858,6 +862,21 @@ struct psr_caps {
        unsigned int psr_power_opt_flag;
 };
 
+union dpcd_dprx_feature_enumeration_list_cont_1 {
+       struct {
+               uint8_t ADAPTIVE_SYNC_SDP_SUPPORT:1;
+               uint8_t AS_SDP_FIRST_HALF_LINE_OR_3840_PIXEL_CYCLE_WINDOW_NOT_SUPPORTED: 1;
+               uint8_t RESERVED0: 2;
+               uint8_t VSC_EXT_SDP_VER1_SUPPORT: 1;
+               uint8_t RESERVED1: 3;
+       } bits;
+       uint8_t raw;
+};
+
+struct adaptive_sync_caps {
+       union dpcd_dprx_feature_enumeration_list_cont_1 dp_adap_sync_caps;
+};
+
 /* Length of router topology ID read from DPCD in bytes. */
 #define DPCD_USB4_TOPOLOGY_ID_LEN 5
 
index 48f6a5b0933611ab3fabd607fd429ee3be065644..1927eacbfa71a5008436f64891d51744e992d4d1 100644 (file)
@@ -280,6 +280,7 @@ struct dc_link {
                bool dp_keep_receiver_powered;
                bool dp_skip_DID2;
                bool dp_skip_reset_segment;
+               bool dp_skip_fs_144hz;
                bool dp_mot_reset_segment;
                /* Some USB4 docks do not handle turning off MST DSC once it has been enabled. */
                bool dpia_mst_dsc_always_on;
@@ -370,11 +371,6 @@ bool dc_link_get_backlight_level_nits(struct dc_link *link,
                uint32_t *backlight_millinits,
                uint32_t *backlight_millinits_peak);
 
-bool dc_link_backlight_enable_aux(struct dc_link *link, bool enable);
-
-bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits);
-bool dc_link_set_default_brightness_aux(struct dc_link *link);
-
 int dc_link_get_backlight_level(const struct dc_link *dc_link);
 
 int dc_link_get_target_backlight_pwm(const struct dc_link *link);
@@ -388,16 +384,10 @@ bool dc_link_setup_psr(struct dc_link *dc_link,
                const struct dc_stream_state *stream, struct psr_config *psr_config,
                struct psr_context *psr_context);
 
-bool dc_power_alpm_dpcd_enable(struct dc_link *link, bool enable);
-
-void dc_link_get_psr_residency(const struct dc_link *link, uint32_t *residency);
-
 void dc_link_blank_all_dp_displays(struct dc *dc);
 void dc_link_blank_all_edp_displays(struct dc *dc);
 
 void dc_link_blank_dp_stream(struct dc_link *link, bool hw_init);
-bool dc_link_set_sink_vtotal_in_psr_active(const struct dc_link *link,
-               uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su);
 
 /* Request DC to detect if there is a Panel connected.
  * boot - If this call is during initial boot.
@@ -441,7 +431,8 @@ bool dc_link_wait_for_t12(struct dc_link *link);
 void dc_link_dp_handle_automated_test(struct dc_link *link);
 void dc_link_dp_handle_link_loss(struct dc_link *link);
 bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link);
-
+bool dc_link_check_link_loss_status(struct dc_link *link,
+                                      union hpd_irq_data *hpd_irq_dpcd_data);
 struct dc_sink_init_data;
 
 struct dc_sink *dc_link_add_remote_sink(
@@ -456,11 +447,6 @@ void dc_link_remove_remote_sink(
 
 /* Used by diagnostics for virtual link at the moment */
 
-void dc_link_dp_set_drive_settings(
-       struct dc_link *link,
-       const struct link_resource *link_res,
-       struct link_training_settings *lt_settings);
-
 bool dc_link_dp_set_test_pattern(
        struct dc_link *link,
        enum dp_test_pattern test_pattern,
@@ -589,4 +575,56 @@ void dc_link_dp_receiver_power_ctrl(struct dc_link *link, bool on);
 bool dc_link_decide_edp_link_settings(struct dc_link *link,
                struct dc_link_settings *link_setting,
                uint32_t req_bw);
+void dc_link_edp_panel_backlight_power_on(struct dc_link *link,
+               bool wait_for_hpd);
+
+#define LINK_TRAINING_ATTEMPTS 4
+#define LINK_TRAINING_RETRY_DELAY 50 /* ms */
+#define MAX_MTP_SLOT_COUNT 64
+#define TRAINING_AUX_RD_INTERVAL 100 //us
+#define LINK_AUX_WAKE_TIMEOUT_MS 1500 // Timeout when trying to wake unresponsive DPRX.
+
+struct dc_link;
+struct dc_stream_state;
+struct dc_link_settings;
+
+enum {
+       /*
+        * Some receivers fail to train on first try and are good
+        * on subsequent tries. 2 retries should be plenty. If we
+        * don't have a successful training then we don't expect to
+        * ever get one.
+        */
+       LINK_TRAINING_MAX_VERIFY_RETRY = 2,
+       PEAK_FACTOR_X1000 = 1006,
+};
+
+bool dp_validate_mode_timing(
+       struct dc_link *link,
+       const struct dc_crtc_timing *timing);
+
+void dp_enable_mst_on_sink(struct dc_link *link, bool enable);
+
+enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready);
+void dp_set_fec_enable(struct dc_link *link, bool enable);
+bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable);
+bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update);
+void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable);
+bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx);
+bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable);
+
+bool dpcd_write_128b_132b_sst_payload_allocation_table(
+               const struct dc_stream_state *stream,
+               struct dc_link *link,
+               struct link_mst_stream_allocation_table *proposed_table,
+               bool allocate);
+
+bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link);
+
+struct fixed31_32 calculate_sst_avg_time_slots_per_mtp(
+               const struct dc_stream_state *stream,
+               const struct dc_link *link);
+void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable);
+void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode);
+
 #endif /* DC_LINK_H_ */
index ef33d7d8a2bf79f8524bb6b7baca914d450b6b9a..567452599659c303eab99545bbb7fac8761ab25d 100644 (file)
@@ -190,6 +190,7 @@ struct dc_stream_state {
        struct dc_info_packet vsp_infopacket;
        struct dc_info_packet hfvsif_infopacket;
        struct dc_info_packet vtem_infopacket;
+       struct dc_info_packet adaptive_sync_infopacket;
        uint8_t dsc_packed_pps[128];
        struct rect src; /* composition area */
        struct rect dst; /* stream addressable area */
@@ -313,6 +314,7 @@ struct dc_stream_update {
        struct dc_info_packet *vsp_infopacket;
        struct dc_info_packet *hfvsif_infopacket;
        struct dc_info_packet *vtem_infopacket;
+       struct dc_info_packet *adaptive_sync_infopacket;
        bool *dpms_off;
        bool integer_scaling_update;
        bool *allow_freesync;
index c73a655bd68777f04994f204ac5c45b22f10817c..f653eca09ba79adfb1503998acad987744551d4a 100644 (file)
@@ -691,6 +691,7 @@ struct psr_config {
        uint8_t su_y_granularity;
        unsigned int line_time_in_us;
        uint8_t rate_control_caps;
+       uint16_t dsc_slice_height;
 };
 
 union dmcu_psr_level {
@@ -802,6 +803,7 @@ struct psr_context {
        uint8_t su_y_granularity;
        unsigned int line_time_in_us;
        uint8_t rate_control_caps;
+       uint16_t dsc_slice_height;
 };
 
 struct colorspace_transform {
index 2d3201b77d6a0d66eb0f88221fbe19c2e429c8f0..1e2d2cbe2c373788eaf2d681394e64e24bd336a1 100644 (file)
@@ -417,6 +417,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
        copy_settings_data->relock_delay_frame_cnt = 0;
        if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8)
                copy_settings_data->relock_delay_frame_cnt = 2;
+       copy_settings_data->dsc_slice_height = psr_context->dsc_slice_height;
 
        dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
        dc_dmub_srv_cmd_execute(dc->dmub_srv);
index a51bd21a796f974499255e9a3802af5903c18f43..adb36be8190e52d4a7db5e5c99dd33375c0cf68f 100644 (file)
@@ -47,7 +47,6 @@
 #include "link_enc_cfg.h"
 #include "link_hwss.h"
 #include "link.h"
-#include "dc_link_dp.h"
 #include "dccg.h"
 #include "clock_source.h"
 #include "clk_mgr.h"
@@ -65,7 +64,6 @@
 
 #include "dcn10/dcn10_hw_sequencer.h"
 
-#include "link/link_dp_trace.h"
 #include "dce110_hw_sequencer.h"
 
 #define GAMMA_HW_POINTS_NUM 256
@@ -653,10 +651,16 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
                pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
                        pipe_ctx->stream_res.stream_enc,
                        &pipe_ctx->stream_res.encoder_info_frame);
-       else
+       else {
+               if (pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num)
+                       pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num(
+                               pipe_ctx->stream_res.stream_enc,
+                               &pipe_ctx->stream_res.encoder_info_frame);
+
                pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
                        pipe_ctx->stream_res.stream_enc,
                        &pipe_ctx->stream_res.encoder_info_frame);
+       }
 }
 
 void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
@@ -807,19 +811,19 @@ void dce110_edp_power_control(
                                div64_u64(dm_get_elapse_time_in_ns(
                                                ctx,
                                                current_ts,
-                                               dp_trace_get_edp_poweroff_timestamp(link)), 1000000);
+                                               link_dp_trace_get_edp_poweroff_timestamp(link)), 1000000);
                unsigned long long time_since_edp_poweron_ms =
                                div64_u64(dm_get_elapse_time_in_ns(
                                                ctx,
                                                current_ts,
-                                               dp_trace_get_edp_poweron_timestamp(link)), 1000000);
+                                               link_dp_trace_get_edp_poweron_timestamp(link)), 1000000);
                DC_LOG_HW_RESUME_S3(
                                "%s: transition: power_up=%d current_ts=%llu edp_poweroff=%llu edp_poweron=%llu time_since_edp_poweroff_ms=%llu time_since_edp_poweron_ms=%llu",
                                __func__,
                                power_up,
                                current_ts,
-                               dp_trace_get_edp_poweroff_timestamp(link),
-                               dp_trace_get_edp_poweron_timestamp(link),
+                               link_dp_trace_get_edp_poweroff_timestamp(link),
+                               link_dp_trace_get_edp_poweron_timestamp(link),
                                time_since_edp_poweroff_ms,
                                time_since_edp_poweron_ms);
 
@@ -834,7 +838,7 @@ void dce110_edp_power_control(
                                        link->panel_config.pps.extra_t12_ms;
 
                        /* Adjust remaining_min_edp_poweroff_time_ms if this is not the first time. */
-                       if (dp_trace_get_edp_poweroff_timestamp(link) != 0) {
+                       if (link_dp_trace_get_edp_poweroff_timestamp(link) != 0) {
                                if (time_since_edp_poweroff_ms < remaining_min_edp_poweroff_time_ms)
                                        remaining_min_edp_poweroff_time_ms =
                                                remaining_min_edp_poweroff_time_ms - time_since_edp_poweroff_ms;
@@ -894,13 +898,13 @@ void dce110_edp_power_control(
                                __func__, (power_up ? "On":"Off"),
                                bp_result);
 
-               dp_trace_set_edp_power_timestamp(link, power_up);
+               link_dp_trace_set_edp_power_timestamp(link, power_up);
 
                DC_LOG_HW_RESUME_S3(
                                "%s: updated values: edp_poweroff=%llu edp_poweron=%llu\n",
                                __func__,
-                               dp_trace_get_edp_poweroff_timestamp(link),
-                               dp_trace_get_edp_poweron_timestamp(link));
+                               link_dp_trace_get_edp_poweroff_timestamp(link),
+                               link_dp_trace_get_edp_poweron_timestamp(link));
 
                if (bp_result != BP_RESULT_OK)
                        DC_LOG_ERROR(
@@ -928,14 +932,14 @@ void dce110_edp_wait_for_T12(
                return;
 
        if (!link->panel_cntl->funcs->is_panel_powered_on(link->panel_cntl) &&
-                       dp_trace_get_edp_poweroff_timestamp(link) != 0) {
+                       link_dp_trace_get_edp_poweroff_timestamp(link) != 0) {
                unsigned int t12_duration = 500; // Default T12 as per spec
                unsigned long long current_ts = dm_get_timestamp(ctx);
                unsigned long long time_since_edp_poweroff_ms =
                                div64_u64(dm_get_elapse_time_in_ns(
                                                ctx,
                                                current_ts,
-                                               dp_trace_get_edp_poweroff_timestamp(link)), 1000000);
+                                               link_dp_trace_get_edp_poweroff_timestamp(link)), 1000000);
 
                t12_duration += link->panel_config.pps.extra_t12_ms; // Add extra T12
 
@@ -1016,7 +1020,7 @@ void dce110_edp_backlight_control(
                 * we shouldn't be doing power-sequencing, hence we can skip
                 * waiting for T7-ready.
                 */
-                       edp_receiver_ready_T7(link);
+                       link_edp_receiver_ready_T7(link);
                else
                        DC_LOG_DC("edp_receiver_ready_T7 skipped\n");
        }
@@ -1047,7 +1051,7 @@ void dce110_edp_backlight_control(
        if (link->dpcd_sink_ext_caps.bits.oled ||
                link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
                link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)
-               dc_link_backlight_enable_aux(link, enable);
+               link_backlight_enable_aux(link, enable);
 
        /*edp 1.2*/
        if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) {
@@ -1059,7 +1063,7 @@ void dce110_edp_backlight_control(
                 * we shouldn't be doing power-sequencing, hence we can skip
                 * waiting for T9-ready.
                 */
-                       edp_add_delay_for_T9(link);
+                       link_edp_add_delay_for_T9(link);
                else
                        DC_LOG_DC("edp_receiver_ready_T9 skipped\n");
        }
@@ -1243,7 +1247,7 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
                                 * we shouldn't be doing power-sequencing, hence we can skip
                                 * waiting for T9-ready.
                                 */
-                               edp_receiver_ready_T9(link);
+                               link_edp_receiver_ready_T9(link);
                        }
                }
        }
index 0a0c930c1626db6b09b3bbf837bb6d264244402c..bb155734ac93da07a590c4d2521de7e0b7db9bea 100644 (file)
@@ -45,7 +45,6 @@
 #include "dcn10_hubp.h"
 #include "dcn10_hubbub.h"
 #include "dcn10_cm_common.h"
-#include "dc_link_dp.h"
 #include "dccg.h"
 #include "clk_mgr.h"
 #include "link_hwss.h"
@@ -56,7 +55,6 @@
 #include "dce/dmub_hw_lock_mgr.h"
 #include "dc_trace.h"
 #include "dce/dmub_outbox.h"
-#include "inc/dc_link_dp.h"
 #include "link.h"
 
 #define DC_LOGGER_INIT(logger)
index 1527c3b4fb19777a31379f43f93dec8bc27107a8..a1e32b9380506c932736f46d1b36fcc6111671e3 100644 (file)
@@ -28,7 +28,7 @@
 #include "dcn10_stream_encoder.h"
 #include "reg_helper.h"
 #include "hw_shared.h"
-#include "dc_link_dp.h"
+#include "link.h"
 #include "dpcd_defs.h"
 #include "dcn30/dcn30_afmt.h"
 
@@ -753,12 +753,19 @@ void enc1_stream_encoder_update_dp_info_packets(
         * use other packetIndex (such as 5,6) for other info packet
         */
 
+       if (info_frame->adaptive_sync.valid)
+               enc1_update_generic_info_packet(
+                               enc1,
+                               5,  /* packetIndex */
+                               &info_frame->adaptive_sync);
+
        /* enable/disable transmission of packet(s).
         * If enabled, packet transmission begins on the next frame
         */
        REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid);
        REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid);
        REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid);
+       REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid);
 
        /* This bit is the master enable bit.
         * When enabling secondary stream engine,
index 6bfa16d9135fe4c91d7f9990ded1e86e92920af8..916dceecd3de2726ae644ee3f7ff656442e60332 100644 (file)
@@ -46,7 +46,6 @@
 #include "dchubbub.h"
 #include "reg_helper.h"
 #include "dcn10/dcn10_cm_common.h"
-#include "dc_link_dp.h"
 #include "vm_helper.h"
 #include "dccg.h"
 #include "dc_dmub_srv.h"
@@ -2023,8 +2022,11 @@ void dcn20_prepare_bandwidth(
                }
        }
 
-       /* program dchubbub watermarks */
-       dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub,
+       /* program dchubbub watermarks:
+        * For assigning wm_optimized_required, use |= operator since we don't want
+        * to clear the value if the optimize has not happened yet
+        */
+       dc->wm_optimized_required |= hubbub->funcs->program_watermarks(hubbub,
                                        &context->bw_ctx.bw.dcn.watermarks,
                                        dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
                                        false);
index cacf3f5298b099448ecb76b78db957ad790a8352..48f662b031ebca4f33cf22fa3a9840fd9212412f 100644 (file)
@@ -29,7 +29,7 @@
 #include "dcn20_stream_encoder.h"
 #include "reg_helper.h"
 #include "hw_shared.h"
-#include "dc_link_dp.h"
+#include "link.h"
 #include "dpcd_defs.h"
 
 #define DC_LOGGER \
@@ -423,6 +423,22 @@ void enc2_set_dynamic_metadata(struct stream_encoder *enc,
        }
 }
 
+static void enc2_stream_encoder_update_dp_info_packets_sdp_line_num(
+               struct stream_encoder *enc,
+               struct encoder_info_frame *info_frame)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       if (info_frame->adaptive_sync.valid == true &&
+               info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) {
+               //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF
+               REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1);
+
+               REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM,
+                                       info_frame->sdp_line_num.adaptive_sync_line_num);
+       }
+}
+
 static void enc2_stream_encoder_update_dp_info_packets(
        struct stream_encoder *enc,
        const struct encoder_info_frame *info_frame)
@@ -587,6 +603,8 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = {
                enc2_stream_encoder_update_hdmi_info_packets,
        .stop_hdmi_info_packets =
                enc2_stream_encoder_stop_hdmi_info_packets,
+       .update_dp_info_packets_sdp_line_num =
+               enc2_stream_encoder_update_dp_info_packets_sdp_line_num,
        .update_dp_info_packets =
                enc2_stream_encoder_update_dp_info_packets,
        .send_immediate_sdp_message =
index 17df53793c9221de444e571891f09d77e8d70a7f..5f9079d3943a67e1fb2250c108996d60852bc9ff 100644 (file)
@@ -404,6 +404,22 @@ static void enc3_read_state(struct stream_encoder *enc, struct enc_state *s)
        }
 }
 
+void enc3_stream_encoder_update_dp_info_packets_sdp_line_num(
+               struct stream_encoder *enc,
+               struct encoder_info_frame *info_frame)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       if (info_frame->adaptive_sync.valid == true &&
+               info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) {
+               //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF
+               REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1);
+
+               REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM,
+                                       info_frame->sdp_line_num.adaptive_sync_line_num);
+       }
+}
+
 void enc3_stream_encoder_update_dp_info_packets(
        struct stream_encoder *enc,
        const struct encoder_info_frame *info_frame)
@@ -452,12 +468,20 @@ void enc3_stream_encoder_update_dp_info_packets(
         * use other packetIndex (such as 5,6) for other info packet
         */
 
+       if (info_frame->adaptive_sync.valid)
+               enc->vpg->funcs->update_generic_info_packet(
+                               enc->vpg,
+                               5,  /* packetIndex */
+                               &info_frame->adaptive_sync,
+                               true);
+
        /* enable/disable transmission of packet(s).
         * If enabled, packet transmission begins on the next frame
         */
        REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid);
        REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid);
        REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid);
+       REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid);
 
        /* This bit is the master enable bit.
         * When enabling secondary stream engine,
@@ -803,6 +827,8 @@ static const struct stream_encoder_funcs dcn30_str_enc_funcs = {
                enc3_stream_encoder_update_hdmi_info_packets,
        .stop_hdmi_info_packets =
                enc3_stream_encoder_stop_hdmi_info_packets,
+       .update_dp_info_packets_sdp_line_num =
+               enc3_stream_encoder_update_dp_info_packets_sdp_line_num,
        .update_dp_info_packets =
                enc3_stream_encoder_update_dp_info_packets,
        .stop_dp_info_packets =
index 54ee230e7f98d8dfdd94cb8f8347f38058703521..06310973ded2d95ed5963b8f7f7bbc3f47a121ef 100644 (file)
@@ -292,6 +292,10 @@ void enc3_stream_encoder_update_hdmi_info_packets(
 void enc3_stream_encoder_stop_hdmi_info_packets(
        struct stream_encoder *enc);
 
+void enc3_stream_encoder_update_dp_info_packets_sdp_line_num(
+               struct stream_encoder *enc,
+               struct encoder_info_frame *info_frame);
+
 void enc3_stream_encoder_update_dp_info_packets(
        struct stream_encoder *enc,
        const struct encoder_info_frame *info_frame);
index 7360b3ce4283c64f23f131e43b78661b70165d7d..444f9fad3de6aa75d51836a396186c6730227b58 100644 (file)
@@ -50,7 +50,7 @@
 #include "dpcd_defs.h"
 #include "../dcn20/dcn20_hwseq.h"
 #include "dcn30_resource.h"
-#include "inc/dc_link_dp.h"
+#include "link.h"
 
 
 
@@ -674,10 +674,16 @@ void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx)
                pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
                        pipe_ctx->stream_res.stream_enc,
                        &pipe_ctx->stream_res.encoder_info_frame);
-       else
+       else {
+               if (pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num)
+                       pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num(
+                               pipe_ctx->stream_res.stream_enc,
+                               &pipe_ctx->stream_res.encoder_info_frame);
+
                pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
                        pipe_ctx->stream_res.stream_enc,
                        &pipe_ctx->stream_res.encoder_info_frame);
+       }
 }
 
 void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
index 16639bd03adf7c40ea2ed54be5a7a7d8dbc3c496..d76f55a12eb41ce0cd6f9a6a9fdfd6c5a3eb0fae 100644 (file)
@@ -430,6 +430,22 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute(
                        MSA_DATA_LANE_3, 0);
 }
 
+static void dcn31_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num(
+               struct hpo_dp_stream_encoder *enc,
+               struct encoder_info_frame *info_frame)
+{
+       struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
+
+       if (info_frame->adaptive_sync.valid == true &&
+               info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) {
+               //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF
+               REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_SOF_REFERENCE, 1);
+
+               REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_TRANSMISSION_LINE_NUMBER,
+                                       info_frame->sdp_line_num.adaptive_sync_line_num);
+       }
+}
+
 static void dcn31_hpo_dp_stream_enc_update_dp_info_packets(
                struct hpo_dp_stream_encoder *enc,
                const struct encoder_info_frame *info_frame)
@@ -458,12 +474,20 @@ static void dcn31_hpo_dp_stream_enc_update_dp_info_packets(
                                &info_frame->hdrsmd,
                                true);
 
+       if (info_frame->adaptive_sync.valid)
+               enc->vpg->funcs->update_generic_info_packet(
+                               enc->vpg,
+                               5,  /* packetIndex */
+                               &info_frame->adaptive_sync,
+                               true);
+
        /* enable/disable transmission of packet(s).
         * If enabled, packet transmission begins on the next frame
         */
        REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->vsc.valid);
        REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL2, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->spd.valid);
        REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL3, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->hdrsmd.valid);
+       REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->adaptive_sync.valid);
 
        /* check if dynamic metadata packet transmission is enabled */
        REG_GET(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL,
@@ -714,6 +738,7 @@ static const struct hpo_dp_stream_encoder_funcs dcn30_str_enc_funcs = {
        .dp_blank = dcn31_hpo_dp_stream_enc_dp_blank,
        .disable = dcn31_hpo_dp_stream_enc_disable,
        .set_stream_attribute = dcn31_hpo_dp_stream_enc_set_stream_attribute,
+       .update_dp_info_packets_sdp_line_num = dcn31_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num,
        .update_dp_info_packets = dcn31_hpo_dp_stream_enc_update_dp_info_packets,
        .stop_dp_info_packets = dcn31_hpo_dp_stream_enc_stop_dp_info_packets,
        .dp_set_dsc_pps_info_packet = dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet,
index 0e1949d9ea582c5702f515197aec30179d39bba7..9871f9e189d3dfac62cc785b71a86bc46b510f25 100644 (file)
@@ -45,7 +45,6 @@
 #include "link_hwss.h"
 #include "dpcd_defs.h"
 #include "dce/dmub_outbox.h"
-#include "dc_link_dp.h"
 #include "link.h"
 #include "dcn10/dcn10_hw_sequencer.h"
 #include "inc/link_enc_cfg.h"
@@ -421,6 +420,11 @@ void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx)
                                &pipe_ctx->stream_res.encoder_info_frame);
                return;
        } else {
+               if (pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num)
+                       pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num(
+                               pipe_ctx->stream_res.stream_enc,
+                               &pipe_ctx->stream_res.encoder_info_frame);
+
                pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
                        pipe_ctx->stream_res.stream_enc,
                        &pipe_ctx->stream_res.encoder_info_frame);
index 67f4589f3e2392d6fb54f037fdf1dcda836d8245..b818ebe7d06de769ed94cecfd20063b5d1454148 100644 (file)
@@ -30,7 +30,7 @@
 #include "dcn314_dio_stream_encoder.h"
 #include "reg_helper.h"
 #include "hw_shared.h"
-#include "dc_link_dp.h"
+#include "link.h"
 #include "dpcd_defs.h"
 
 #define DC_LOGGER \
@@ -429,6 +429,8 @@ static const struct stream_encoder_funcs dcn314_str_enc_funcs = {
                enc3_stream_encoder_update_hdmi_info_packets,
        .stop_hdmi_info_packets =
                enc3_stream_encoder_stop_hdmi_info_packets,
+       .update_dp_info_packets_sdp_line_num =
+               enc3_stream_encoder_update_dp_info_packets_sdp_line_num,
        .update_dp_info_packets =
                enc3_stream_encoder_update_dp_info_packets,
        .stop_dp_info_packets =
index 33dfdf8b4100fefaaaa0d4ce7f866fb124c499f6..ed07723879036a9bfba404e8dae0ecf21d0b1ed9 100644 (file)
@@ -280,6 +280,10 @@ void enc3_stream_encoder_update_hdmi_info_packets(
 void enc3_stream_encoder_stop_hdmi_info_packets(
        struct stream_encoder *enc);
 
+void enc3_stream_encoder_update_dp_info_packets_sdp_line_num(
+               struct stream_encoder *enc,
+               struct encoder_info_frame *info_frame);
+
 void enc3_stream_encoder_update_dp_info_packets(
        struct stream_encoder *enc,
        const struct encoder_info_frame *info_frame);
index 7980462e3abefcf26bd6d039f4a245199a27282d..d725260336fe62b846b35f7f841c3df8e7a4e7ab 100644 (file)
@@ -46,9 +46,7 @@
 #include "link_hwss.h"
 #include "dpcd_defs.h"
 #include "dce/dmub_outbox.h"
-#include "dc_link_dp.h"
 #include "link.h"
-#include "inc/dc_link_dp.h"
 #include "dcn10/dcn10_hw_sequencer.h"
 #include "inc/link_enc_cfg.h"
 #include "dcn30/dcn30_vpg.h"
index f01968f6d18263bb9c024538f6b21f3e3551d252..3c0ce9404699ab47d606b5268fa7f9db31959a5c 100644 (file)
@@ -29,7 +29,7 @@
 #include "dcn32_dio_stream_encoder.h"
 #include "reg_helper.h"
 #include "hw_shared.h"
-#include "dc_link_dp.h"
+#include "link.h"
 #include "dpcd_defs.h"
 
 #define DC_LOGGER \
@@ -463,6 +463,8 @@ static const struct stream_encoder_funcs dcn32_str_enc_funcs = {
                enc3_stream_encoder_update_hdmi_info_packets,
        .stop_hdmi_info_packets =
                enc3_stream_encoder_stop_hdmi_info_packets,
+       .update_dp_info_packets_sdp_line_num =
+               enc3_stream_encoder_update_dp_info_packets_sdp_line_num,
        .update_dp_info_packets =
                enc3_stream_encoder_update_dp_info_packets,
        .stop_dp_info_packets =
index 3b44006e1a80d7199f8ee3326050cdf84eb197a3..addfde594622232590393f558e66a013b29e3af1 100644 (file)
@@ -51,7 +51,6 @@
 #include "dce/dmub_hw_lock_mgr.h"
 #include "dcn32_resource.h"
 #include "link.h"
-#include "dc_link_dp.h"
 #include "dmub/inc/dmub_subvp_state.h"
 
 #define DC_LOGGER_INIT(logger)
@@ -247,6 +246,13 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable)
        if (!dc->ctx->dmub_srv)
                return false;
 
+       for (i = 0; i < dc->current_state->stream_count; i++) {
+               /* MALL SS messaging is not supported with PSR at this time */
+               if (dc->current_state->streams[i] != NULL &&
+                               dc->current_state->streams[i]->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED)
+                       return false;
+       }
+
        if (enable) {
                if (dc->current_state) {
 
@@ -689,6 +695,7 @@ static void dcn32_initialize_min_clocks(struct dc *dc)
 {
        struct dc_clocks *clocks = &dc->current_state->bw_ctx.bw.dcn.clk;
 
+       clocks->dcfclk_deep_sleep_khz = DCN3_2_DCFCLK_DS_INIT_KHZ;
        clocks->dcfclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz * 1000;
        clocks->socclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].socclk_mhz * 1000;
        clocks->dramclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].memclk_mhz * 1000;
@@ -800,6 +807,16 @@ void dcn32_init_hw(struct dc *dc)
                                        !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
 
                dcn32_initialize_min_clocks(dc);
+
+               /* On HW init, allow idle optimizations after pipes have been turned off.
+                *
+                * In certain D3 cases (i.e. BOCO / BOMACO) it's possible that hardware state
+                * is reset (i.e. not in idle at the time hw init is called), but software state
+                * still has idle_optimizations = true, so we must disable idle optimizations first
+                * (i.e. set false), then re-enable (set true).
+                */
+               dc_allow_idle_optimizations(dc, false);
+               dc_allow_idle_optimizations(dc, true);
        }
 
        /* In headless boot cases, DIG may be turned
index 47dc96acdacb2a3d7b258c14c41cecb986de7115..74e50c09bb62f9156a8436d4b86025e5b9b5b8a9 100644 (file)
@@ -57,7 +57,6 @@
 #include "dcn31/dcn31_hpo_dp_stream_encoder.h"
 #include "dcn31/dcn31_hpo_dp_link_encoder.h"
 #include "dcn32/dcn32_hpo_dp_link_encoder.h"
-#include "dc_link_dp.h"
 #include "dcn31/dcn31_apg.h"
 #include "dcn31/dcn31_dio_link_encoder.h"
 #include "dcn32/dcn32_dio_link_encoder.h"
@@ -2150,13 +2149,19 @@ static bool dcn32_resource_construct(
        dc->caps.max_cursor_size = 64;
        dc->caps.min_horizontal_blanking_period = 80;
        dc->caps.dmdata_alloc_size = 2048;
-       dc->caps.mall_size_per_mem_channel = 0;
+       dc->caps.mall_size_per_mem_channel = 4;
        dc->caps.mall_size_total = 0;
        dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8;
 
        dc->caps.cache_line_size = 64;
        dc->caps.cache_num_ways = 16;
-       dc->caps.max_cab_allocation_bytes = 67108864; // 64MB = 1024 * 1024 * 64
+
+       /* Calculate the available MALL space */
+       dc->caps.max_cab_allocation_bytes = dcn32_calc_num_avail_chans_for_mall(
+               dc, dc->ctx->dc_bios->vram_info.num_chans) *
+               dc->caps.mall_size_per_mem_channel * 1024 * 1024;
+       dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes;
+
        dc->caps.subvp_fw_processing_delay_us = 15;
        dc->caps.subvp_drr_max_vblank_margin_us = 40;
        dc->caps.subvp_prefetch_end_to_mall_start_us = 15;
@@ -2593,3 +2598,55 @@ struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
 
        return idle_pipe;
 }
+
+unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans)
+{
+       /*
+        * DCN32 and DCN321 SKUs may have different sizes for MALL
+        *  but we may not be able to access all the MALL space.
+        *  If the num_chans is power of 2, then we can access all
+        *  of the available MALL space.  Otherwise, we can only
+        *  access:
+        *
+        *  max_cab_size_in_bytes = total_cache_size_in_bytes *
+        *    ((2^floor(log2(num_chans)))/num_chans)
+        *
+        * Calculating the MALL sizes for all available SKUs, we
+        *  have come up with the follow simplified check.
+        * - we have max_chans which provides the max MALL size.
+        *  Each chans supports 4MB of MALL so:
+        *
+        *  total_cache_size_in_bytes = max_chans * 4 MB
+        *
+        * - we have avail_chans which shows the number of channels
+        *  we can use if we can't access the entire MALL space.
+        *  It is generally half of max_chans
+        * - so we use the following checks:
+        *
+        *   if (num_chans == max_chans), return max_chans
+        *   if (num_chans < max_chans), return avail_chans
+        *
+        * - exception is GC_11_0_0 where we can't access max_chans,
+        *  so we define max_avail_chans as the maximum available
+        *  MALL space
+        *
+        */
+       int gc_11_0_0_max_chans = 48;
+       int gc_11_0_0_max_avail_chans = 32;
+       int gc_11_0_0_avail_chans = 16;
+       int gc_11_0_3_max_chans = 16;
+       int gc_11_0_3_avail_chans = 8;
+       int gc_11_0_2_max_chans = 8;
+       int gc_11_0_2_avail_chans = 4;
+
+       if (ASICREV_IS_GC_11_0_0(dc->ctx->asic_id.hw_internal_rev)) {
+               return (num_chans == gc_11_0_0_max_chans) ?
+                       gc_11_0_0_max_avail_chans : gc_11_0_0_avail_chans;
+       } else if (ASICREV_IS_GC_11_0_2(dc->ctx->asic_id.hw_internal_rev)) {
+               return (num_chans == gc_11_0_2_max_chans) ?
+                       gc_11_0_2_max_chans : gc_11_0_2_avail_chans;
+       } else { // if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev)) {
+               return (num_chans == gc_11_0_3_max_chans) ?
+                       gc_11_0_3_max_chans : gc_11_0_3_avail_chans;
+       }
+}
index b07d3b0e6a5c8695f81efcfb564e181f0e23b5e2..a09db7c63a04fcb32623811e65587462df6582ff 100644 (file)
@@ -38,6 +38,7 @@
 #define DCN3_2_MBLK_HEIGHT_4BPE 128
 #define DCN3_2_MBLK_HEIGHT_8BPE 64
 #define DCN3_2_VMIN_DISPCLK_HZ 717000000
+#define DCN3_2_DCFCLK_DS_INIT_KHZ 10000 // Choose 10Mhz for init DCFCLK DS freq
 
 #define TO_DCN32_RES_POOL(pool)\
        container_of(pool, struct dcn32_resource_pool, base)
@@ -122,6 +123,7 @@ bool dcn32_mpo_in_use(struct dc_state *context);
 
 bool dcn32_any_surfaces_rotated(struct dc *dc, struct dc_state *context);
 bool dcn32_is_center_timing(struct pipe_ctx *pipe);
+bool dcn32_is_psr_capable(struct pipe_ctx *pipe);
 
 struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
                struct dc_state *state,
@@ -146,6 +148,8 @@ void dcn32_restore_mall_state(struct dc *dc,
 
 bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe);
 
+unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans);
+
 /* definitions for run time init of reg offsets */
 
 /* CLK SRC */
index 0fc79d75ce766eb65f99c2e7d02817a2e9e7faee..3a2d7bcc4b6d6cb62a7238a7438ee7ed9cc7d009 100644 (file)
@@ -251,6 +251,16 @@ bool dcn32_is_center_timing(struct pipe_ctx *pipe)
        return is_center_timing;
 }
 
+bool dcn32_is_psr_capable(struct pipe_ctx *pipe)
+{
+       bool psr_capable = false;
+
+       if (pipe->stream && pipe->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED) {
+               psr_capable = true;
+       }
+       return psr_capable;
+}
+
 /**
  * *******************************************************************************************
  * dcn32_determine_det_override: Determine DET allocation for each pipe
index 260d71ca020568db11f28735fa0608c160daf18a..fd57e0167737108d4c082ce09b6c18d02dbd95f0 100644 (file)
@@ -60,7 +60,6 @@
 #include "dcn31/dcn31_hpo_dp_stream_encoder.h"
 #include "dcn31/dcn31_hpo_dp_link_encoder.h"
 #include "dcn32/dcn32_hpo_dp_link_encoder.h"
-#include "dc_link_dp.h"
 #include "dcn31/dcn31_apg.h"
 #include "dcn31/dcn31_dio_link_encoder.h"
 #include "dcn32/dcn32_dio_link_encoder.h"
@@ -1703,11 +1702,18 @@ static bool dcn321_resource_construct(
        dc->caps.max_cursor_size = 64;
        dc->caps.min_horizontal_blanking_period = 80;
        dc->caps.dmdata_alloc_size = 2048;
-       dc->caps.mall_size_per_mem_channel = 0;
+       dc->caps.mall_size_per_mem_channel = 4;
        dc->caps.mall_size_total = 0;
        dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8;
        dc->caps.cache_line_size = 64;
        dc->caps.cache_num_ways = 16;
+
+       /* Calculate the available MALL space */
+       dc->caps.max_cab_allocation_bytes = dcn32_calc_num_avail_chans_for_mall(
+               dc, dc->ctx->dc_bios->vram_info.num_chans) *
+               dc->caps.mall_size_per_mem_channel * 1024 * 1024;
+       dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes;
+
        dc->caps.max_cab_allocation_bytes = 33554432; // 32MB = 1024 * 1024 * 32
        dc->caps.subvp_fw_processing_delay_us = 15;
        dc->caps.subvp_drr_max_vblank_margin_us = 40;
index af1c50ed905abdfa3b26ca5a272bc889ca13f857..c624c768cc3d1df0973e30b2e86f7ac96ea2da43 100644 (file)
@@ -161,6 +161,12 @@ enum dc_edid_status dm_helpers_read_local_edid(
                struct dc_link *link,
                struct dc_sink *sink);
 
+bool dm_helpers_dp_handle_test_pattern_request(
+               struct dc_context *ctx,
+               const struct dc_link *link,
+               union link_test_pattern dpcd_test_pattern,
+               union test_misc dpcd_test_params);
+
 void dm_set_dcn_clocks(
                struct dc_context *ctx,
                struct dc_clocks *clks);
index d2b89c50be2a10b398124bacf5ed2c32538848ca..197df404761ac219db24ebbad1f9f17be2080a25 100644 (file)
@@ -26,7 +26,6 @@
 
 #include "resource.h"
 #include "clk_mgr.h"
-#include "dc_link_dp.h"
 #include "dchubbub.h"
 #include "dcn20/dcn20_resource.h"
 #include "dcn21/dcn21_resource.h"
@@ -1004,6 +1003,39 @@ static enum dcn_zstate_support_state  decide_zstate_support(struct dc *dc, struc
        }
 }
 
+static void dcn20_adjust_freesync_v_startup(
+               const struct dc_crtc_timing *dc_crtc_timing, int *vstartup_start)
+{
+       struct dc_crtc_timing patched_crtc_timing;
+       uint32_t asic_blank_end   = 0;
+       uint32_t asic_blank_start = 0;
+       uint32_t newVstartup      = 0;
+
+       patched_crtc_timing = *dc_crtc_timing;
+
+       if (patched_crtc_timing.flags.INTERLACE == 1) {
+               if (patched_crtc_timing.v_front_porch < 2)
+                       patched_crtc_timing.v_front_porch = 2;
+       } else {
+               if (patched_crtc_timing.v_front_porch < 1)
+                       patched_crtc_timing.v_front_porch = 1;
+       }
+
+       /* blank_start = frame end - front porch */
+       asic_blank_start = patched_crtc_timing.v_total -
+                                       patched_crtc_timing.v_front_porch;
+
+       /* blank_end = blank_start - active */
+       asic_blank_end = asic_blank_start -
+                                       patched_crtc_timing.v_border_bottom -
+                                       patched_crtc_timing.v_addressable -
+                                       patched_crtc_timing.v_border_top;
+
+       newVstartup = asic_blank_end + (patched_crtc_timing.v_total - asic_blank_start);
+
+       *vstartup_start = ((newVstartup > *vstartup_start) ? newVstartup : *vstartup_start);
+}
+
 void dcn20_calculate_dlg_params(
                struct dc *dc, struct dc_state *context,
                display_e2e_pipe_params_st *pipes,
@@ -1063,6 +1095,11 @@ void dcn20_calculate_dlg_params(
                context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz =
                                                pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
                context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest;
+               if (context->res_ctx.pipe_ctx[i].stream->adaptive_sync_infopacket.valid)
+                       dcn20_adjust_freesync_v_startup(
+                               &context->res_ctx.pipe_ctx[i].stream->timing,
+                               &context->res_ctx.pipe_ctx[i].pipe_dlg_param.vstartup_start);
+
                pipe_idx++;
        }
        /*save a original dppclock copy*/
index 7feb8759e4755303c9e2449e91d791e55c7ffc81..0dc1a03999b6f52246d952bf2f6e8601488fdc52 100644 (file)
@@ -24,7 +24,6 @@
  *
  */
 #include "dcn32_fpu.h"
-#include "dc_link_dp.h"
 #include "dcn32/dcn32_resource.h"
 #include "dcn20/dcn20_resource.h"
 #include "display_mode_vba_util_32.h"
@@ -692,7 +691,7 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
                 *   to combine this with SubVP can cause issues with the scheduling).
                 * - Not TMZ surface
                 */
-               if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) &&
+               if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) && !dcn32_is_psr_capable(pipe) &&
                                pipe->stream->mall_stream_config.type == SUBVP_NONE && refresh_rate < 120 && !pipe->plane_state->address.tmz_surface &&
                                (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0 ||
                                (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] > 0 &&
@@ -1272,6 +1271,38 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context)
        return false;
 }
 
+static void dcn20_adjust_freesync_v_startup(const struct dc_crtc_timing *dc_crtc_timing, int *vstartup_start)
+{
+       struct dc_crtc_timing patched_crtc_timing;
+       uint32_t asic_blank_end   = 0;
+       uint32_t asic_blank_start = 0;
+       uint32_t newVstartup      = 0;
+
+       patched_crtc_timing = *dc_crtc_timing;
+
+       if (patched_crtc_timing.flags.INTERLACE == 1) {
+               if (patched_crtc_timing.v_front_porch < 2)
+                       patched_crtc_timing.v_front_porch = 2;
+       } else {
+               if (patched_crtc_timing.v_front_porch < 1)
+                       patched_crtc_timing.v_front_porch = 1;
+       }
+
+       /* blank_start = frame end - front porch */
+       asic_blank_start = patched_crtc_timing.v_total -
+                                       patched_crtc_timing.v_front_porch;
+
+       /* blank_end = blank_start - active */
+       asic_blank_end = asic_blank_start -
+                                       patched_crtc_timing.v_border_bottom -
+                                       patched_crtc_timing.v_addressable -
+                                       patched_crtc_timing.v_border_top;
+
+       newVstartup = asic_blank_end + (patched_crtc_timing.v_total - asic_blank_start);
+
+       *vstartup_start = ((newVstartup > *vstartup_start) ? newVstartup : *vstartup_start);
+}
+
 static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
                                       display_e2e_pipe_params_st *pipes,
                                       int pipe_cnt, int vlevel)
@@ -1375,6 +1406,11 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
                        }
                }
 
+               if (context->res_ctx.pipe_ctx[i].stream->adaptive_sync_infopacket.valid)
+                       dcn20_adjust_freesync_v_startup(
+                               &context->res_ctx.pipe_ctx[i].stream->timing,
+                               &context->res_ctx.pipe_ctx[i].pipe_dlg_param.vstartup_start);
+
                pipe_idx++;
        }
        /* If DCN isn't making memory requests we can allow pstate change and lower clocks */
@@ -1601,16 +1637,12 @@ bool dcn32_internal_validate_bw(struct dc *dc,
                 * to support with Prefetch mode 1 (dm_prefetch_support_fclk_and_stutter == 2)
                 */
                context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
-                       dm_prefetch_support_fclk_and_stutter;
+                       dm_prefetch_support_none;
 
+               context->bw_ctx.dml.validate_max_state = fast_validate;
                vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
 
-               /* Last attempt with Prefetch mode 2 (dm_prefetch_support_stutter == 3) */
-               if (vlevel == context->bw_ctx.dml.soc.num_states) {
-                       context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
-                               dm_prefetch_support_stutter;
-                       vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
-               }
+               context->bw_ctx.dml.validate_max_state = false;
 
                if (vlevel < context->bw_ctx.dml.soc.num_states) {
                        memset(split, 0, sizeof(split));
@@ -2499,8 +2531,11 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
                }
 
                /* Override from VBIOS for num_chan */
-               if (dc->ctx->dc_bios->vram_info.num_chans)
+               if (dc->ctx->dc_bios->vram_info.num_chans) {
                        dcn3_2_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans;
+                       dcn3_2_soc.mall_allocated_for_dcn_mbytes = (double)(dcn32_calc_num_avail_chans_for_mall(dc,
+                               dc->ctx->dc_bios->vram_info.num_chans) * dc->caps.mall_size_per_mem_channel);
+               }
 
                if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
                        dcn3_2_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
index 6c5ab5c26b38240bafacc33f1fed2c1f7d1c9bca..23e50d15e9aefd2fa4995aa3b1fa751ae20b66f1 100644 (file)
@@ -1639,9 +1639,14 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
 static void mode_support_configuration(struct vba_vars_st *v,
                                  struct display_mode_lib *mode_lib)
 {
-       int i, j;
+       int i, j, start_state;
 
-       for (i = v->soc.num_states - 1; i >= 0; i--) {
+       if (mode_lib->validate_max_state)
+               start_state = v->soc.num_states - 1;
+       else
+               start_state = 0;
+
+       for (i = v->soc.num_states - 1; i >= start_state; i--) {
                for (j = 0; j < 2; j++) {
                        if (mode_lib->vba.ScaleRatioAndTapsSupport == true
                                && mode_lib->vba.SourceFormatPixelAndScanSupport == true
@@ -1710,7 +1715,7 @@ static void mode_support_configuration(struct vba_vars_st *v,
 void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib)
 {
        struct vba_vars_st *v = &mode_lib->vba;
-       int i, j;
+       int i, j, start_state;
        unsigned int k, m;
        unsigned int MaximumMPCCombine;
        unsigned int NumberOfNonCombinedSurfaceOfMaximumBandwidth;
@@ -1723,6 +1728,10 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
 #endif
 
        /*MODE SUPPORT, VOLTAGE STATE AND SOC CONFIGURATION*/
+       if (mode_lib->validate_max_state)
+               start_state = v->soc.num_states - 1;
+       else
+               start_state = 0;
 
        /*Scale Ratio, taps Support Check*/
 
@@ -2012,7 +2021,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
        mode_lib->vba.MPCCombineMethodIncompatible = v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.MPCCombineMethodAsNeededForPStateChangeAndVoltage
                        && v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.MPCCombineMethodAsPossible;
 
-       for (i = 0; i < v->soc.num_states; i++) {
+       for (i = start_state; i < v->soc.num_states; i++) {
                for (j = 0; j < 2; j++) {
                        mode_lib->vba.TotalNumberOfActiveDPP[i][j] = 0;
                        mode_lib->vba.TotalAvailablePipesSupport[i][j] = true;
@@ -2289,7 +2298,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                }
        }
 
-       for (i = 0; i < v->soc.num_states; ++i) {
+       for (i = start_state; i < v->soc.num_states; ++i) {
                mode_lib->vba.ExceededMultistreamSlots[i] = false;
                for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) {
                        if (mode_lib->vba.OutputMultistreamEn[k] == true && mode_lib->vba.OutputMultistreamId[k] == k) {
@@ -2389,7 +2398,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                }
        }
 
-       for (i = 0; i < v->soc.num_states; ++i) {
+       for (i = start_state; i < v->soc.num_states; ++i) {
                mode_lib->vba.DTBCLKRequiredMoreThanSupported[i] = false;
                for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) {
                        if (mode_lib->vba.BlendingAndTiming[k] == k
@@ -2406,7 +2415,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                }
        }
 
-       for (i = 0; i < v->soc.num_states; ++i) {
+       for (i = start_state; i < v->soc.num_states; ++i) {
                mode_lib->vba.ODMCombine2To1SupportCheckOK[i] = true;
                mode_lib->vba.ODMCombine4To1SupportCheckOK[i] = true;
                for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) {
@@ -2424,7 +2433,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                }
        }
 
-       for (i = 0; i < v->soc.num_states; i++) {
+       for (i = start_state; i < v->soc.num_states; i++) {
                mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] = false;
                for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) {
                        if (mode_lib->vba.BlendingAndTiming[k] == k) {
@@ -2461,7 +2470,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
        /* Check DSC Unit and Slices Support */
        v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.TotalDSCUnitsRequired = 0;
 
-       for (i = 0; i < v->soc.num_states; ++i) {
+       for (i = start_state; i < v->soc.num_states; ++i) {
                mode_lib->vba.NotEnoughDSCUnits[i] = false;
                mode_lib->vba.NotEnoughDSCSlices[i] = false;
                v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.TotalDSCUnitsRequired = 0;
@@ -2496,7 +2505,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
        }
 
        /*DSC Delay per state*/
-       for (i = 0; i < v->soc.num_states; ++i) {
+       for (i = start_state; i < v->soc.num_states; ++i) {
                for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) {
                        mode_lib->vba.DSCDelayPerState[i][k] = dml32_DSCDelayRequirement(
                                        mode_lib->vba.RequiresDSC[i][k], mode_lib->vba.ODMCombineEnablePerState[i][k],
@@ -2523,7 +2532,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
 
        //Calculate Swath, DET Configuration, DCFCLKDeepSleep
        //
-       for (i = 0; i < (int) v->soc.num_states; ++i) {
+       for (i = start_state; i < (int) v->soc.num_states; ++i) {
                for (j = 0; j <= 1; ++j) {
                        for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) {
                                mode_lib->vba.RequiredDPPCLKThisState[k] = mode_lib->vba.RequiredDPPCLK[i][j][k];
@@ -2661,7 +2670,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                        mode_lib->vba.SurfaceSizeInMALL,
                        &mode_lib->vba.ExceededMALLSize);
 
-       for (i = 0; i < v->soc.num_states; i++) {
+       for (i = start_state; i < v->soc.num_states; i++) {
                for (j = 0; j < 2; j++) {
                        for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) {
                                mode_lib->vba.swath_width_luma_ub_this_state[k] =
@@ -2888,7 +2897,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
        }
 
        //Calculate Return BW
-       for (i = 0; i < (int) v->soc.num_states; ++i) {
+       for (i = start_state; i < (int) v->soc.num_states; ++i) {
                for (j = 0; j <= 1; ++j) {
                        for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) {
                                if (mode_lib->vba.BlendingAndTiming[k] == k) {
@@ -2967,7 +2976,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                        &mode_lib->vba.MinPrefetchMode,
                        &mode_lib->vba.MaxPrefetchMode);
 
-       for (i = 0; i < (int) v->soc.num_states; ++i) {
+       for (i = start_state; i < (int) v->soc.num_states; ++i) {
                for (j = 0; j <= 1; ++j)
                        mode_lib->vba.DCFCLKState[i][j] = mode_lib->vba.DCFCLKPerState[i];
        }
@@ -3089,7 +3098,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                mode_lib->vba.DCFCLKState);
        } // UseMinimumRequiredDCFCLK == true
 
-       for (i = 0; i < (int) v->soc.num_states; ++i) {
+       for (i = start_state; i < (int) v->soc.num_states; ++i) {
                for (j = 0; j <= 1; ++j) {
                        mode_lib->vba.ReturnBWPerState[i][j] = dml32_get_return_bw_mbps(&mode_lib->vba.soc, i,
                                        mode_lib->vba.HostVMEnable, mode_lib->vba.DCFCLKState[i][j],
@@ -3098,7 +3107,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
        }
 
        //Re-ordering Buffer Support Check
-       for (i = 0; i < (int) v->soc.num_states; ++i) {
+       for (i = start_state; i < (int) v->soc.num_states; ++i) {
                for (j = 0; j <= 1; ++j) {
                        if ((mode_lib->vba.ROBBufferSizeInKByte - mode_lib->vba.PixelChunkSizeInKByte) * 1024
                                        / mode_lib->vba.ReturnBWPerState[i][j]
@@ -3120,7 +3129,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                + mode_lib->vba.ReadBandwidthChroma[k];
        }
 
-       for (i = 0; i < (int) v->soc.num_states; ++i) {
+       for (i = start_state; i < (int) v->soc.num_states; ++i) {
                for (j = 0; j <= 1; ++j) {
                        mode_lib->vba.MaxTotalVerticalActiveAvailableBandwidth[i][j] =
                                dml_min3(mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKState[i][j]
@@ -3144,7 +3153,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
 
        /* Prefetch Check */
 
-       for (i = 0; i < (int) v->soc.num_states; ++i) {
+       for (i = start_state; i < (int) v->soc.num_states; ++i) {
                for (j = 0; j <= 1; ++j) {
 
                        mode_lib->vba.TimeCalc = 24 / mode_lib->vba.ProjectedDCFCLKDeepSleep[i][j];
@@ -3662,7 +3671,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
 
        MaximumMPCCombine = 0;
 
-       for (i = v->soc.num_states; i >= 0; i--) {
+       for (i = v->soc.num_states; i >= start_state; i--) {
                if (i == v->soc.num_states || mode_lib->vba.ModeSupport[i][0] == true ||
                                mode_lib->vba.ModeSupport[i][1] == true) {
                        mode_lib->vba.VoltageLevel = i;
index 0ea406145c1d79397dbfe7d453951aa63ebf33b9..b80cef70fa60f113f7223e51fcfdfebb9c607dd1 100644 (file)
@@ -534,8 +534,11 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
                }
 
                /* Override from VBIOS for num_chan */
-               if (dc->ctx->dc_bios->vram_info.num_chans)
+               if (dc->ctx->dc_bios->vram_info.num_chans) {
                        dcn3_21_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans;
+                       dcn3_21_soc.mall_allocated_for_dcn_mbytes = (double)(dcn32_calc_num_avail_chans_for_mall(dc,
+                               dc->ctx->dc_bios->vram_info.num_chans) * dc->caps.mall_size_per_mem_channel);
+               }
 
                if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
                        dcn3_21_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
index 3d643d50c3eb59e69e99c4865dfb06803c1404fe..a9d49ef58fb59c07daac02ae46ae8274199a8157 100644 (file)
@@ -91,6 +91,7 @@ struct display_mode_lib {
        struct dal_logger *logger;
        struct dml_funcs funcs;
        struct _vcs_dpi_display_e2e_pipe_params_st dml_pipe_state[6];
+       bool validate_max_state;
 };
 
 void dml_init_instance(struct display_mode_lib *lib,
index 906a43e85f6dbadfef123f0df1c0f61f36ad6e9a..e1422e5e86c92e57573ddc43de405b90caa3c492 100644 (file)
@@ -32,7 +32,7 @@
 #include "core_types.h"
 #include "link.h"
 #include "link_hwss.h"
-#include "link/link_dpcd.h"
+#include "link/protocols/link_dpcd.h"
 
 #define DC_LOGGER \
        link->ctx->logger
diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
deleted file mode 100644 (file)
index 52e1aad..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2015 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#ifndef __DC_LINK_DP_H__
-#define __DC_LINK_DP_H__
-
-#define LINK_TRAINING_ATTEMPTS 4
-#define LINK_TRAINING_RETRY_DELAY 50 /* ms */
-#define MAX_MTP_SLOT_COUNT 64
-#define TRAINING_AUX_RD_INTERVAL 100 //us
-#define LINK_AUX_WAKE_TIMEOUT_MS 1500 // Timeout when trying to wake unresponsive DPRX.
-
-struct dc_link;
-struct dc_stream_state;
-struct dc_link_settings;
-
-enum {
-       /*
-        * Some receivers fail to train on first try and are good
-        * on subsequent tries. 2 retries should be plenty. If we
-        * don't have a successful training then we don't expect to
-        * ever get one.
-        */
-       LINK_TRAINING_MAX_VERIFY_RETRY = 2,
-       PEAK_FACTOR_X1000 = 1006,
-};
-
-
-bool dp_verify_link_cap_with_retries(
-       struct dc_link *link,
-       struct dc_link_settings *known_limit_link_setting,
-       int attempts);
-
-bool dp_validate_mode_timing(
-       struct dc_link *link,
-       const struct dc_crtc_timing *timing);
-
-bool hpd_rx_irq_check_link_loss_status(struct dc_link *link,
-                                      union hpd_irq_data *hpd_irq_dpcd_data);
-enum dc_status read_hpd_rx_irq_data(
-       struct dc_link *link,
-       union hpd_irq_data *irq_data);
-
-bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timing *crtc_timing);
-
-void dp_enable_mst_on_sink(struct dc_link *link, bool enable);
-
-enum dp_panel_mode dp_get_panel_mode(struct dc_link *link);
-void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode);
-
-void dpcd_write_cable_id_to_dprx(struct dc_link *link);
-
-enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready);
-void dp_set_fec_enable(struct dc_link *link, bool enable);
-bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable);
-bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update);
-void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable);
-bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx);
-bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable);
-
-/* Initialize output parameter lt_settings. */
-void dp_decide_training_settings(
-       struct dc_link *link,
-       const struct dc_link_settings *link_setting,
-       struct link_training_settings *lt_settings);
-
-bool dpcd_write_128b_132b_sst_payload_allocation_table(
-               const struct dc_stream_state *stream,
-               struct dc_link *link,
-               struct link_mst_stream_allocation_table *proposed_table,
-               bool allocate);
-
-bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link);
-
-struct fixed31_32 calculate_sst_avg_time_slots_per_mtp(
-               const struct dc_stream_state *stream,
-               const struct dc_link *link);
-void enable_dp_hpo_output(struct dc_link *link,
-               const struct link_resource *link_res,
-               const struct dc_link_settings *link_settings);
-void disable_dp_hpo_output(struct dc_link *link,
-               const struct link_resource *link_res,
-               enum signal_type signal);
-void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable);
-void edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd);
-void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode);
-void edp_add_delay_for_T9(struct dc_link *link);
-bool edp_receiver_ready_T9(struct dc_link *link);
-bool edp_receiver_ready_T7(struct dc_link *link);
-
-void dp_retrain_link_dp_test(struct dc_link *link,
-               struct dc_link_settings *link_setting,
-               bool skip_video_pattern);
-
-#endif /* __DC_LINK_DP_H__ */
index 42db4b7b79fdc4ffaaabefc31abed719d2d31a75..bb5ad70d42662fbe4a87456f1fd57822260ed24b 100644 (file)
@@ -72,6 +72,12 @@ enum dynamic_metadata_mode {
        dmdata_dolby_vision
 };
 
+struct enc_sdp_line_num {
+       /* Adaptive Sync SDP */
+       bool adaptive_sync_line_num_valid;
+       uint32_t adaptive_sync_line_num;
+};
+
 struct encoder_info_frame {
        /* auxiliary video information */
        struct dc_info_packet avi;
@@ -85,6 +91,9 @@ struct encoder_info_frame {
        struct dc_info_packet vsc;
        /* HDR Static MetaData */
        struct dc_info_packet hdrsmd;
+       /* Adaptive Sync SDP*/
+       struct dc_info_packet adaptive_sync;
+       struct enc_sdp_line_num sdp_line_num;
 };
 
 struct encoder_unblank_param {
@@ -154,6 +163,10 @@ struct stream_encoder_funcs {
        void (*stop_hdmi_info_packets)(
                struct stream_encoder *enc);
 
+       void (*update_dp_info_packets_sdp_line_num)(
+               struct stream_encoder *enc,
+               struct encoder_info_frame *info_frame);
+
        void (*update_dp_info_packets)(
                struct stream_encoder *enc,
                const struct encoder_info_frame *info_frame);
@@ -302,6 +315,10 @@ struct hpo_dp_stream_encoder_funcs {
                bool compressed_format,
                bool double_buffer_en);
 
+       void (*update_dp_info_packets_sdp_line_num)(
+               struct hpo_dp_stream_encoder *enc,
+               struct encoder_info_frame *info_frame);
+
        void (*update_dp_info_packets)(
                struct hpo_dp_stream_encoder *enc,
                const struct encoder_info_frame *info_frame);
index 3945522fb798213b68b95b1663349424d8d320e6..d4cebf49e5d440cfe77fce9c4019668dd68ea44c 100644 (file)
@@ -89,4 +89,21 @@ bool link_decide_link_settings(
        struct dc_stream_state *stream,
        struct dc_link_settings *link_setting);
 
+void link_dp_trace_set_edp_power_timestamp(struct dc_link *link,
+               bool power_up);
+uint64_t link_dp_trace_get_edp_poweron_timestamp(struct dc_link *link);
+uint64_t link_dp_trace_get_edp_poweroff_timestamp(struct dc_link *link);
+
+bool link_is_edp_ilr_optimization_required(struct dc_link *link,
+               struct dc_crtc_timing *crtc_timing);
+
+bool link_backlight_enable_aux(struct dc_link *link, bool enable);
+void link_edp_add_delay_for_T9(struct dc_link *link);
+bool link_edp_receiver_ready_T9(struct dc_link *link);
+bool link_edp_receiver_ready_T7(struct dc_link *link);
+bool link_power_alpm_dpcd_enable(struct dc_link *link, bool enable);
+bool link_set_sink_vtotal_in_psr_active(const struct dc_link *link,
+               uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su);
+void link_get_psr_residency(const struct dc_link *link, uint32_t *residency);
+
 #endif /* __DC_LINK_HPD_H__ */
index 4dee0e6248b1df9058be35116a7235f9a88889e9..0f642cbac3d57d44c81945c363fdfea464774387 100644 (file)
 # It abstracts the control and status of back end pipe such as DIO, HPO, DPIA,
 # PHY, HPD, DDC and etc).
 
-LINK = link_hwss_dio.o link_hwss_dpia.o link_hwss_hpo_dp.o link_dp_trace.o \
-link_hpd.o link_ddc.o link_dpcd.o link_dp_dpia.o link_dp_training.o \
-link_dp_training_8b_10b.o link_dp_training_128b_132b.o link_dp_training_dpia.o \
-link_dp_training_auxless.o link_dp_training_fixed_vs_pe_retimer.o link_dp_phy.o \
-link_dp_capability.o
+###############################################################################
+# accessories
+###############################################################################
+LINK_ACCESSORIES = link_dp_trace.o link_dp_cts.o
 
-AMD_DAL_LINK = $(addprefix $(AMDDALPATH)/dc/link/,$(LINK))
+AMD_DAL_LINK_ACCESSORIES = $(addprefix $(AMDDALPATH)/dc/link/accessories/, \
+$(LINK_ACCESSORIES))
 
-AMD_DISPLAY_FILES += $(AMD_DAL_LINK)
+AMD_DISPLAY_FILES += $(AMD_DAL_LINK_ACCESSORIES)
+###############################################################################
+# hwss
+###############################################################################
+LINK_HWSS = link_hwss_dio.o link_hwss_dpia.o link_hwss_hpo_dp.o
+
+AMD_DAL_LINK_HWSS = $(addprefix $(AMDDALPATH)/dc/link/hwss/, \
+$(LINK_HWSS))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_LINK_HWSS)
+###############################################################################
+# protocols
+###############################################################################
+LINK_PROTOCOLS = link_hpd.o link_ddc.o link_dpcd.o link_dp_dpia.o \
+link_dp_training.o link_dp_training_8b_10b.o link_dp_training_128b_132b.o \
+link_dp_training_dpia.o link_dp_training_auxless.o \
+link_dp_training_fixed_vs_pe_retimer.o link_dp_phy.o link_dp_capability.o \
+link_edp_panel_control.o link_dp_irq_handler.o
+
+AMD_DAL_LINK_PROTOCOLS = $(addprefix $(AMDDALPATH)/dc/link/protocols/, \
+$(LINK_PROTOCOLS))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_LINK_PROTOCOLS)
\ No newline at end of file
diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
new file mode 100644 (file)
index 0000000..7fb2c0b
--- /dev/null
@@ -0,0 +1,1055 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "link_dp_cts.h"
+#include "link/protocols/link_dpcd.h"
+#include "link/protocols/link_dp_training.h"
+#include "link/protocols/link_dp_phy.h"
+#include "link/protocols/link_dp_training_fixed_vs_pe_retimer.h"
+#include "resource.h"
+#include "dm_helpers.h"
+#include "dc_dmub_srv.h"
+#include "dce/dmub_hw_lock_mgr.h"
+
+#define DC_LOGGER \
+       link->ctx->logger
+
+static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate)
+{
+       switch (test_rate) {
+       case DP_TEST_LINK_RATE_RBR:
+               return LINK_RATE_LOW;
+       case DP_TEST_LINK_RATE_HBR:
+               return LINK_RATE_HIGH;
+       case DP_TEST_LINK_RATE_HBR2:
+               return LINK_RATE_HIGH2;
+       case DP_TEST_LINK_RATE_HBR3:
+               return LINK_RATE_HIGH3;
+       case DP_TEST_LINK_RATE_UHBR10:
+               return LINK_RATE_UHBR10;
+       case DP_TEST_LINK_RATE_UHBR20:
+               return LINK_RATE_UHBR20;
+       case DP_TEST_LINK_RATE_UHBR13_5:
+               return LINK_RATE_UHBR13_5;
+       default:
+               return LINK_RATE_UNKNOWN;
+       }
+}
+
+static bool is_dp_phy_sqaure_pattern(enum dp_test_pattern test_pattern)
+{
+       return (DP_TEST_PATTERN_SQUARE_BEGIN <= test_pattern &&
+                       test_pattern <= DP_TEST_PATTERN_SQUARE_END);
+}
+
+static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
+{
+       if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern &&
+                       test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) ||
+                       test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
+               return true;
+       else
+               return false;
+}
+
+void dp_retrain_link_dp_test(struct dc_link *link,
+                       struct dc_link_settings *link_setting,
+                       bool skip_video_pattern)
+{
+       struct pipe_ctx *pipe;
+       unsigned int i;
+
+       udelay(100);
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               pipe = &link->dc->current_state->res_ctx.pipe_ctx[i];
+               if (pipe->stream != NULL &&
+                               pipe->stream->link == link &&
+                               !pipe->stream->dpms_off &&
+                               !pipe->top_pipe && !pipe->prev_odm_pipe) {
+                       core_link_disable_stream(pipe);
+                       pipe->link_config.dp_link_settings = *link_setting;
+                       update_dp_encoder_resources_for_test_harness(
+                                       link->dc,
+                                       pipe->stream->ctx->dc->current_state,
+                                       pipe);
+               }
+       }
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               pipe = &link->dc->current_state->res_ctx.pipe_ctx[i];
+               if (pipe->stream != NULL &&
+                               pipe->stream->link == link &&
+                               !pipe->stream->dpms_off &&
+                               !pipe->top_pipe && !pipe->prev_odm_pipe) {
+                       core_link_enable_stream(
+                                       pipe->stream->ctx->dc->current_state,
+                                       pipe);
+               }
+       }
+}
+
+static void dp_test_send_link_training(struct dc_link *link)
+{
+       struct dc_link_settings link_settings = {0};
+       uint8_t test_rate = 0;
+
+       core_link_read_dpcd(
+                       link,
+                       DP_TEST_LANE_COUNT,
+                       (unsigned char *)(&link_settings.lane_count),
+                       1);
+       core_link_read_dpcd(
+                       link,
+                       DP_TEST_LINK_RATE,
+                       &test_rate,
+                       1);
+       link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate);
+
+       /* Set preferred link settings */
+       link->verified_link_cap.lane_count = link_settings.lane_count;
+       link->verified_link_cap.link_rate = link_settings.link_rate;
+
+       dp_retrain_link_dp_test(link, &link_settings, false);
+}
+
+static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
+{
+       union audio_test_mode            dpcd_test_mode = {0};
+       struct audio_test_pattern_type   dpcd_pattern_type = {0};
+       union audio_test_pattern_period  dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
+       enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
+
+       struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
+       struct pipe_ctx *pipe_ctx = &pipes[0];
+       unsigned int channel_count;
+       unsigned int channel = 0;
+       unsigned int modes = 0;
+       unsigned int sampling_rate_in_hz = 0;
+
+       // get audio test mode and test pattern parameters
+       core_link_read_dpcd(
+               link,
+               DP_TEST_AUDIO_MODE,
+               &dpcd_test_mode.raw,
+               sizeof(dpcd_test_mode));
+
+       core_link_read_dpcd(
+               link,
+               DP_TEST_AUDIO_PATTERN_TYPE,
+               &dpcd_pattern_type.value,
+               sizeof(dpcd_pattern_type));
+
+       channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT);
+
+       // read pattern periods for requested channels when sawTooth pattern is requested
+       if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
+                       dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
+
+               test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
+                               DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
+               // read period for each channel
+               for (channel = 0; channel < channel_count; channel++) {
+                       core_link_read_dpcd(
+                                                       link,
+                                                       DP_TEST_AUDIO_PERIOD_CH1 + channel,
+                                                       &dpcd_pattern_period[channel].raw,
+                                                       sizeof(dpcd_pattern_period[channel]));
+               }
+       }
+
+       // translate sampling rate
+       switch (dpcd_test_mode.bits.sampling_rate) {
+       case AUDIO_SAMPLING_RATE_32KHZ:
+               sampling_rate_in_hz = 32000;
+               break;
+       case AUDIO_SAMPLING_RATE_44_1KHZ:
+               sampling_rate_in_hz = 44100;
+               break;
+       case AUDIO_SAMPLING_RATE_48KHZ:
+               sampling_rate_in_hz = 48000;
+               break;
+       case AUDIO_SAMPLING_RATE_88_2KHZ:
+               sampling_rate_in_hz = 88200;
+               break;
+       case AUDIO_SAMPLING_RATE_96KHZ:
+               sampling_rate_in_hz = 96000;
+               break;
+       case AUDIO_SAMPLING_RATE_176_4KHZ:
+               sampling_rate_in_hz = 176400;
+               break;
+       case AUDIO_SAMPLING_RATE_192KHZ:
+               sampling_rate_in_hz = 192000;
+               break;
+       default:
+               sampling_rate_in_hz = 0;
+               break;
+       }
+
+       link->audio_test_data.flags.test_requested = 1;
+       link->audio_test_data.flags.disable_video = disable_video;
+       link->audio_test_data.sampling_rate = sampling_rate_in_hz;
+       link->audio_test_data.channel_count = channel_count;
+       link->audio_test_data.pattern_type = test_pattern;
+
+       if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
+               for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
+                       link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
+               }
+       }
+}
+
+/* TODO Raven hbr2 compliance eye output is unstable
+ * (toggling on and off) with debugger break
+ * This caueses intermittent PHY automation failure
+ * Need to look into the root cause */
+static void dp_test_send_phy_test_pattern(struct dc_link *link)
+{
+       union phy_test_pattern dpcd_test_pattern;
+       union lane_adjust dpcd_lane_adjustment[2];
+       unsigned char dpcd_post_cursor_2_adjustment = 0;
+       unsigned char test_pattern_buffer[
+                       (DP_TEST_264BIT_CUSTOM_PATTERN_263_256 -
+                       DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0};
+       unsigned int test_pattern_size = 0;
+       enum dp_test_pattern test_pattern;
+       union lane_adjust dpcd_lane_adjust;
+       unsigned int lane;
+       struct link_training_settings link_training_settings;
+       unsigned char no_preshoot = 0;
+       unsigned char no_deemphasis = 0;
+
+       dpcd_test_pattern.raw = 0;
+       memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
+       memset(&link_training_settings, 0, sizeof(link_training_settings));
+
+       /* get phy test pattern and pattern parameters from DP receiver */
+       core_link_read_dpcd(
+                       link,
+                       DP_PHY_TEST_PATTERN,
+                       &dpcd_test_pattern.raw,
+                       sizeof(dpcd_test_pattern));
+       core_link_read_dpcd(
+                       link,
+                       DP_ADJUST_REQUEST_LANE0_1,
+                       &dpcd_lane_adjustment[0].raw,
+                       sizeof(dpcd_lane_adjustment));
+
+       /* prepare link training settings */
+       link_training_settings.link_settings = link->cur_link_settings;
+
+       link_training_settings.lttpr_mode = dc_link_decide_lttpr_mode(link, &link->cur_link_settings);
+
+       if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
+                       link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT)
+               dp_fixed_vs_pe_read_lane_adjust(
+                               link,
+                               link_training_settings.dpcd_lane_settings);
+
+       /*get post cursor 2 parameters
+        * For DP 1.1a or eariler, this DPCD register's value is 0
+        * For DP 1.2 or later:
+        * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
+        * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
+        */
+       core_link_read_dpcd(
+                       link,
+                       DP_ADJUST_REQUEST_POST_CURSOR2,
+                       &dpcd_post_cursor_2_adjustment,
+                       sizeof(dpcd_post_cursor_2_adjustment));
+
+       /* translate request */
+       switch (dpcd_test_pattern.bits.PATTERN) {
+       case PHY_TEST_PATTERN_D10_2:
+               test_pattern = DP_TEST_PATTERN_D102;
+               break;
+       case PHY_TEST_PATTERN_SYMBOL_ERROR:
+               test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
+               break;
+       case PHY_TEST_PATTERN_PRBS7:
+               test_pattern = DP_TEST_PATTERN_PRBS7;
+               break;
+       case PHY_TEST_PATTERN_80BIT_CUSTOM:
+               test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
+               break;
+       case PHY_TEST_PATTERN_CP2520_1:
+               /* CP2520 pattern is unstable, temporarily use TPS4 instead */
+               test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
+                               DP_TEST_PATTERN_TRAINING_PATTERN4 :
+                               DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
+               break;
+       case PHY_TEST_PATTERN_CP2520_2:
+               /* CP2520 pattern is unstable, temporarily use TPS4 instead */
+               test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
+                               DP_TEST_PATTERN_TRAINING_PATTERN4 :
+                               DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
+               break;
+       case PHY_TEST_PATTERN_CP2520_3:
+               test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
+               break;
+       case PHY_TEST_PATTERN_128b_132b_TPS1:
+               test_pattern = DP_TEST_PATTERN_128b_132b_TPS1;
+               break;
+       case PHY_TEST_PATTERN_128b_132b_TPS2:
+               test_pattern = DP_TEST_PATTERN_128b_132b_TPS2;
+               break;
+       case PHY_TEST_PATTERN_PRBS9:
+               test_pattern = DP_TEST_PATTERN_PRBS9;
+               break;
+       case PHY_TEST_PATTERN_PRBS11:
+               test_pattern = DP_TEST_PATTERN_PRBS11;
+               break;
+       case PHY_TEST_PATTERN_PRBS15:
+               test_pattern = DP_TEST_PATTERN_PRBS15;
+               break;
+       case PHY_TEST_PATTERN_PRBS23:
+               test_pattern = DP_TEST_PATTERN_PRBS23;
+               break;
+       case PHY_TEST_PATTERN_PRBS31:
+               test_pattern = DP_TEST_PATTERN_PRBS31;
+               break;
+       case PHY_TEST_PATTERN_264BIT_CUSTOM:
+               test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM;
+               break;
+       case PHY_TEST_PATTERN_SQUARE:
+               test_pattern = DP_TEST_PATTERN_SQUARE;
+               break;
+       case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED:
+               test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED;
+               no_preshoot = 1;
+               break;
+       case PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED:
+               test_pattern = DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED;
+               no_deemphasis = 1;
+               break;
+       case PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED:
+               test_pattern = DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED;
+               no_preshoot = 1;
+               no_deemphasis = 1;
+               break;
+       default:
+               test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
+       break;
+       }
+
+       if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
+               test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
+                               DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1;
+               core_link_read_dpcd(
+                               link,
+                               DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
+                               test_pattern_buffer,
+                               test_pattern_size);
+       }
+
+       if (is_dp_phy_sqaure_pattern(test_pattern)) {
+               test_pattern_size = 1; // Square pattern data is 1 byte (DP spec)
+               core_link_read_dpcd(
+                               link,
+                               DP_PHY_SQUARE_PATTERN,
+                               test_pattern_buffer,
+                               test_pattern_size);
+       }
+
+       if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) {
+               test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256-
+                               DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1;
+               core_link_read_dpcd(
+                               link,
+                               DP_TEST_264BIT_CUSTOM_PATTERN_7_0,
+                               test_pattern_buffer,
+                               test_pattern_size);
+       }
+
+       for (lane = 0; lane <
+               (unsigned int)(link->cur_link_settings.lane_count);
+               lane++) {
+               dpcd_lane_adjust.raw =
+                       dp_get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
+               if (link_dp_get_encoding_format(&link->cur_link_settings) ==
+                               DP_8b_10b_ENCODING) {
+                       link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING =
+                               (enum dc_voltage_swing)
+                               (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
+                       link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS =
+                               (enum dc_pre_emphasis)
+                               (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
+                       link_training_settings.hw_lane_settings[lane].POST_CURSOR2 =
+                               (enum dc_post_cursor2)
+                               ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
+               } else if (link_dp_get_encoding_format(&link->cur_link_settings) ==
+                               DP_128b_132b_ENCODING) {
+                       link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.level =
+                                       dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
+                       link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_preshoot = no_preshoot;
+                       link_training_settings.hw_lane_settings[lane].FFE_PRESET.settings.no_deemphasis = no_deemphasis;
+               }
+       }
+
+       dp_hw_to_dpcd_lane_settings(&link_training_settings,
+                       link_training_settings.hw_lane_settings,
+                       link_training_settings.dpcd_lane_settings);
+       /*Usage: Measure DP physical lane signal
+        * by DP SI test equipment automatically.
+        * PHY test pattern request is generated by equipment via HPD interrupt.
+        * HPD needs to be active all the time. HPD should be active
+        * all the time. Do not touch it.
+        * forward request to DS
+        */
+       dc_link_dp_set_test_pattern(
+               link,
+               test_pattern,
+               DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
+               &link_training_settings,
+               test_pattern_buffer,
+               test_pattern_size);
+}
+
+static void set_crtc_test_pattern(struct dc_link *link,
+                               struct pipe_ctx *pipe_ctx,
+                               enum dp_test_pattern test_pattern,
+                               enum dp_test_pattern_color_space test_pattern_color_space)
+{
+       enum controller_dp_test_pattern controller_test_pattern;
+       enum dc_color_depth color_depth = pipe_ctx->
+               stream->timing.display_color_depth;
+       struct bit_depth_reduction_params params;
+       struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
+       int width = pipe_ctx->stream->timing.h_addressable +
+               pipe_ctx->stream->timing.h_border_left +
+               pipe_ctx->stream->timing.h_border_right;
+       int height = pipe_ctx->stream->timing.v_addressable +
+               pipe_ctx->stream->timing.v_border_bottom +
+               pipe_ctx->stream->timing.v_border_top;
+
+       memset(&params, 0, sizeof(params));
+
+       switch (test_pattern) {
+       case DP_TEST_PATTERN_COLOR_SQUARES:
+               controller_test_pattern =
+                               CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
+       break;
+       case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
+               controller_test_pattern =
+                               CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
+       break;
+       case DP_TEST_PATTERN_VERTICAL_BARS:
+               controller_test_pattern =
+                               CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
+       break;
+       case DP_TEST_PATTERN_HORIZONTAL_BARS:
+               controller_test_pattern =
+                               CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
+       break;
+       case DP_TEST_PATTERN_COLOR_RAMP:
+               controller_test_pattern =
+                               CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
+       break;
+       default:
+               controller_test_pattern =
+                               CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
+       break;
+       }
+
+       switch (test_pattern) {
+       case DP_TEST_PATTERN_COLOR_SQUARES:
+       case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
+       case DP_TEST_PATTERN_VERTICAL_BARS:
+       case DP_TEST_PATTERN_HORIZONTAL_BARS:
+       case DP_TEST_PATTERN_COLOR_RAMP:
+       {
+               /* disable bit depth reduction */
+               pipe_ctx->stream->bit_depth_params = params;
+               opp->funcs->opp_program_bit_depth_reduction(opp, &params);
+               if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
+                       pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
+                               controller_test_pattern, color_depth);
+               else if (link->dc->hwss.set_disp_pattern_generator) {
+                       struct pipe_ctx *odm_pipe;
+                       enum controller_dp_color_space controller_color_space;
+                       int opp_cnt = 1;
+                       int offset = 0;
+                       int dpg_width = width;
+
+                       switch (test_pattern_color_space) {
+                       case DP_TEST_PATTERN_COLOR_SPACE_RGB:
+                               controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
+                               break;
+                       case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
+                               controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
+                               break;
+                       case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
+                               controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
+                               break;
+                       case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
+                       default:
+                               controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
+                               DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
+                               ASSERT(0);
+                               break;
+                       }
+
+                       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
+                               opp_cnt++;
+                       dpg_width = width / opp_cnt;
+                       offset = dpg_width;
+
+                       link->dc->hwss.set_disp_pattern_generator(link->dc,
+                                       pipe_ctx,
+                                       controller_test_pattern,
+                                       controller_color_space,
+                                       color_depth,
+                                       NULL,
+                                       dpg_width,
+                                       height,
+                                       0);
+
+                       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+                               struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
+
+                               odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
+                               link->dc->hwss.set_disp_pattern_generator(link->dc,
+                                               odm_pipe,
+                                               controller_test_pattern,
+                                               controller_color_space,
+                                               color_depth,
+                                               NULL,
+                                               dpg_width,
+                                               height,
+                                               offset);
+                               offset += offset;
+                       }
+               }
+       }
+       break;
+       case DP_TEST_PATTERN_VIDEO_MODE:
+       {
+               /* restore bitdepth reduction */
+               resource_build_bit_depth_reduction_params(pipe_ctx->stream, &params);
+               pipe_ctx->stream->bit_depth_params = params;
+               opp->funcs->opp_program_bit_depth_reduction(opp, &params);
+               if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
+                       pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
+                               CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
+                               color_depth);
+               else if (link->dc->hwss.set_disp_pattern_generator) {
+                       struct pipe_ctx *odm_pipe;
+                       int opp_cnt = 1;
+                       int dpg_width;
+
+                       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
+                               opp_cnt++;
+
+                       dpg_width = width / opp_cnt;
+                       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+                               struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
+
+                               odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
+                               link->dc->hwss.set_disp_pattern_generator(link->dc,
+                                               odm_pipe,
+                                               CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
+                                               CONTROLLER_DP_COLOR_SPACE_UDEFINED,
+                                               color_depth,
+                                               NULL,
+                                               dpg_width,
+                                               height,
+                                               0);
+                       }
+                       link->dc->hwss.set_disp_pattern_generator(link->dc,
+                                       pipe_ctx,
+                                       CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
+                                       CONTROLLER_DP_COLOR_SPACE_UDEFINED,
+                                       color_depth,
+                                       NULL,
+                                       dpg_width,
+                                       height,
+                                       0);
+               }
+       }
+       break;
+
+       default:
+       break;
+       }
+}
+
+void dc_link_dp_handle_automated_test(struct dc_link *link)
+{
+       union test_request test_request;
+       union test_response test_response;
+
+       memset(&test_request, 0, sizeof(test_request));
+       memset(&test_response, 0, sizeof(test_response));
+
+       core_link_read_dpcd(
+               link,
+               DP_TEST_REQUEST,
+               &test_request.raw,
+               sizeof(union test_request));
+       if (test_request.bits.LINK_TRAINING) {
+               /* ACK first to let DP RX test box monitor LT sequence */
+               test_response.bits.ACK = 1;
+               core_link_write_dpcd(
+                       link,
+                       DP_TEST_RESPONSE,
+                       &test_response.raw,
+                       sizeof(test_response));
+               dp_test_send_link_training(link);
+               /* no acknowledge request is needed again */
+               test_response.bits.ACK = 0;
+       }
+       if (test_request.bits.LINK_TEST_PATTRN) {
+               union test_misc dpcd_test_params;
+               union link_test_pattern dpcd_test_pattern;
+
+               memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
+               memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
+
+               /* get link test pattern and pattern parameters */
+               core_link_read_dpcd(
+                               link,
+                               DP_TEST_PATTERN,
+                               &dpcd_test_pattern.raw,
+                               sizeof(dpcd_test_pattern));
+               core_link_read_dpcd(
+                               link,
+                               DP_TEST_MISC0,
+                               &dpcd_test_params.raw,
+                               sizeof(dpcd_test_params));
+               test_response.bits.ACK = dm_helpers_dp_handle_test_pattern_request(link->ctx, link,
+                               dpcd_test_pattern, dpcd_test_params) ? 1 : 0;
+       }
+
+       if (test_request.bits.AUDIO_TEST_PATTERN) {
+               dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
+               test_response.bits.ACK = 1;
+       }
+
+       if (test_request.bits.PHY_TEST_PATTERN) {
+               dp_test_send_phy_test_pattern(link);
+               test_response.bits.ACK = 1;
+       }
+
+       /* send request acknowledgment */
+       if (test_response.bits.ACK)
+               core_link_write_dpcd(
+                       link,
+                       DP_TEST_RESPONSE,
+                       &test_response.raw,
+                       sizeof(test_response));
+}
+
+bool dc_link_dp_set_test_pattern(
+       struct dc_link *link,
+       enum dp_test_pattern test_pattern,
+       enum dp_test_pattern_color_space test_pattern_color_space,
+       const struct link_training_settings *p_link_settings,
+       const unsigned char *p_custom_pattern,
+       unsigned int cust_pattern_size)
+{
+       struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
+       struct pipe_ctx *pipe_ctx = NULL;
+       unsigned int lane;
+       unsigned int i;
+       unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
+       union dpcd_training_pattern training_pattern;
+       enum dpcd_phy_test_patterns pattern;
+
+       memset(&training_pattern, 0, sizeof(training_pattern));
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               if (pipes[i].stream == NULL)
+                       continue;
+
+               if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
+                       pipe_ctx = &pipes[i];
+                       break;
+               }
+       }
+
+       if (pipe_ctx == NULL)
+               return false;
+
+       /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
+       if (link->test_pattern_enabled && test_pattern ==
+                       DP_TEST_PATTERN_VIDEO_MODE) {
+               /* Set CRTC Test Pattern */
+               set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
+               dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
+                               (uint8_t *)p_custom_pattern,
+                               (uint32_t)cust_pattern_size);
+
+               /* Unblank Stream */
+               link->dc->hwss.unblank_stream(
+                       pipe_ctx,
+                       &link->verified_link_cap);
+               /* TODO:m_pHwss->MuteAudioEndpoint
+                * (pPathMode->pDisplayPath, false);
+                */
+
+               /* Reset Test Pattern state */
+               link->test_pattern_enabled = false;
+
+               return true;
+       }
+
+       /* Check for PHY Test Patterns */
+       if (is_dp_phy_pattern(test_pattern)) {
+               /* Set DPCD Lane Settings before running test pattern */
+               if (p_link_settings != NULL) {
+                       if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
+                                       p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
+                               dp_fixed_vs_pe_set_retimer_lane_settings(
+                                               link,
+                                               p_link_settings->dpcd_lane_settings,
+                                               p_link_settings->link_settings.lane_count);
+                       } else {
+                               dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX);
+                       }
+                       dpcd_set_lane_settings(link, p_link_settings, DPRX);
+               }
+
+               /* Blank stream if running test pattern */
+               if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
+                       /*TODO:
+                        * m_pHwss->
+                        * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
+                        */
+                       /* Blank stream */
+                       link->dc->hwss.blank_stream(pipe_ctx);
+               }
+
+               dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
+                               (uint8_t *)p_custom_pattern,
+                               (uint32_t)cust_pattern_size);
+
+               if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
+                       /* Set Test Pattern state */
+                       link->test_pattern_enabled = true;
+                       if (p_link_settings != NULL)
+                               dpcd_set_link_settings(link,
+                                               p_link_settings);
+               }
+
+               switch (test_pattern) {
+               case DP_TEST_PATTERN_VIDEO_MODE:
+                       pattern = PHY_TEST_PATTERN_NONE;
+                       break;
+               case DP_TEST_PATTERN_D102:
+                       pattern = PHY_TEST_PATTERN_D10_2;
+                       break;
+               case DP_TEST_PATTERN_SYMBOL_ERROR:
+                       pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
+                       break;
+               case DP_TEST_PATTERN_PRBS7:
+                       pattern = PHY_TEST_PATTERN_PRBS7;
+                       break;
+               case DP_TEST_PATTERN_80BIT_CUSTOM:
+                       pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
+                       break;
+               case DP_TEST_PATTERN_CP2520_1:
+                       pattern = PHY_TEST_PATTERN_CP2520_1;
+                       break;
+               case DP_TEST_PATTERN_CP2520_2:
+                       pattern = PHY_TEST_PATTERN_CP2520_2;
+                       break;
+               case DP_TEST_PATTERN_CP2520_3:
+                       pattern = PHY_TEST_PATTERN_CP2520_3;
+                       break;
+               case DP_TEST_PATTERN_128b_132b_TPS1:
+                       pattern = PHY_TEST_PATTERN_128b_132b_TPS1;
+                       break;
+               case DP_TEST_PATTERN_128b_132b_TPS2:
+                       pattern = PHY_TEST_PATTERN_128b_132b_TPS2;
+                       break;
+               case DP_TEST_PATTERN_PRBS9:
+                       pattern = PHY_TEST_PATTERN_PRBS9;
+                       break;
+               case DP_TEST_PATTERN_PRBS11:
+                       pattern = PHY_TEST_PATTERN_PRBS11;
+                       break;
+               case DP_TEST_PATTERN_PRBS15:
+                       pattern = PHY_TEST_PATTERN_PRBS15;
+                       break;
+               case DP_TEST_PATTERN_PRBS23:
+                       pattern = PHY_TEST_PATTERN_PRBS23;
+                       break;
+               case DP_TEST_PATTERN_PRBS31:
+                       pattern = PHY_TEST_PATTERN_PRBS31;
+                       break;
+               case DP_TEST_PATTERN_264BIT_CUSTOM:
+                       pattern = PHY_TEST_PATTERN_264BIT_CUSTOM;
+                       break;
+               case DP_TEST_PATTERN_SQUARE:
+                       pattern = PHY_TEST_PATTERN_SQUARE;
+                       break;
+               case DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED:
+                       pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED;
+                       break;
+               case DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED:
+                       pattern = PHY_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED;
+                       break;
+               case DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED:
+                       pattern = PHY_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED;
+                       break;
+               default:
+                       return false;
+               }
+
+               if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
+               /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
+                       return false;
+
+               if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
+                       if (is_dp_phy_sqaure_pattern(test_pattern))
+                               core_link_write_dpcd(link,
+                                               DP_LINK_SQUARE_PATTERN,
+                                               p_custom_pattern,
+                                               1);
+
+                       /* tell receiver that we are sending qualification
+                        * pattern DP 1.2 or later - DP receiver's link quality
+                        * pattern is set using DPCD LINK_QUAL_LANEx_SET
+                        * register (0x10B~0x10E)\
+                        */
+                       for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
+                               link_qual_pattern[lane] =
+                                               (unsigned char)(pattern);
+
+                       core_link_write_dpcd(link,
+                                       DP_LINK_QUAL_LANE0_SET,
+                                       link_qual_pattern,
+                                       sizeof(link_qual_pattern));
+               } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
+                          link->dpcd_caps.dpcd_rev.raw == 0) {
+                       /* tell receiver that we are sending qualification
+                        * pattern DP 1.1a or earlier - DP receiver's link
+                        * quality pattern is set using
+                        * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
+                        * register (0x102). We will use v_1.3 when we are
+                        * setting test pattern for DP 1.1.
+                        */
+                       core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
+                                           &training_pattern.raw,
+                                           sizeof(training_pattern));
+                       training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
+                       core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
+                                            &training_pattern.raw,
+                                            sizeof(training_pattern));
+               }
+       } else {
+               enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
+
+               switch (test_pattern_color_space) {
+               case DP_TEST_PATTERN_COLOR_SPACE_RGB:
+                       color_space = COLOR_SPACE_SRGB;
+                       if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
+                               color_space = COLOR_SPACE_SRGB_LIMITED;
+                       break;
+
+               case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
+                       color_space = COLOR_SPACE_YCBCR601;
+                       if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
+                               color_space = COLOR_SPACE_YCBCR601_LIMITED;
+                       break;
+               case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
+                       color_space = COLOR_SPACE_YCBCR709;
+                       if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
+                               color_space = COLOR_SPACE_YCBCR709_LIMITED;
+                       break;
+               default:
+                       break;
+               }
+
+               if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) {
+                       if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
+                               union dmub_hw_lock_flags hw_locks = { 0 };
+                               struct dmub_hw_lock_inst_flags inst_flags = { 0 };
+
+                               hw_locks.bits.lock_dig = 1;
+                               inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
+
+                               dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
+                                                       true,
+                                                       &hw_locks,
+                                                       &inst_flags);
+                       } else
+                               pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable(
+                                               pipe_ctx->stream_res.tg);
+               }
+
+               pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
+               /* update MSA to requested color space */
+               pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(pipe_ctx->stream_res.stream_enc,
+                               &pipe_ctx->stream->timing,
+                               color_space,
+                               pipe_ctx->stream->use_vsc_sdp_for_colorimetry,
+                               link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
+
+               if (pipe_ctx->stream->use_vsc_sdp_for_colorimetry) {
+                       if (test_pattern == DP_TEST_PATTERN_COLOR_SQUARES_CEA)
+                               pipe_ctx->stream->vsc_infopacket.sb[17] |= (1 << 7); // sb17 bit 7 Dynamic Range: 0 = VESA range, 1 = CTA range
+                       else
+                               pipe_ctx->stream->vsc_infopacket.sb[17] &= ~(1 << 7);
+                       resource_build_info_frame(pipe_ctx);
+                       link->dc->hwss.update_info_frame(pipe_ctx);
+               }
+
+               /* CRTC Patterns */
+               set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
+               pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
+               pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
+                               CRTC_STATE_VACTIVE);
+               pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
+                               CRTC_STATE_VBLANK);
+               pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg,
+                               CRTC_STATE_VACTIVE);
+
+               if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable) {
+                       if (pipe_ctx->stream && should_use_dmub_lock(pipe_ctx->stream->link)) {
+                               union dmub_hw_lock_flags hw_locks = { 0 };
+                               struct dmub_hw_lock_inst_flags inst_flags = { 0 };
+
+                               hw_locks.bits.lock_dig = 1;
+                               inst_flags.dig_inst = pipe_ctx->stream_res.tg->inst;
+
+                               dmub_hw_lock_mgr_cmd(link->ctx->dmub_srv,
+                                                       false,
+                                                       &hw_locks,
+                                                       &inst_flags);
+                       } else
+                               pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_disable(
+                                               pipe_ctx->stream_res.tg);
+               }
+
+               /* Set Test Pattern state */
+               link->test_pattern_enabled = true;
+       }
+
+       return true;
+}
+
+void dc_link_set_drive_settings(struct dc *dc,
+                               struct link_training_settings *lt_settings,
+                               const struct dc_link *link)
+{
+
+       int i;
+       struct link_resource link_res;
+
+       for (i = 0; i < dc->link_count; i++)
+               if (dc->links[i] == link)
+                       break;
+
+       if (i >= dc->link_count)
+               ASSERT_CRITICAL(false);
+
+       dc_link_get_cur_link_res(link, &link_res);
+       dp_set_drive_settings(dc->links[i], &link_res, lt_settings);
+}
+
+void dc_link_set_preferred_link_settings(struct dc *dc,
+                                        struct dc_link_settings *link_setting,
+                                        struct dc_link *link)
+{
+       int i;
+       struct pipe_ctx *pipe;
+       struct dc_stream_state *link_stream;
+       struct dc_link_settings store_settings = *link_setting;
+
+       link->preferred_link_setting = store_settings;
+
+       /* Retrain with preferred link settings only relevant for
+        * DP signal type
+        * Check for non-DP signal or if passive dongle present
+        */
+       if (!dc_is_dp_signal(link->connector_signal) ||
+               link->dongle_max_pix_clk > 0)
+               return;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+               if (pipe->stream && pipe->stream->link) {
+                       if (pipe->stream->link == link) {
+                               link_stream = pipe->stream;
+                               break;
+                       }
+               }
+       }
+
+       /* Stream not found */
+       if (i == MAX_PIPES)
+               return;
+
+       /* Cannot retrain link if backend is off */
+       if (link_stream->dpms_off)
+               return;
+
+       if (link_decide_link_settings(link_stream, &store_settings))
+               dp_retrain_link_dp_test(link, &store_settings, false);
+}
+
+void dc_link_set_preferred_training_settings(struct dc *dc,
+                                                struct dc_link_settings *link_setting,
+                                                struct dc_link_training_overrides *lt_overrides,
+                                                struct dc_link *link,
+                                                bool skip_immediate_retrain)
+{
+       if (lt_overrides != NULL)
+               link->preferred_training_settings = *lt_overrides;
+       else
+               memset(&link->preferred_training_settings, 0, sizeof(link->preferred_training_settings));
+
+       if (link_setting != NULL) {
+               link->preferred_link_setting = *link_setting;
+       } else {
+               link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN;
+               link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN;
+       }
+
+       if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
+                       link->type == dc_connection_mst_branch)
+               dm_helpers_dp_mst_update_branch_bandwidth(dc->ctx, link);
+
+       /* Retrain now, or wait until next stream update to apply */
+       if (skip_immediate_retrain == false)
+               dc_link_set_preferred_link_settings(dc, &link->preferred_link_setting, link);
+}
+
+void dc_link_set_test_pattern(struct dc_link *link,
+               enum dp_test_pattern test_pattern,
+               enum dp_test_pattern_color_space test_pattern_color_space,
+               const struct link_training_settings *p_link_settings,
+               const unsigned char *p_custom_pattern,
+               unsigned int cust_pattern_size)
+{
+       if (link != NULL)
+               dc_link_dp_set_test_pattern(
+                       link,
+                       test_pattern,
+                       test_pattern_color_space,
+                       p_link_settings,
+                       p_custom_pattern,
+                       cust_pattern_size);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.h b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.h
new file mode 100644 (file)
index 0000000..7f17838
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __LINK_DP_CTS_H__
+#define __LINK_DP_CTS_H__
+#include "link.h"
+
+void dp_retrain_link_dp_test(struct dc_link *link,
+               struct dc_link_settings *link_setting,
+               bool skip_video_pattern);
+
+#endif /* __LINK_DP_CTS_H__ */
similarity index 95%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_trace.c
rename to drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c
index 2c1a3bfcdb5067630b4a117cf92c8acde05a6de3..04838a31e5139212917b663f787494c8ddb9c669 100644 (file)
@@ -145,7 +145,7 @@ unsigned int dc_dp_trace_get_link_loss_count(struct dc_link *link)
        return link->dp_trace.link_loss_count;
 }
 
-void dp_trace_set_edp_power_timestamp(struct dc_link *link,
+void link_dp_trace_set_edp_power_timestamp(struct dc_link *link,
                bool power_up)
 {
        if (!power_up)
@@ -155,12 +155,12 @@ void dp_trace_set_edp_power_timestamp(struct dc_link *link,
                link->dp_trace.edp_trace_power_timestamps.poweron = dm_get_timestamp(link->dc->ctx);
 }
 
-uint64_t dp_trace_get_edp_poweron_timestamp(struct dc_link *link)
+uint64_t link_dp_trace_get_edp_poweron_timestamp(struct dc_link *link)
 {
        return link->dp_trace.edp_trace_power_timestamps.poweron;
 }
 
-uint64_t dp_trace_get_edp_poweroff_timestamp(struct dc_link *link)
+uint64_t link_dp_trace_get_edp_poweroff_timestamp(struct dc_link *link)
 {
        return link->dp_trace.edp_trace_power_timestamps.poweroff;
-}
\ No newline at end of file
+}
similarity index 91%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_trace.h
rename to drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h
index 26700e3cd65e9c5136bfcd095e1ee2d1371e2e20..702f97c6ead02f026c13e3902988147d1b451e92 100644 (file)
@@ -54,9 +54,4 @@ struct dp_trace_lt_counts *dc_dp_trace_get_lt_counts(struct dc_link *link,
                bool in_detection);
 unsigned int dc_dp_trace_get_link_loss_count(struct dc_link *link);
 
-void dp_trace_set_edp_power_timestamp(struct dc_link *link,
-               bool power_up);
-uint64_t dp_trace_get_edp_poweron_timestamp(struct dc_link *link);
-uint64_t dp_trace_get_edp_poweroff_timestamp(struct dc_link *link);
-
 #endif /* __LINK_DP_TRACE_H__ */
similarity index 99%
rename from drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c
rename to drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
index 33148b753c03b485f887213da6583f088d097b7e..841a23da5dd32ef5aef07f0697d217dccfc661c8 100644 (file)
@@ -24,7 +24,6 @@
  */
 #include "link_hwss_dio.h"
 #include "core_types.h"
-#include "dc_link_dp.h"
 #include "link_enc_cfg.h"
 
 void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx,
similarity index 99%
rename from drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h
rename to drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.h
index 9a108c3d7831563a83d72fb9af96441f3aa60bd5..8b8a099feeb09d81b713b783a4c26c1475e1034e 100644 (file)
@@ -26,6 +26,7 @@
 #define __LINK_HWSS_DIO_H__
 
 #include "link_hwss.h"
+#include "link.h"
 
 const struct link_hwss *get_dio_link_hwss(void);
 bool can_use_dio_link_hwss(const struct dc_link *link,
similarity index 99%
rename from drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c
rename to drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
index 164d631e88099abd931b747a04731878247b4530..d8947f3233f31db78d305a6322e898fa7072c680 100644 (file)
@@ -26,7 +26,6 @@
 #include "dm_helpers.h"
 #include "core_types.h"
 #include "dccg.h"
-#include "dc_link_dp.h"
 #include "clk_mgr.h"
 
 static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link)
similarity index 98%
rename from drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.h
rename to drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.h
index 57d447ec27b87d434be675b4b010a801817ac5a3..3cbb94b41a23163b948ecf9a10654447b468b3da 100644 (file)
@@ -26,6 +26,7 @@
 #define __LINK_HWSS_HPO_DP_H__
 
 #include "link_hwss.h"
+#include "link.h"
 
 bool can_use_hpo_dp_link_hwss(const struct dc_link *link,
                const struct link_resource *link_res);
similarity index 98%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_capability.c
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
index e72ad1b8330f86b6146fcb47aafd6bef0609afd1..138e5684c7fd343126b3f1fd2fdd58d27b76e32b 100644 (file)
 #include "link_dpcd.h"
 #include "link_dp_dpia.h"
 #include "link_dp_phy.h"
-#include "link_dp_trace.h"
+#include "link_edp_panel_control.h"
+#include "link_dp_irq_handler.h"
+#include "link/accessories/link_dp_trace.h"
 #include "link_dp_training.h"
 #include "atomfirmware.h"
 #include "resource.h"
 #include "link_enc_cfg.h"
-#include "dc_link_dp.h"
 #include "dc_dmub_srv.h"
 
 #define DC_LOGGER \
@@ -1462,7 +1463,7 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)
        bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
 
        if (!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support)
-               return DC_ERROR_UNEXPECTED;
+               return DC_NOT_SUPPORTED;
 
        /* By reading LTTPR capability, RX assumes that we will enable
         * LTTPR extended aux timeout if LTTPR is present.
@@ -1645,6 +1646,22 @@ static bool retrieve_link_cap(struct dc_link *link)
 
                if (status != DC_OK)
                        dm_error("%s: Read DPRX caps data failed.\n", __func__);
+
+               /* AdaptiveSyncCapability  */
+               dpcd_dprx_data = 0;
+               for (i = 0; i < read_dpcd_retry_cnt; i++) {
+                       status = core_link_read_dpcd(
+                                       link, DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1,
+                                       &dpcd_dprx_data, sizeof(dpcd_dprx_data));
+                       if (status == DC_OK)
+                               break;
+               }
+
+               link->dpcd_caps.adaptive_sync_caps.dp_adap_sync_caps.raw = dpcd_dprx_data;
+
+               if (status != DC_OK)
+                       dm_error("%s: Read DPRX caps data failed. Addr:%#x\n",
+                                       __func__, DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1);
        }
 
        else {
@@ -1925,7 +1942,7 @@ void detect_edp_sink_caps(struct dc_link *link)
        link->dpcd_caps.set_power_state_capable_edp =
                                (general_edp_cap & DP_EDP_SET_POWER_CAP) ? true:false;
 
-       dc_link_set_default_brightness_aux(link);
+       set_default_brightness_aux(link);
 
        core_link_read_dpcd(link, DP_EDP_DPCD_REV,
                &link->dpcd_caps.edp_rev,
@@ -2110,8 +2127,8 @@ static bool dp_verify_link_cap(
                if (status == LINK_TRAINING_SUCCESS) {
                        success = true;
                        udelay(1000);
-                       if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK &&
-                                       hpd_rx_irq_check_link_loss_status(
+                       if (dp_read_hpd_rx_irq_data(link, &irq_data) == DC_OK &&
+                                       dc_link_check_link_loss_status(
                                                        link,
                                                        &irq_data))
                                (*fail_count)++;
similarity index 85%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_capability.h
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h
index 5500744d2e47bbdf1daf3f0cd744ecc4515397bf..f79e4a4a9db628ccd0454287ee01cd845ae0a5ba 100644 (file)
@@ -46,6 +46,15 @@ bool is_dp_active_dongle(const struct dc_link *link);
 
 bool is_dp_branch_device(const struct dc_link *link);
 
+void dpcd_write_cable_id_to_dprx(struct dc_link *link);
+
+/* Initialize output parameter lt_settings. */
+void dp_decide_training_settings(
+       struct dc_link *link,
+       const struct dc_link_settings *link_setting,
+       struct link_training_settings *lt_settings);
+
+
 bool decide_edp_link_settings_with_dsc(struct dc_link *link,
                struct dc_link_settings *link_setting,
                uint32_t req_bw,
@@ -62,5 +71,9 @@ bool decide_fallback_link_setting(
                struct dc_link_settings *cur,
                enum link_training_result training_result);
 
+bool dp_verify_link_cap_with_retries(
+       struct dc_link *link,
+       struct dc_link_settings *known_limit_link_setting,
+       int attempts);
 
 #endif /* __DC_LINK_DP_CAPABILITY_H__ */
similarity index 99%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_dpia.c
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c
index 6136db392548103f4a389887a53f1c19d8af1fd6..a57a2be2eba0789817d25d5e022cb02e4d334b76 100644 (file)
@@ -27,7 +27,6 @@
 #include "dc.h"
 #include "inc/core_status.h"
 #include "dc_link.h"
-#include "dc_link_dp.h"
 #include "dpcd_defs.h"
 
 #include "link_dp_dpia.h"
@@ -104,4 +103,3 @@ bool dc_link_dpia_query_hpd_status(struct dc_link *link)
 
        return is_hpd_high;
 }
-
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
new file mode 100644 (file)
index 0000000..9a832a9
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/* FILE POLICY AND INTENDED USAGE:
+ *
+ *
+ */
+
+#include "link_dp_irq_handler.h"
+#include "link_dpcd.h"
+#include "link_dp_training.h"
+#include "link_dp_capability.h"
+#include "link/accessories/link_dp_trace.h"
+#include "dm_helpers.h"
+
+#define DC_LOGGER_INIT(logger)
+
+bool dc_link_check_link_loss_status(
+       struct dc_link *link,
+       union hpd_irq_data *hpd_irq_dpcd_data)
+{
+       uint8_t irq_reg_rx_power_state = 0;
+       enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
+       union lane_status lane_status;
+       uint32_t lane;
+       bool sink_status_changed;
+       bool return_code;
+
+       sink_status_changed = false;
+       return_code = false;
+
+       if (link->cur_link_settings.lane_count == 0)
+               return return_code;
+
+       /*1. Check that Link Status changed, before re-training.*/
+
+       /*parse lane status*/
+       for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
+               /* check status of lanes 0,1
+                * changed DpcdAddress_Lane01Status (0x202)
+                */
+               lane_status.raw = dp_get_nibble_at_index(
+                       &hpd_irq_dpcd_data->bytes.lane01_status.raw,
+                       lane);
+
+               if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
+                       !lane_status.bits.CR_DONE_0 ||
+                       !lane_status.bits.SYMBOL_LOCKED_0) {
+                       /* if one of the channel equalization, clock
+                        * recovery or symbol lock is dropped
+                        * consider it as (link has been
+                        * dropped) dp sink status has changed
+                        */
+                       sink_status_changed = true;
+                       break;
+               }
+       }
+
+       /* Check interlane align.*/
+       if (sink_status_changed ||
+               !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
+
+               DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
+
+               return_code = true;
+
+               /*2. Check that we can handle interrupt: Not in FS DOS,
+                *  Not in "Display Timeout" state, Link is trained.
+                */
+               dpcd_result = core_link_read_dpcd(link,
+                       DP_SET_POWER,
+                       &irq_reg_rx_power_state,
+                       sizeof(irq_reg_rx_power_state));
+
+               if (dpcd_result != DC_OK) {
+                       DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",
+                               __func__);
+               } else {
+                       if (irq_reg_rx_power_state != DP_SET_POWER_D0)
+                               return_code = false;
+               }
+       }
+
+       return return_code;
+}
+
+static bool handle_hpd_irq_psr_sink(struct dc_link *link)
+{
+       union dpcd_psr_configuration psr_configuration;
+
+       if (!link->psr_settings.psr_feature_enabled)
+               return false;
+
+       dm_helpers_dp_read_dpcd(
+               link->ctx,
+               link,
+               368,/*DpcdAddress_PSR_Enable_Cfg*/
+               &psr_configuration.raw,
+               sizeof(psr_configuration.raw));
+
+       if (psr_configuration.bits.ENABLE) {
+               unsigned char dpcdbuf[3] = {0};
+               union psr_error_status psr_error_status;
+               union psr_sink_psr_status psr_sink_psr_status;
+
+               dm_helpers_dp_read_dpcd(
+                       link->ctx,
+                       link,
+                       0x2006, /*DpcdAddress_PSR_Error_Status*/
+                       (unsigned char *) dpcdbuf,
+                       sizeof(dpcdbuf));
+
+               /*DPCD 2006h   ERROR STATUS*/
+               psr_error_status.raw = dpcdbuf[0];
+               /*DPCD 2008h   SINK PANEL SELF REFRESH STATUS*/
+               psr_sink_psr_status.raw = dpcdbuf[2];
+
+               if (psr_error_status.bits.LINK_CRC_ERROR ||
+                               psr_error_status.bits.RFB_STORAGE_ERROR ||
+                               psr_error_status.bits.VSC_SDP_ERROR) {
+                       bool allow_active;
+
+                       /* Acknowledge and clear error bits */
+                       dm_helpers_dp_write_dpcd(
+                               link->ctx,
+                               link,
+                               8198,/*DpcdAddress_PSR_Error_Status*/
+                               &psr_error_status.raw,
+                               sizeof(psr_error_status.raw));
+
+                       /* PSR error, disable and re-enable PSR */
+                       if (link->psr_settings.psr_allow_active) {
+                               allow_active = false;
+                               dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
+                               allow_active = true;
+                               dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
+                       }
+
+                       return true;
+               } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
+                               PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){
+                       /* No error is detect, PSR is active.
+                        * We should return with IRQ_HPD handled without
+                        * checking for loss of sync since PSR would have
+                        * powered down main link.
+                        */
+                       return true;
+               }
+       }
+       return false;
+}
+
+void dc_link_dp_handle_link_loss(struct dc_link *link)
+{
+       int i;
+       struct pipe_ctx *pipe_ctx;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
+               if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
+                       break;
+       }
+
+       if (pipe_ctx == NULL || pipe_ctx->stream == NULL)
+               return;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
+               if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
+                               pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
+                       core_link_disable_stream(pipe_ctx);
+       }
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
+               if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off
+                               && pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
+                       // Always use max settings here for DP 1.4a LL Compliance CTS
+                       if (link->is_automated) {
+                               pipe_ctx->link_config.dp_link_settings.lane_count =
+                                               link->verified_link_cap.lane_count;
+                               pipe_ctx->link_config.dp_link_settings.link_rate =
+                                               link->verified_link_cap.link_rate;
+                               pipe_ctx->link_config.dp_link_settings.link_spread =
+                                               link->verified_link_cap.link_spread;
+                       }
+                       core_link_enable_stream(link->dc->current_state, pipe_ctx);
+               }
+       }
+}
+
+enum dc_status dp_read_hpd_rx_irq_data(
+       struct dc_link *link,
+       union hpd_irq_data *irq_data)
+{
+       static enum dc_status retval;
+
+       /* The HW reads 16 bytes from 200h on HPD,
+        * but if we get an AUX_DEFER, the HW cannot retry
+        * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
+        * fail, so we now explicitly read 6 bytes which is
+        * the req from the above mentioned test cases.
+        *
+        * For DP 1.4 we need to read those from 2002h range.
+        */
+       if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14)
+               retval = core_link_read_dpcd(
+                       link,
+                       DP_SINK_COUNT,
+                       irq_data->raw,
+                       sizeof(union hpd_irq_data));
+       else {
+               /* Read 14 bytes in a single read and then copy only the required fields.
+                * This is more efficient than doing it in two separate AUX reads. */
+
+               uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1];
+
+               retval = core_link_read_dpcd(
+                       link,
+                       DP_SINK_COUNT_ESI,
+                       tmp,
+                       sizeof(tmp));
+
+               if (retval != DC_OK)
+                       return retval;
+
+               irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI];
+               irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI];
+               irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI];
+               irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI];
+               irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI];
+               irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI];
+       }
+
+       return retval;
+}
+
+/*************************Short Pulse IRQ***************************/
+bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link)
+{
+       /*
+        * Don't handle RX IRQ unless one of following is met:
+        * 1) The link is established (cur_link_settings != unknown)
+        * 2) We know we're dealing with a branch device, SST or MST
+        */
+
+       if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
+               is_dp_branch_device(link))
+               return true;
+
+       return false;
+}
+
+bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss,
+                                                       bool defer_handling, bool *has_left_work)
+{
+       union hpd_irq_data hpd_irq_dpcd_data = {0};
+       union device_service_irq device_service_clear = {0};
+       enum dc_status result;
+       bool status = false;
+
+       if (out_link_loss)
+               *out_link_loss = false;
+
+       if (has_left_work)
+               *has_left_work = false;
+       /* For use cases related to down stream connection status change,
+        * PSR and device auto test, refer to function handle_sst_hpd_irq
+        * in DAL2.1*/
+
+       DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",
+               __func__, link->link_index);
+
+
+        /* All the "handle_hpd_irq_xxx()" methods
+                * should be called only after
+                * dal_dpsst_ls_read_hpd_irq_data
+                * Order of calls is important too
+                */
+       result = dp_read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
+       if (out_hpd_irq_dpcd_data)
+               *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
+
+       if (result != DC_OK) {
+               DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n",
+                       __func__);
+               return false;
+       }
+
+       if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
+               // Workaround for DP 1.4a LL Compliance CTS as USB4 has to share encoders unlike DP and USBC
+               link->is_automated = true;
+               device_service_clear.bits.AUTOMATED_TEST = 1;
+               core_link_write_dpcd(
+                       link,
+                       DP_DEVICE_SERVICE_IRQ_VECTOR,
+                       &device_service_clear.raw,
+                       sizeof(device_service_clear.raw));
+               device_service_clear.raw = 0;
+               if (defer_handling && has_left_work)
+                       *has_left_work = true;
+               else
+                       dc_link_dp_handle_automated_test(link);
+               return false;
+       }
+
+       if (!dc_link_dp_allow_hpd_rx_irq(link)) {
+               DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",
+                       __func__, link->link_index);
+               return false;
+       }
+
+       if (handle_hpd_irq_psr_sink(link))
+               /* PSR-related error was detected and handled */
+               return true;
+
+       /* If PSR-related error handled, Main link may be off,
+        * so do not handle as a normal sink status change interrupt.
+        */
+
+       if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) {
+               if (defer_handling && has_left_work)
+                       *has_left_work = true;
+               return true;
+       }
+
+       /* check if we have MST msg and return since we poll for it */
+       if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
+               if (defer_handling && has_left_work)
+                       *has_left_work = true;
+               return false;
+       }
+
+       /* For now we only handle 'Downstream port status' case.
+        * If we got sink count changed it means
+        * Downstream port status changed,
+        * then DM should call DC to do the detection.
+        * NOTE: Do not handle link loss on eDP since it is internal link*/
+       if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
+               dc_link_check_link_loss_status(
+                       link,
+                       &hpd_irq_dpcd_data)) {
+               /* Connectivity log: link loss */
+               CONN_DATA_LINK_LOSS(link,
+                                       hpd_irq_dpcd_data.raw,
+                                       sizeof(hpd_irq_dpcd_data),
+                                       "Status: ");
+
+               if (defer_handling && has_left_work)
+                       *has_left_work = true;
+               else
+                       dc_link_dp_handle_link_loss(link);
+
+               status = false;
+               if (out_link_loss)
+                       *out_link_loss = true;
+
+               dp_trace_link_loss_increment(link);
+       }
+
+       if (link->type == dc_connection_sst_branch &&
+               hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
+                       != link->dpcd_sink_count)
+               status = true;
+
+       /* reasons for HPD RX:
+        * 1. Link Loss - ie Re-train the Link
+        * 2. MST sideband message
+        * 3. Automated Test - ie. Internal Commit
+        * 4. CP (copy protection) - (not interesting for DM???)
+        * 5. DRR
+        * 6. Downstream Port status changed
+        * -ie. Detect - this the only one
+        * which is interesting for DM because
+        * it must call dc_link_detect.
+        */
+       return status;
+}
+
similarity index 80%
rename from drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.h
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.h
index ea8d9760132fd790eee26b6bdaa2399e75dcff59..cac7acd33511d849be022ccd3e840ebc0e3b736e 100644 (file)
  * Authors: AMD
  *
  */
-#ifndef __LINK_HWSS_HPO_FRL_H__
-#define __LINK_HWSS_HPO_FRL_H__
 
-#include "link_hwss.h"
+#ifndef __DC_LINK_DP_IRQ_HANDLER_H__
+#define __DC_LINK_DP_IRQ_HANDLER_H__
 
-bool can_use_hpo_frl_link_hwss(const struct dc_link *link,
-               const struct link_resource *link_res);
-const struct link_hwss *get_hpo_frl_link_hwss(void);
+#include "link.h"
 
-#endif /* __LINK_HWSS_HPO_FRL_H__ */
+enum dc_status dp_read_hpd_rx_irq_data(
+       struct dc_link *link,
+       union hpd_irq_data *irq_data);
+
+#endif /* __DC_LINK_DP_IRQ_HANDLER_H__ */
similarity index 98%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_phy.c
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
index afe3b21335c27232c8955a2a0570d44f2836c5fb..5e531620926fef130b2e818cc78d4823d7d6d667 100644 (file)
 #include "link_dp_capability.h"
 #include "clk_mgr.h"
 #include "resource.h"
-#include "dc_link_dp.h"
 
 #define DC_LOGGER \
        link->ctx->logger
 
-void dc_link_dp_set_drive_settings(
-       struct dc_link *link,
-       const struct link_resource *link_res,
-       struct link_training_settings *lt_settings)
-{
-       /* program ASIC PHY settings*/
-       dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
-
-       dp_hw_to_dpcd_lane_settings(lt_settings,
-                       lt_settings->hw_lane_settings,
-                       lt_settings->dpcd_lane_settings);
-
-       /* Notify DP sink the PHY settings from source */
-       dpcd_set_lane_settings(link, lt_settings, DPRX);
-}
-
 void dc_link_dp_receiver_power_ctrl(struct dc_link *link, bool on)
 {
        uint8_t state;
@@ -143,3 +126,19 @@ void dp_set_hw_lane_settings(
                        link_settings->hw_lane_settings,
                        sizeof(link->cur_lane_setting));
 }
+
+void dp_set_drive_settings(
+       struct dc_link *link,
+       const struct link_resource *link_res,
+       struct link_training_settings *lt_settings)
+{
+       /* program ASIC PHY settings*/
+       dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
+
+       dp_hw_to_dpcd_lane_settings(lt_settings,
+                       lt_settings->hw_lane_settings,
+                       lt_settings->dpcd_lane_settings);
+
+       /* Notify DP sink the PHY settings from source */
+       dpcd_set_lane_settings(link, lt_settings, DPRX);
+}
similarity index 93%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_phy.h
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h
index 717e078fd564b598b4c1bfe5eb8664bdf1bea942..850da64c90058b8979685937e95deffa95c153ac 100644 (file)
@@ -48,4 +48,9 @@ void dp_set_hw_lane_settings(
                const struct link_training_settings *link_settings,
                uint32_t offset);
 
+void dp_set_drive_settings(
+       struct dc_link *link,
+       const struct link_resource *link_res,
+       struct link_training_settings *lt_settings);
+
 #endif /* __DC_LINK_DP_PHY_H__ */
similarity index 99%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_training.c
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
index e49e0258a1bdc98a5da08b3a1b5f2dbdf2b195ea..18ec09b5a8ba47c6f9ab475941cd3f8c7ad6983f 100644 (file)
 #include "link_dp_training_dpia.h"
 #include "link_dp_training_fixed_vs_pe_retimer.h"
 #include "link_dpcd.h"
-#include "link_dp_trace.h"
+#include "link/accessories/link_dp_trace.h"
 #include "link_dp_phy.h"
 #include "link_dp_capability.h"
-#include "dc_link_dp.h"
+#include "link_edp_panel_control.h"
 #include "atomfirmware.h"
 #include "link_enc_cfg.h"
 #include "resource.h"
@@ -239,7 +239,7 @@ enum dpcd_training_patterns
        return dpcd_tr_pattern;
 }
 
-static uint8_t get_nibble_at_index(const uint8_t *buf,
+uint8_t dp_get_nibble_at_index(const uint8_t *buf,
        uint32_t index)
 {
        uint8_t nibble;
@@ -519,7 +519,7 @@ enum link_training_result dp_check_link_loss_status(
                /*
                 * check lanes status
                 */
-               lane_status.raw = get_nibble_at_index(&dpcd_buf[2], lane);
+               lane_status.raw = dp_get_nibble_at_index(&dpcd_buf[2], lane);
 
                if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
                        !lane_status.bits.CR_DONE_0 ||
@@ -578,9 +578,9 @@ enum dc_status dp_get_lane_status_and_lane_adjust(
                lane++) {
 
                ln_status[lane].raw =
-                       get_nibble_at_index(&dpcd_buf[0], lane);
+                       dp_get_nibble_at_index(&dpcd_buf[0], lane);
                ln_adjust[lane].raw =
-                       get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
+                       dp_get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
        }
 
        ln_align->raw = dpcd_buf[2];
@@ -1389,7 +1389,7 @@ static bool perform_post_lt_adj_req_sequence(
                                dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
                                                lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
 
-                               dc_link_dp_set_drive_settings(link,
+                               dp_set_drive_settings(link,
                                                link_res,
                                                lt_settings);
                                break;
similarity index 98%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_training.h
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.h
index 376d370e3bbbe755b25b228db7f60f8d440e35f6..a04948635369f639cad6190a6e3f9ff9a451ec3f 100644 (file)
@@ -176,4 +176,7 @@ void dp_log_training_result(
 
 uint32_t dp_translate_training_aux_read_interval(
                uint32_t dpcd_aux_read_interval);
+
+uint8_t dp_get_nibble_at_index(const uint8_t *buf,
+       uint32_t index);
 #endif /* __DC_LINK_DP_TRAINING_H__ */
similarity index 99%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_training_128b_132b.c
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c
index bfabebed58689ea3af227cab92b31c2bf06e6f78..23d380f09a21c8a0371e31207d475e59035e2de0 100644 (file)
@@ -32,7 +32,6 @@
 #include "link_dpcd.h"
 #include "link_dp_phy.h"
 #include "link_dp_capability.h"
-#include "dc_link_dp.h"
 
 #define DC_LOGGER \
        link->ctx->logger
similarity index 99%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_training_8b_10b.c
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c
index ec8b619d51c5e8ae520c3acef4416b784a54218f..14b98e096d392691c51885461928d9cfe713dcf3 100644 (file)
@@ -31,7 +31,6 @@
 #include "link_dpcd.h"
 #include "link_dp_phy.h"
 #include "link_dp_capability.h"
-#include "dc_link_dp.h"
 
 #define DC_LOGGER \
        link->ctx->logger
similarity index 99%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_training_auxless.c
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_auxless.c
index f84b6ea53e8b44e5c7c7ba02cc1aeef2e0831507..e50ec5012559bd4d07ec3dc204e182d7e52aa9d6 100644 (file)
@@ -28,7 +28,6 @@
  */
 #include "link_dp_training_auxless.h"
 #include "link_dp_phy.h"
-#include "dc_link_dp.h"
 #define DC_LOGGER \
        link->ctx->logger
 bool dc_link_dp_perform_link_training_skip_aux(
similarity index 99%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_training_dpia.c
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
index cf47db1c21410c9044d81b91ab8c7bca7428de82..05657627ae45ea9b2851e6d93809ae569e4e7bbb 100644 (file)
@@ -30,7 +30,6 @@
 #include "dc.h"
 #include "inc/core_status.h"
 #include "dc_link.h"
-#include "dc_link_dp.h"
 #include "dpcd_defs.h"
 
 #include "link_dp_dpia.h"
similarity index 99%
rename from drivers/gpu/drm/amd/display/dc/link/link_dp_training_fixed_vs_pe_retimer.c
rename to drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c
index 860b5eea89aa965609825374217ef7d9456297b2..a4071d2959a03303d67b0f4b700d4817e76bf75b 100644 (file)
@@ -36,7 +36,6 @@
 #include "link_dpcd.h"
 #include "link_dp_phy.h"
 #include "link_dp_capability.h"
-#include "dc_link_dp.h"
 
 #define DC_LOGGER \
        link->ctx->logger
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
new file mode 100644 (file)
index 0000000..97e02b5
--- /dev/null
@@ -0,0 +1,833 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/* FILE POLICY AND INTENDED USAGE:
+ * This file implements retrieval and configuration of eDP panel features such
+ * as PSR and ABM and it also manages specs defined eDP panel power sequences.
+ */
+
+#include "link_edp_panel_control.h"
+#include "link_dpcd.h"
+#include "link_dp_capability.h"
+#include "dm_helpers.h"
+#include "dal_asic_id.h"
+#include "dce/dmub_psr.h"
+#include "abm.h"
+#define DC_LOGGER_INIT(logger)
+
+void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode)
+{
+       union dpcd_edp_config edp_config_set;
+       bool panel_mode_edp = false;
+
+       memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
+
+       if (panel_mode != DP_PANEL_MODE_DEFAULT) {
+
+               switch (panel_mode) {
+               case DP_PANEL_MODE_EDP:
+               case DP_PANEL_MODE_SPECIAL:
+                       panel_mode_edp = true;
+                       break;
+
+               default:
+                               break;
+               }
+
+               /*set edp panel mode in receiver*/
+               core_link_read_dpcd(
+                       link,
+                       DP_EDP_CONFIGURATION_SET,
+                       &edp_config_set.raw,
+                       sizeof(edp_config_set.raw));
+
+               if (edp_config_set.bits.PANEL_MODE_EDP
+                       != panel_mode_edp) {
+                       enum dc_status result;
+
+                       edp_config_set.bits.PANEL_MODE_EDP =
+                       panel_mode_edp;
+                       result = core_link_write_dpcd(
+                               link,
+                               DP_EDP_CONFIGURATION_SET,
+                               &edp_config_set.raw,
+                               sizeof(edp_config_set.raw));
+
+                       ASSERT(result == DC_OK);
+               }
+       }
+       DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
+                "eDP panel mode enabled: %d \n",
+                link->link_index,
+                link->dpcd_caps.panel_mode_edp,
+                panel_mode_edp);
+}
+
+enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
+{
+       /* We need to explicitly check that connector
+        * is not DP. Some Travis_VGA get reported
+        * by video bios as DP.
+        */
+       if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
+
+               switch (link->dpcd_caps.branch_dev_id) {
+               case DP_BRANCH_DEVICE_ID_0022B9:
+                       /* alternate scrambler reset is required for Travis
+                        * for the case when external chip does not
+                        * provide sink device id, alternate scrambler
+                        * scheme will  be overriden later by querying
+                        * Encoder features
+                        */
+                       if (strncmp(
+                               link->dpcd_caps.branch_dev_name,
+                               DP_VGA_LVDS_CONVERTER_ID_2,
+                               sizeof(
+                               link->dpcd_caps.
+                               branch_dev_name)) == 0) {
+                                       return DP_PANEL_MODE_SPECIAL;
+                       }
+                       break;
+               case DP_BRANCH_DEVICE_ID_00001A:
+                       /* alternate scrambler reset is required for Travis
+                        * for the case when external chip does not provide
+                        * sink device id, alternate scrambler scheme will
+                        * be overriden later by querying Encoder feature
+                        */
+                       if (strncmp(link->dpcd_caps.branch_dev_name,
+                               DP_VGA_LVDS_CONVERTER_ID_3,
+                               sizeof(
+                               link->dpcd_caps.
+                               branch_dev_name)) == 0) {
+                                       return DP_PANEL_MODE_SPECIAL;
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (link->dpcd_caps.panel_mode_edp &&
+               (link->connector_signal == SIGNAL_TYPE_EDP ||
+                (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
+                 link->is_internal_display))) {
+               return DP_PANEL_MODE_EDP;
+       }
+
+       return DP_PANEL_MODE_DEFAULT;
+}
+
+bool dc_link_set_backlight_level_nits(struct dc_link *link,
+               bool isHDR,
+               uint32_t backlight_millinits,
+               uint32_t transition_time_in_ms)
+{
+       struct dpcd_source_backlight_set dpcd_backlight_set;
+       uint8_t backlight_control = isHDR ? 1 : 0;
+
+       if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
+                       link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
+               return false;
+
+       // OLEDs have no PWM, they can only use AUX
+       if (link->dpcd_sink_ext_caps.bits.oled == 1)
+               backlight_control = 1;
+
+       *(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits;
+       *(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms;
+
+
+       if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
+                       (uint8_t *)(&dpcd_backlight_set),
+                       sizeof(dpcd_backlight_set)) != DC_OK)
+               return false;
+
+       if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL,
+                       &backlight_control, 1) != DC_OK)
+               return false;
+
+       return true;
+}
+
+bool dc_link_get_backlight_level_nits(struct dc_link *link,
+               uint32_t *backlight_millinits_avg,
+               uint32_t *backlight_millinits_peak)
+{
+       union dpcd_source_backlight_get dpcd_backlight_get;
+
+       memset(&dpcd_backlight_get, 0, sizeof(union dpcd_source_backlight_get));
+
+       if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
+                       link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
+               return false;
+
+       if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK,
+                       dpcd_backlight_get.raw,
+                       sizeof(union dpcd_source_backlight_get)))
+               return false;
+
+       *backlight_millinits_avg =
+               dpcd_backlight_get.bytes.backlight_millinits_avg;
+       *backlight_millinits_peak =
+               dpcd_backlight_get.bytes.backlight_millinits_peak;
+
+       /* On non-supported panels dpcd_read usually succeeds with 0 returned */
+       if (*backlight_millinits_avg == 0 ||
+                       *backlight_millinits_avg > *backlight_millinits_peak)
+               return false;
+
+       return true;
+}
+
+bool link_backlight_enable_aux(struct dc_link *link, bool enable)
+{
+       uint8_t backlight_enable = enable ? 1 : 0;
+
+       if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
+               link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
+               return false;
+
+       if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
+               &backlight_enable, 1) != DC_OK)
+               return false;
+
+       return true;
+}
+
+// we read default from 0x320 because we expect BIOS wrote it there
+// regular get_backlight_nit reads from panel set at 0x326
+static bool read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits)
+{
+       if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
+               link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
+               return false;
+
+       if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
+               (uint8_t *) backlight_millinits,
+               sizeof(uint32_t)))
+               return false;
+
+       return true;
+}
+
+bool set_default_brightness_aux(struct dc_link *link)
+{
+       uint32_t default_backlight;
+
+       if (link && link->dpcd_sink_ext_caps.bits.oled == 1) {
+               if (!read_default_bl_aux(link, &default_backlight))
+                       default_backlight = 150000;
+               // if < 5 nits or > 5000, it might be wrong readback
+               if (default_backlight < 5000 || default_backlight > 5000000)
+                       default_backlight = 150000; //
+
+               return dc_link_set_backlight_level_nits(link, true,
+                               default_backlight, 0);
+       }
+       return false;
+}
+
+bool link_is_edp_ilr_optimization_required(struct dc_link *link,
+               struct dc_crtc_timing *crtc_timing)
+{
+       struct dc_link_settings link_setting;
+       uint8_t link_bw_set;
+       uint8_t link_rate_set;
+       uint32_t req_bw;
+       union lane_count_set lane_count_set = {0};
+
+       ASSERT(link || crtc_timing); // invalid input
+
+       if (link->dpcd_caps.edp_supported_link_rates_count == 0 ||
+                       !link->panel_config.ilr.optimize_edp_link_rate)
+               return false;
+
+
+       // Read DPCD 00100h to find if standard link rates are set
+       core_link_read_dpcd(link, DP_LINK_BW_SET,
+                               &link_bw_set, sizeof(link_bw_set));
+
+       if (link_bw_set) {
+               DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS used link_bw_set\n");
+               return true;
+       }
+
+       // Read DPCD 00115h to find the edp link rate set used
+       core_link_read_dpcd(link, DP_LINK_RATE_SET,
+                           &link_rate_set, sizeof(link_rate_set));
+
+       // Read DPCD 00101h to find out the number of lanes currently set
+       core_link_read_dpcd(link, DP_LANE_COUNT_SET,
+                               &lane_count_set.raw, sizeof(lane_count_set));
+
+       req_bw = dc_bandwidth_in_kbps_from_timing(crtc_timing);
+
+       if (!crtc_timing->flags.DSC)
+               dc_link_decide_edp_link_settings(link, &link_setting, req_bw);
+       else
+               decide_edp_link_settings_with_dsc(link, &link_setting, req_bw, LINK_RATE_UNKNOWN);
+
+       if (link->dpcd_caps.edp_supported_link_rates[link_rate_set] != link_setting.link_rate ||
+                       lane_count_set.bits.LANE_COUNT_SET != link_setting.lane_count) {
+               DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS link_rate_set not optimal\n");
+               return true;
+       }
+
+       DC_LOG_EVENT_LINK_TRAINING("eDP ILR: No optimization required, VBIOS set optimal link_rate_set\n");
+       return false;
+}
+
+void dc_link_edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd)
+{
+       if (link->connector_signal != SIGNAL_TYPE_EDP)
+               return;
+
+       link->dc->hwss.edp_power_control(link, true);
+       if (wait_for_hpd)
+               link->dc->hwss.edp_wait_for_hpd_ready(link, true);
+       if (link->dc->hwss.edp_backlight_control)
+               link->dc->hwss.edp_backlight_control(link, true);
+}
+
+bool dc_link_wait_for_t12(struct dc_link *link)
+{
+       if (link->connector_signal == SIGNAL_TYPE_EDP && link->dc->hwss.edp_wait_for_T12) {
+               link->dc->hwss.edp_wait_for_T12(link);
+
+               return true;
+       }
+
+       return false;
+}
+
+void link_edp_add_delay_for_T9(struct dc_link *link)
+{
+       if (link && link->panel_config.pps.extra_delay_backlight_off > 0)
+               udelay(link->panel_config.pps.extra_delay_backlight_off * 1000);
+}
+
+bool link_edp_receiver_ready_T9(struct dc_link *link)
+{
+       unsigned int tries = 0;
+       unsigned char sinkstatus = 0;
+       unsigned char edpRev = 0;
+       enum dc_status result = DC_OK;
+
+       result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
+
+       /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
+       if (result == DC_OK && edpRev >= DP_EDP_12) {
+               do {
+                       sinkstatus = 1;
+                       result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
+                       if (sinkstatus == 0)
+                               break;
+                       if (result != DC_OK)
+                               break;
+                       udelay(100); //MAx T9
+               } while (++tries < 50);
+       }
+
+       return result;
+}
+
+bool link_edp_receiver_ready_T7(struct dc_link *link)
+{
+       unsigned char sinkstatus = 0;
+       unsigned char edpRev = 0;
+       enum dc_status result = DC_OK;
+
+       /* use absolute time stamp to constrain max T7*/
+       unsigned long long enter_timestamp = 0;
+       unsigned long long finish_timestamp = 0;
+       unsigned long long time_taken_in_ns = 0;
+
+       result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
+
+       if (result == DC_OK && edpRev >= DP_EDP_12) {
+               /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
+               enter_timestamp = dm_get_timestamp(link->ctx);
+               do {
+                       sinkstatus = 0;
+                       result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
+                       if (sinkstatus == 1)
+                               break;
+                       if (result != DC_OK)
+                               break;
+                       udelay(25);
+                       finish_timestamp = dm_get_timestamp(link->ctx);
+                       time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp);
+               } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms
+       }
+
+       if (link && link->panel_config.pps.extra_t7_ms > 0)
+               udelay(link->panel_config.pps.extra_t7_ms * 1000);
+
+       return result;
+}
+
+bool link_power_alpm_dpcd_enable(struct dc_link *link, bool enable)
+{
+       bool ret = false;
+       union dpcd_alpm_configuration alpm_config;
+
+       if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
+               memset(&alpm_config, 0, sizeof(alpm_config));
+
+               alpm_config.bits.ENABLE = (enable ? true : false);
+               ret = dm_helpers_dp_write_dpcd(link->ctx, link,
+                               DP_RECEIVER_ALPM_CONFIG, &alpm_config.raw,
+                               sizeof(alpm_config.raw));
+       }
+       return ret;
+}
+
+static struct pipe_ctx *get_pipe_from_link(const struct dc_link *link)
+{
+       int i;
+       struct dc *dc = link->ctx->dc;
+       struct pipe_ctx *pipe_ctx = NULL;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               if (dc->current_state->res_ctx.pipe_ctx[i].stream) {
+                       if (dc->current_state->res_ctx.pipe_ctx[i].stream->link == link) {
+                               pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
+                               break;
+                       }
+               }
+       }
+
+       return pipe_ctx;
+}
+
+bool dc_link_set_backlight_level(const struct dc_link *link,
+               uint32_t backlight_pwm_u16_16,
+               uint32_t frame_ramp)
+{
+       struct dc  *dc = link->ctx->dc;
+
+       DC_LOGGER_INIT(link->ctx->logger);
+       DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
+                       backlight_pwm_u16_16, backlight_pwm_u16_16);
+
+       if (dc_is_embedded_signal(link->connector_signal)) {
+               struct pipe_ctx *pipe_ctx = get_pipe_from_link(link);
+
+               if (pipe_ctx) {
+                       /* Disable brightness ramping when the display is blanked
+                        * as it can hang the DMCU
+                        */
+                       if (pipe_ctx->plane_state == NULL)
+                               frame_ramp = 0;
+               } else {
+                       return false;
+               }
+
+               dc->hwss.set_backlight_level(
+                               pipe_ctx,
+                               backlight_pwm_u16_16,
+                               frame_ramp);
+       }
+       return true;
+}
+
+bool dc_link_set_psr_allow_active(struct dc_link *link, const bool *allow_active,
+               bool wait, bool force_static, const unsigned int *power_opts)
+{
+       struct dc  *dc = link->ctx->dc;
+       struct dmcu *dmcu = dc->res_pool->dmcu;
+       struct dmub_psr *psr = dc->res_pool->psr;
+       unsigned int panel_inst;
+
+       if (psr == NULL && force_static)
+               return false;
+
+       if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
+               return false;
+
+       if ((allow_active != NULL) && (*allow_active == true) && (link->type == dc_connection_none)) {
+               // Don't enter PSR if panel is not connected
+               return false;
+       }
+
+       /* Set power optimization flag */
+       if (power_opts && link->psr_settings.psr_power_opt != *power_opts) {
+               link->psr_settings.psr_power_opt = *power_opts;
+
+               if (psr != NULL && link->psr_settings.psr_feature_enabled && psr->funcs->psr_set_power_opt)
+                       psr->funcs->psr_set_power_opt(psr, link->psr_settings.psr_power_opt, panel_inst);
+       }
+
+       if (psr != NULL && link->psr_settings.psr_feature_enabled &&
+                       force_static && psr->funcs->psr_force_static)
+               psr->funcs->psr_force_static(psr, panel_inst);
+
+       /* Enable or Disable PSR */
+       if (allow_active && link->psr_settings.psr_allow_active != *allow_active) {
+               link->psr_settings.psr_allow_active = *allow_active;
+
+               if (!link->psr_settings.psr_allow_active)
+                       dc_z10_restore(dc);
+
+               if (psr != NULL && link->psr_settings.psr_feature_enabled) {
+                       psr->funcs->psr_enable(psr, link->psr_settings.psr_allow_active, wait, panel_inst);
+               } else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) &&
+                       link->psr_settings.psr_feature_enabled)
+                       dmcu->funcs->set_psr_enable(dmcu, link->psr_settings.psr_allow_active, wait);
+               else
+                       return false;
+       }
+       return true;
+}
+
+bool dc_link_get_psr_state(const struct dc_link *link, enum dc_psr_state *state)
+{
+       struct dc  *dc = link->ctx->dc;
+       struct dmcu *dmcu = dc->res_pool->dmcu;
+       struct dmub_psr *psr = dc->res_pool->psr;
+       unsigned int panel_inst;
+
+       if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
+               return false;
+
+       if (psr != NULL && link->psr_settings.psr_feature_enabled)
+               psr->funcs->psr_get_state(psr, state, panel_inst);
+       else if (dmcu != NULL && link->psr_settings.psr_feature_enabled)
+               dmcu->funcs->get_psr_state(dmcu, state);
+
+       return true;
+}
+
+static inline enum physical_phy_id
+transmitter_to_phy_id(struct dc_link *link)
+{
+       struct dc_context *dc_ctx = link->ctx;
+       enum transmitter transmitter_value = link->link_enc->transmitter;
+
+       switch (transmitter_value) {
+       case TRANSMITTER_UNIPHY_A:
+               return PHYLD_0;
+       case TRANSMITTER_UNIPHY_B:
+               return PHYLD_1;
+       case TRANSMITTER_UNIPHY_C:
+               return PHYLD_2;
+       case TRANSMITTER_UNIPHY_D:
+               return PHYLD_3;
+       case TRANSMITTER_UNIPHY_E:
+               return PHYLD_4;
+       case TRANSMITTER_UNIPHY_F:
+               return PHYLD_5;
+       case TRANSMITTER_NUTMEG_CRT:
+               return PHYLD_6;
+       case TRANSMITTER_TRAVIS_CRT:
+               return PHYLD_7;
+       case TRANSMITTER_TRAVIS_LCD:
+               return PHYLD_8;
+       case TRANSMITTER_UNIPHY_G:
+               return PHYLD_9;
+       case TRANSMITTER_COUNT:
+               return PHYLD_COUNT;
+       case TRANSMITTER_UNKNOWN:
+               return PHYLD_UNKNOWN;
+       default:
+               DC_ERROR("Unknown transmitter value %d\n", transmitter_value);
+               return PHYLD_UNKNOWN;
+       }
+}
+
+bool dc_link_setup_psr(struct dc_link *link,
+               const struct dc_stream_state *stream, struct psr_config *psr_config,
+               struct psr_context *psr_context)
+{
+       struct dc *dc;
+       struct dmcu *dmcu;
+       struct dmub_psr *psr;
+       int i;
+       unsigned int panel_inst;
+       /* updateSinkPsrDpcdConfig*/
+       union dpcd_psr_configuration psr_configuration;
+       union dpcd_sink_active_vtotal_control_mode vtotal_control = {0};
+
+       psr_context->controllerId = CONTROLLER_ID_UNDEFINED;
+
+       if (!link)
+               return false;
+
+       dc = link->ctx->dc;
+       dmcu = dc->res_pool->dmcu;
+       psr = dc->res_pool->psr;
+
+       if (!dmcu && !psr)
+               return false;
+
+       if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
+               return false;
+
+
+       memset(&psr_configuration, 0, sizeof(psr_configuration));
+
+       psr_configuration.bits.ENABLE                    = 1;
+       psr_configuration.bits.CRC_VERIFICATION          = 1;
+       psr_configuration.bits.FRAME_CAPTURE_INDICATION  =
+                       psr_config->psr_frame_capture_indication_req;
+
+       /* Check for PSR v2*/
+       if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
+               /* For PSR v2 selective update.
+                * Indicates whether sink should start capturing
+                * immediately following active scan line,
+                * or starting with the 2nd active scan line.
+                */
+               psr_configuration.bits.LINE_CAPTURE_INDICATION = 0;
+               /*For PSR v2, determines whether Sink should generate
+                * IRQ_HPD when CRC mismatch is detected.
+                */
+               psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR    = 1;
+               /* For PSR v2, set the bit when the Source device will
+                * be enabling PSR2 operation.
+                */
+               psr_configuration.bits.ENABLE_PSR2    = 1;
+               /* For PSR v2, the Sink device must be able to receive
+                * SU region updates early in the frame time.
+                */
+               psr_configuration.bits.EARLY_TRANSPORT_ENABLE    = 1;
+       }
+
+       dm_helpers_dp_write_dpcd(
+               link->ctx,
+               link,
+               368,
+               &psr_configuration.raw,
+               sizeof(psr_configuration.raw));
+
+       if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
+               link_power_alpm_dpcd_enable(link, true);
+               psr_context->su_granularity_required =
+                       psr_config->su_granularity_required;
+               psr_context->su_y_granularity =
+                       psr_config->su_y_granularity;
+               psr_context->line_time_in_us = psr_config->line_time_in_us;
+
+               /* linux must be able to expose AMD Source DPCD definition
+                * in order to support FreeSync PSR
+                */
+               if (link->psr_settings.psr_vtotal_control_support) {
+                       psr_context->rate_control_caps = psr_config->rate_control_caps;
+                       vtotal_control.bits.ENABLE = true;
+                       core_link_write_dpcd(link, DP_SINK_PSR_ACTIVE_VTOTAL_CONTROL_MODE,
+                                                       &vtotal_control.raw, sizeof(vtotal_control.raw));
+               }
+       }
+
+       psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel;
+       psr_context->transmitterId = link->link_enc->transmitter;
+       psr_context->engineId = link->link_enc->preferred_engine;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               if (dc->current_state->res_ctx.pipe_ctx[i].stream
+                               == stream) {
+                       /* dmcu -1 for all controller id values,
+                        * therefore +1 here
+                        */
+                       psr_context->controllerId =
+                               dc->current_state->res_ctx.
+                               pipe_ctx[i].stream_res.tg->inst + 1;
+                       break;
+               }
+       }
+
+       /* Hardcoded for now.  Can be Pcie or Uniphy (or Unknown)*/
+       psr_context->phyType = PHY_TYPE_UNIPHY;
+       /*PhyId is associated with the transmitter id*/
+       psr_context->smuPhyId = transmitter_to_phy_id(link);
+
+       psr_context->crtcTimingVerticalTotal = stream->timing.v_total;
+       psr_context->vsync_rate_hz = div64_u64(div64_u64((stream->
+                                       timing.pix_clk_100hz * 100),
+                                       stream->timing.v_total),
+                                       stream->timing.h_total);
+
+       psr_context->psrSupportedDisplayConfig = true;
+       psr_context->psrExitLinkTrainingRequired =
+               psr_config->psr_exit_link_training_required;
+       psr_context->sdpTransmitLineNumDeadline =
+               psr_config->psr_sdp_transmit_line_num_deadline;
+       psr_context->psrFrameCaptureIndicationReq =
+               psr_config->psr_frame_capture_indication_req;
+
+       psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */
+
+       psr_context->numberOfControllers =
+                       link->dc->res_pool->timing_generator_count;
+
+       psr_context->rfb_update_auto_en = true;
+
+       /* 2 frames before enter PSR. */
+       psr_context->timehyst_frames = 2;
+       /* half a frame
+        * (units in 100 lines, i.e. a value of 1 represents 100 lines)
+        */
+       psr_context->hyst_lines = stream->timing.v_total / 2 / 100;
+       psr_context->aux_repeats = 10;
+
+       psr_context->psr_level.u32all = 0;
+
+       /*skip power down the single pipe since it blocks the cstate*/
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+       if (link->ctx->asic_id.chip_family >= FAMILY_RV) {
+               switch (link->ctx->asic_id.chip_family) {
+               case FAMILY_YELLOW_CARP:
+               case AMDGPU_FAMILY_GC_10_3_6:
+               case AMDGPU_FAMILY_GC_11_0_1:
+                       if (dc->debug.disable_z10 || dc->debug.psr_skip_crtc_disable)
+                               psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
+                       break;
+               default:
+                       psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
+                       break;
+               }
+       }
+#else
+       if (link->ctx->asic_id.chip_family >= FAMILY_RV)
+               psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
+#endif
+
+       /* SMU will perform additional powerdown sequence.
+        * For unsupported ASICs, set psr_level flag to skip PSR
+        *  static screen notification to SMU.
+        *  (Always set for DAL2, did not check ASIC)
+        */
+       psr_context->allow_smu_optimizations = psr_config->allow_smu_optimizations;
+       psr_context->allow_multi_disp_optimizations = psr_config->allow_multi_disp_optimizations;
+
+       /* Complete PSR entry before aborting to prevent intermittent
+        * freezes on certain eDPs
+        */
+       psr_context->psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1;
+
+       /* Disable ALPM first for compatible non-ALPM panel now */
+       psr_context->psr_level.bits.DISABLE_ALPM = 0;
+       psr_context->psr_level.bits.ALPM_DEFAULT_PD_MODE = 1;
+
+       /* Controls additional delay after remote frame capture before
+        * continuing power down, default = 0
+        */
+       psr_context->frame_delay = 0;
+
+       psr_context->dsc_slice_height = psr_config->dsc_slice_height;
+
+       if (psr) {
+               link->psr_settings.psr_feature_enabled = psr->funcs->psr_copy_settings(psr,
+                       link, psr_context, panel_inst);
+               link->psr_settings.psr_power_opt = 0;
+               link->psr_settings.psr_allow_active = 0;
+       } else {
+               link->psr_settings.psr_feature_enabled = dmcu->funcs->setup_psr(dmcu, link, psr_context);
+       }
+
+       /* psr_enabled == 0 indicates setup_psr did not succeed, but this
+        * should not happen since firmware should be running at this point
+        */
+       if (link->psr_settings.psr_feature_enabled == 0)
+               ASSERT(0);
+
+       return true;
+
+}
+
+void link_get_psr_residency(const struct dc_link *link, uint32_t *residency)
+{
+       struct dc  *dc = link->ctx->dc;
+       struct dmub_psr *psr = dc->res_pool->psr;
+       unsigned int panel_inst;
+
+       if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
+               return;
+
+       // PSR residency measurements only supported on DMCUB
+       if (psr != NULL && link->psr_settings.psr_feature_enabled)
+               psr->funcs->psr_get_residency(psr, residency, panel_inst);
+       else
+               *residency = 0;
+}
+bool link_set_sink_vtotal_in_psr_active(const struct dc_link *link, uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su)
+{
+       struct dc *dc = link->ctx->dc;
+       struct dmub_psr *psr = dc->res_pool->psr;
+
+       if (psr == NULL || !link->psr_settings.psr_feature_enabled || !link->psr_settings.psr_vtotal_control_support)
+               return false;
+
+       psr->funcs->psr_set_sink_vtotal_in_psr_active(psr, psr_vtotal_idle, psr_vtotal_su);
+
+       return true;
+}
+
+static struct abm *get_abm_from_stream_res(const struct dc_link *link)
+{
+       int i;
+       struct dc *dc = link->ctx->dc;
+       struct abm *abm = NULL;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               struct pipe_ctx pipe_ctx = dc->current_state->res_ctx.pipe_ctx[i];
+               struct dc_stream_state *stream = pipe_ctx.stream;
+
+               if (stream && stream->link == link) {
+                       abm = pipe_ctx.stream_res.abm;
+                       break;
+               }
+       }
+       return abm;
+}
+
+int dc_link_get_backlight_level(const struct dc_link *link)
+{
+       struct abm *abm = get_abm_from_stream_res(link);
+       struct panel_cntl *panel_cntl = link->panel_cntl;
+       struct dc  *dc = link->ctx->dc;
+       struct dmcu *dmcu = dc->res_pool->dmcu;
+       bool fw_set_brightness = true;
+
+       if (dmcu)
+               fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
+
+       if (!fw_set_brightness && panel_cntl->funcs->get_current_backlight)
+               return panel_cntl->funcs->get_current_backlight(panel_cntl);
+       else if (abm != NULL && abm->funcs->get_current_backlight != NULL)
+               return (int) abm->funcs->get_current_backlight(abm);
+       else
+               return DC_ERROR_UNEXPECTED;
+}
+
+int dc_link_get_target_backlight_pwm(const struct dc_link *link)
+{
+       struct abm *abm = get_abm_from_stream_res(link);
+
+       if (abm == NULL || abm->funcs->get_target_backlight == NULL)
+               return DC_ERROR_UNEXPECTED;
+
+       return (int) abm->funcs->get_target_backlight(abm);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
new file mode 100644 (file)
index 0000000..7f91a56
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_LINK_EDP_PANEL_CONTROL_H__
+#define __DC_LINK_EDP_PANEL_CONTROL_H__
+#include "link.h"
+
+enum dp_panel_mode dp_get_panel_mode(struct dc_link *link);
+void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode);
+bool set_default_brightness_aux(struct dc_link *link);
+#endif /* __DC_LINK_EDP_POWER_CONTROL_H__ */
index 06c553b6132212816fd32e800bef6aeed9812a1e..04df407092b1ed42bb5e199c9f9c23f92ced7608 100644 (file)
@@ -1968,6 +1968,14 @@ struct dmub_cmd_psr_copy_settings_data {
         * Explicit padding to 2 byte boundary.
         */
        uint8_t pad3;
+       /**
+        * DSC Slice height.
+        */
+       uint16_t dsc_slice_height;
+       /**
+        * Explicit padding to 4 byte boundary.
+        */
+       uint16_t pad;
 };
 
 /**
@@ -3112,7 +3120,7 @@ struct dmub_rb_cmd_panel_cntl {
 struct dmub_cmd_lvtma_control_data {
        uint8_t uc_pwr_action; /**< LVTMA_ACTION */
        uint8_t bypass_panel_control_wait;
-       uint8_t reserved_0[2];
+       uint8_t reserved_0[2]; /**< For future use */
        uint8_t panel_inst; /**< LVTMA control instance */
        uint8_t reserved_1[3]; /**< For future use */
 };
index edf5845f6a1f77082ac3dc62b00265d2f49f89bb..91fe039c0c95981109a0651909f3221f7da0ea90 100644 (file)
@@ -41,4 +41,40 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
 void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
                struct dc_info_packet *info_packet);
 
+enum adaptive_sync_type {
+       ADAPTIVE_SYNC_TYPE_NONE                  = 0,
+       ADAPTIVE_SYNC_TYPE_DP                    = 1,
+       ADAPTIVE_SYNC_TYPE_PCON_IN_WHITELIST     = 2,
+       ADAPTIVE_SYNC_TYPE_PCON_NOT_IN_WHITELIST = 3,
+       ADAPTIVE_SYNC_TYPE_EDP                   = 4,
+};
+
+enum adaptive_sync_sdp_version {
+       AS_SDP_VER_0 = 0x0,
+       AS_SDP_VER_1 = 0x1,
+       AS_SDP_VER_2 = 0x2,
+};
+
+#define AS_DP_SDP_LENGTH (9)
+
+struct frame_duration_op {
+       bool          support;
+       unsigned char frame_duration_hex;
+};
+
+struct AS_Df_params {
+       bool   supportMode;
+       struct frame_duration_op increase;
+       struct frame_duration_op decrease;
+};
+
+void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream,
+               enum adaptive_sync_type asType, const struct AS_Df_params *param,
+               struct dc_info_packet *info_packet);
+
+void mod_build_adaptive_sync_infopacket_v2(const struct dc_stream_state *stream,
+               const struct AS_Df_params *param, struct dc_info_packet *info_packet);
+
+void mod_build_adaptive_sync_infopacket_v1(struct dc_info_packet *info_packet);
+
 #endif
index 69691058ab89817c6d7edf50fc47c49cd9fcbcbd..a8a31d0a7a7fec66a29fcac9b5e45625af357655 100644 (file)
@@ -519,3 +519,58 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
                info_packet->valid = true;
 }
 
+void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream,
+               enum adaptive_sync_type asType,
+               const struct AS_Df_params *param,
+               struct dc_info_packet *info_packet)
+{
+       info_packet->valid = false;
+
+       memset(info_packet, 0, sizeof(struct dc_info_packet));
+
+       switch (asType) {
+       case ADAPTIVE_SYNC_TYPE_DP:
+               if (stream != NULL)
+                       mod_build_adaptive_sync_infopacket_v2(stream, param, info_packet);
+               break;
+       case ADAPTIVE_SYNC_TYPE_PCON_IN_WHITELIST:
+               mod_build_adaptive_sync_infopacket_v1(info_packet);
+               break;
+       case ADAPTIVE_SYNC_TYPE_NONE:
+       case ADAPTIVE_SYNC_TYPE_PCON_NOT_IN_WHITELIST:
+       default:
+               break;
+       }
+}
+
+void mod_build_adaptive_sync_infopacket_v1(struct dc_info_packet *info_packet)
+{
+       info_packet->valid = true;
+       // HEADER {HB0, HB1, HB2, HB3} = {00, Type, Version, Length}
+       info_packet->hb0 = 0x00;
+       info_packet->hb1 = 0x22;
+       info_packet->hb2 = AS_SDP_VER_1;
+       info_packet->hb3 = 0x00;
+}
+
+void mod_build_adaptive_sync_infopacket_v2(const struct dc_stream_state *stream,
+               const struct AS_Df_params *param,
+               struct dc_info_packet *info_packet)
+{
+       info_packet->valid = true;
+       // HEADER {HB0, HB1, HB2, HB3} = {00, Type, Version, Length}
+       info_packet->hb0 = 0x00;
+       info_packet->hb1 = 0x22;
+       info_packet->hb2 = AS_SDP_VER_2;
+       info_packet->hb3 = AS_DP_SDP_LENGTH;
+
+       //Payload
+       info_packet->sb[0] = param->supportMode; //1: AVT; 0: FAVT
+       info_packet->sb[1] = (stream->timing.v_total & 0x00FF);
+       info_packet->sb[2] = (stream->timing.v_total & 0xFF00) >> 8;
+       //info_packet->sb[3] = 0x00; Target RR, not use fot AVT
+       info_packet->sb[4] = (param->increase.support << 6 | param->decrease.support << 7);
+       info_packet->sb[5] = param->increase.frame_duration_hex;
+       info_packet->sb[6] = param->decrease.frame_duration_hex;
+}
+
index cf4fa87c7db60a1b1c4e61eea8a144b9035239ba..e39b133d05af4e47f17c8993080160726c8ab3f6 100644 (file)
@@ -917,13 +917,14 @@ bool mod_power_only_edp(const struct dc_state *context, const struct dc_stream_s
        return context && context->stream_count == 1 && dc_is_embedded_signal(stream->signal);
 }
 
-bool psr_su_set_y_granularity(struct dc *dc, struct dc_link *link,
+bool psr_su_set_dsc_slice_height(struct dc *dc, struct dc_link *link,
                              struct dc_stream_state *stream,
                              struct psr_config *config)
 {
        uint16_t pic_height;
-       uint8_t slice_height;
+       uint16_t slice_height;
 
+       config->dsc_slice_height = 0;
        if ((link->connector_signal & SIGNAL_TYPE_EDP) &&
            (!dc->caps.edp_dsc_support ||
            link->panel_config.dsc.disable_dsc_edp ||
@@ -934,6 +935,7 @@ bool psr_su_set_y_granularity(struct dc *dc, struct dc_link *link,
        pic_height = stream->timing.v_addressable +
                stream->timing.v_border_top + stream->timing.v_border_bottom;
        slice_height = pic_height / stream->timing.dsc_cfg.num_slices_v;
+       config->dsc_slice_height = slice_height;
 
        if (slice_height) {
                if (config->su_y_granularity &&
@@ -941,8 +943,6 @@ bool psr_su_set_y_granularity(struct dc *dc, struct dc_link *link,
                        ASSERT(0);
                        return false;
                }
-
-               config->su_y_granularity = slice_height;
        }
 
        return true;
index bb16b37b83da75fced224d041436b2a618dfc028..1d3079e56799f3daf4c9d119873a036d52f93e13 100644 (file)
@@ -59,7 +59,7 @@ void mod_power_calc_psr_configs(struct psr_config *psr_config,
                const struct dc_stream_state *stream);
 bool mod_power_only_edp(const struct dc_state *context,
                const struct dc_stream_state *stream);
-bool psr_su_set_y_granularity(struct dc *dc, struct dc_link *link,
+bool psr_su_set_dsc_slice_height(struct dc *dc, struct dc_link *link,
                              struct dc_stream_state *stream,
                              struct psr_config *config);
 #endif /* MODULES_POWER_POWER_HELPERS_H_ */
index d0cdc578344d8d2af25c0bc1b10de275a8d2d9ed..f89ce6575b15c45564f1ba4a535856f733bdd564 100644 (file)
@@ -145,6 +145,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] =
        MSG_MAP(SetBadMemoryPagesRetiredFlagsPerChannel,
                            PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel,   0),
        MSG_MAP(AllowGpo,                       PPSMC_MSG_SetGpoAllow,           0),
+       MSG_MAP(AllowIHHostInterrupt,           PPSMC_MSG_AllowIHHostInterrupt,       0),
 };
 
 static struct cmn2asic_mapping smu_v13_0_0_clk_map[SMU_CLK_COUNT] = {
index 5861b0a6247bc1bb10d5ae4dda45f27f537750d8..847c10aa2098ceb279dfae8b61e87281a102d14a 100644 (file)
@@ -3377,6 +3377,9 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 
        mgr->payload_count--;
        mgr->next_start_slot -= payload->time_slots;
+
+       if (payload->delete)
+               drm_dp_mst_put_port_malloc(payload->port);
 }
 EXPORT_SYMBOL(drm_dp_remove_payload);
 
@@ -4335,7 +4338,6 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state,
 
        drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, payload->time_slots);
        if (!payload->delete) {
-               drm_dp_mst_put_port_malloc(port);
                payload->pbn = 0;
                payload->delete = true;
                topology_state->payload_mask &= ~BIT(payload->vcpi - 1);
index c3753da97c4ece3823d422b3c905dc9b8f08c0e8..a93a387f8a1a15b17fe2826e4b09017189394e02 100644 (file)
@@ -521,7 +521,7 @@ __printf(1, 2)
 void __drm_err(const char *format, ...);
 
 #if !defined(CONFIG_DRM_USE_DYNAMIC_DEBUG)
-#define __drm_dbg(fmt, ...)            ___drm_dbg(NULL, fmt, ##__VA_ARGS__)
+#define __drm_dbg(cat, fmt, ...)               ___drm_dbg(NULL, cat, fmt, ##__VA_ARGS__)
 #else
 #define __drm_dbg(cat, fmt, ...)                                       \
        _dynamic_func_call_cls(cat, fmt, ___drm_dbg,                    \