From: Fangzhi Zuo <jerry....@amd.com>

Sequence to reset synaptics SDP fifo before enabling first stream

Reviewed-by: Hersen Wu <hersenxs...@amd.com>
Acked-by: Rodrigo Siqueira <rodrigo.sique...@amd.com>
Signed-off-by: Fangzhi Zuo <jerry....@amd.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 133 ++++++++++++++++++
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |   2 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  10 ++
 3 files changed, 144 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index d757bdd9f0e2..b760c0b199d5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -536,6 +536,139 @@ bool dm_helpers_submit_i2c(
 
        return result;
 }
+
+static bool execute_synatpics_rc_command(struct drm_dp_aux *aux,
+               bool is_write_cmd,
+               unsigned char cmd,
+               unsigned int length,
+               unsigned int offset,
+               unsigned char *data)
+{
+       bool success = false;
+       unsigned char rc_data[16] = {0};
+       unsigned char rc_offset[4] = {0};
+       unsigned char rc_length[2] = {0};
+       unsigned char rc_cmd = 0;
+       unsigned char rc_result = 0xFF;
+       unsigned char i = 0;
+       uint8_t ret = 0;
+
+       if (is_write_cmd) {
+               // write rc data
+               memmove(rc_data, data, length);
+               ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_DATA, rc_data, 
sizeof(rc_data));
+       }
+
+       // write rc offset
+       rc_offset[0] = (unsigned char) offset & 0xFF;
+       rc_offset[1] = (unsigned char) (offset >> 8) & 0xFF;
+       rc_offset[2] = (unsigned char) (offset >> 16) & 0xFF;
+       rc_offset[3] = (unsigned char) (offset >> 24) & 0xFF;
+       ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_OFFSET, rc_offset, 
sizeof(rc_offset));
+
+       // write rc length
+       rc_length[0] = (unsigned char) length & 0xFF;
+       rc_length[1] = (unsigned char) (length >> 8) & 0xFF;
+       ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_LENGTH, rc_length, 
sizeof(rc_length));
+
+       // write rc cmd
+       rc_cmd = cmd | 0x80;
+       ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_COMMAND, &rc_cmd, 
sizeof(rc_cmd));
+
+       if (ret < 0) {
+               DRM_ERROR("     execute_synatpics_rc_command - write cmd ..., 
err = %d\n", ret);
+               return false;
+       }
+
+       // poll until active is 0
+       for (i = 0; i < 10; i++) {
+               drm_dp_dpcd_read(aux, SYNAPTICS_RC_COMMAND, &rc_cmd, 
sizeof(rc_cmd));
+               if (rc_cmd == cmd)
+                       // active is 0
+                       break;
+               msleep(10);
+       }
+
+       // read rc result
+       drm_dp_dpcd_read(aux, SYNAPTICS_RC_RESULT, &rc_result, 
sizeof(rc_result));
+       success = (rc_result == 0);
+
+       if (success && !is_write_cmd) {
+               // read rc data
+               drm_dp_dpcd_read(aux, SYNAPTICS_RC_DATA, data, length);
+       }
+
+       DC_LOG_DC("     execute_synatpics_rc_command - success = %d\n", 
success);
+
+       return success;
+}
+
+static void apply_synaptics_fifo_reset_wa(struct drm_dp_aux *aux)
+{
+       unsigned char data[16] = {0};
+
+       DC_LOG_DC("Start apply_synaptics_fifo_reset_wa\n");
+
+       // Step 2
+       data[0] = 'P';
+       data[1] = 'R';
+       data[2] = 'I';
+       data[3] = 'U';
+       data[4] = 'S';
+
+       if (!execute_synatpics_rc_command(aux, true, 0x01, 5, 0, data))
+               return;
+
+       // Step 3 and 4
+       if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x220998, data))
+               return;
+
+       data[0] &= (~(1 << 1)); // set bit 1 to 0
+       if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x220998, data))
+               return;
+
+       if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x220D98, data))
+               return;
+
+       data[0] &= (~(1 << 1)); // set bit 1 to 0
+       if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x220D98, data))
+               return;
+
+       if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x221198, data))
+               return;
+
+       data[0] &= (~(1 << 1)); // set bit 1 to 0
+       if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x221198, data))
+               return;
+
+       // Step 3 and 5
+       if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x220998, data))
+               return;
+
+       data[0] |= (1 << 1); // set bit 1 to 1
+       if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x220998, data))
+               return;
+
+       if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x220D98, data))
+               return;
+
+       data[0] |= (1 << 1); // set bit 1 to 1
+               return;
+
+       if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x221198, data))
+               return;
+
+       data[0] |= (1 << 1); // set bit 1 to 1
+       if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x221198, data))
+               return;
+
+       // Step 6
+       if (!execute_synatpics_rc_command(aux, true, 0x02, 0, 0, NULL))
+               return;
+
+       DC_LOG_DC("Done apply_synaptics_fifo_reset_wa\n");
+}
+
 bool dm_helpers_dp_write_dsc_enable(
                struct dc_context *ctx,
                const struct dc_stream_state *stream,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index cc34a35d0bcb..23cc6a6fe70e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -159,7 +159,7 @@ static const struct drm_connector_funcs 
dm_dp_mst_connector_funcs = {
 };
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-static bool needs_dsc_aux_workaround(struct dc_link *link)
+bool needs_dsc_aux_workaround(struct dc_link *link)
 {
        if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 &&
            (link->dpcd_caps.dpcd_rev.raw == DPCD_REV_14 || 
link->dpcd_caps.dpcd_rev.raw == DPCD_REV_12) &&
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
index 900d3f7a8498..5da28ca03372 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -26,6 +26,14 @@
 #ifndef __DAL_AMDGPU_DM_MST_TYPES_H__
 #define __DAL_AMDGPU_DM_MST_TYPES_H__
 
+#define DP_BRANCH_DEVICE_ID_90CC24 0x90CC24
+
+#define SYNAPTICS_RC_COMMAND       0x4B2
+#define SYNAPTICS_RC_RESULT        0x4B3
+#define SYNAPTICS_RC_LENGTH        0x4B8
+#define SYNAPTICS_RC_OFFSET        0x4BC
+#define SYNAPTICS_RC_DATA          0x4C0
+
 struct amdgpu_display_manager;
 struct amdgpu_dm_connector;
 
@@ -50,6 +58,8 @@ struct dsc_mst_fairness_vars {
 bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
                                       struct dc_state *dc_state,
                                       struct dsc_mst_fairness_vars *vars);
+
+bool needs_dsc_aux_workaround(struct dc_link *link);
 #endif
 
 #endif
-- 
2.25.1

Reply via email to