[PATCH 09/24] drm/amd/display: Add Synaptics Fifo Reset Workaround
Rodrigo Siqueira
Rodrigo.Siqueira at amd.com
Sun Jan 23 18:20:06 UTC 2022
From: Fangzhi Zuo <Jerry.Zuo at amd.com>
Sequence to reset synaptics SDP fifo before enabling first stream
Reviewed-by: Hersen Wu <hersenxs.wu at amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira at amd.com>
Signed-off-by: Fangzhi Zuo <Jerry.Zuo at 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
More information about the amd-gfx
mailing list