OSDN Git Service

drm/amd/display: Add Synaptics Fifo Reset Workaround
authorFangzhi Zuo <Jerry.Zuo@amd.com>
Sun, 23 Jan 2022 18:20:06 +0000 (13:20 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 25 Jan 2022 23:00:35 +0000 (18:00 -0500)
Sequence to reset synaptics SDP fifo before enabling first stream

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
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_mst_types.h

index 575840c..8554c93 100644 (file)
@@ -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,
index cc34a35..23cc6a6 100644 (file)
@@ -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) &&
index 900d3f7..5da28ca 100644 (file)
 #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