diff options
author | Dave Airlie <airlied@redhat.com> | 2022-02-14 10:31:51 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2022-02-14 10:31:51 +1000 |
commit | 123db17ddff007080d464e785689fb14f94cbc7a (patch) | |
tree | 11da22fd6a508e496be838e43e0b504266c4a4d3 /drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | |
parent | e7a09cea6483b44ea0c82f07145fcbd8a918bf96 (diff) | |
parent | 7f161df1a513e2961f4e3c96a8355c8ce93ad175 (diff) | |
download | linux-123db17ddff007080d464e785689fb14f94cbc7a.tar.bz2 |
Merge tag 'amd-drm-next-5.18-2022-02-11-1' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-5.18-2022-02-11-1:
amdgpu:
- Clean up of power management code
- Enable freesync video mode by default
- Clean up of RAS code
- Improve VRAM access for debug using SDMA
- Coding style cleanups
- SR-IOV fixes
- More display FP reorg
- TLB flush fixes for Arcuturus, Vega20
- Misc display fixes
- Rework special register access methods for SR-IOV
- DP2 fixes
- DP tunneling fixes
- DSC fixes
- More IP discovery cleanups
- Misc RAS fixes
- Enable both SMU i2c buses where applicable
- s2idle improvements
- DPCS header cleanup
- Add new CAP firmware support for SR-IOV
amdkfd:
- Misc cleanups
- SVM fixes
- CRIU support
- Clean up MQD manager
UAPI:
- Add interface to amdgpu CTX ioctl to request a stable power state for profiling
https://gitlab.freedesktop.org/mesa/drm/-/merge_requests/207
- Add amdkfd support for CRIU
https://github.com/checkpoint-restore/criu/pull/1709
- Remove old unused amdkfd debugger interface
Was only implemented for Kaveri and was only ever used by an old HSA tool that was never open sourced
radeon:
- Fix error handling in radeon_driver_open_kms
- UVD suspend fix
- Misc fixes
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220211220706.5803-1-alexander.deucher@amd.com
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 219 |
1 files changed, 186 insertions, 33 deletions
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 29f07c26d080..db4ab01267e4 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 @@ -39,6 +39,7 @@ #include "amdgpu_dm_mst_types.h" #include "dm_helpers.h" +#include "ddc_service_types.h" struct monitor_patch_info { unsigned int manufacturer_id; @@ -445,40 +446,24 @@ bool dm_helpers_dp_mst_start_top_mgr( return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0); } -void dm_helpers_dp_mst_stop_top_mgr( +bool dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, struct dc_link *link) { struct amdgpu_dm_connector *aconnector = link->priv; - uint8_t i; if (!aconnector) { DRM_ERROR("Failed to find connector for link!"); - return; + return false; } DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n", aconnector, aconnector->base.base.id); - if (aconnector->mst_mgr.mst_state == true) { + if (aconnector->mst_mgr.mst_state == true) drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, false); - for (i = 0; i < MAX_SINKS_PER_LINK; i++) { - if (link->remote_sinks[i] == NULL) - continue; - - if (link->remote_sinks[i]->sink_signal == - SIGNAL_TYPE_DISPLAY_PORT_MST) { - dc_link_remove_remote_sink(link, link->remote_sinks[i]); - - if (aconnector->dc_sink) { - dc_sink_release(aconnector->dc_sink); - aconnector->dc_sink = NULL; - aconnector->dc_link->cur_link_settings.lane_count = 0; - } - } - } - } + return false; } bool dm_helpers_dp_read_dpcd( @@ -552,6 +537,177 @@ bool dm_helpers_submit_i2c( return result; } + +#if defined(CONFIG_DRM_AMD_DC_DCN) +static bool execute_synaptics_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_synaptics_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_synaptics_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_synaptics_rc_command(aux, true, 0x01, 5, 0, data)) + return; + + // Step 3 and 4 + if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220998, data)) + return; + + data[0] &= (~(1 << 1)); // set bit 1 to 0 + if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x220998, data)) + return; + + if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220D98, data)) + return; + + data[0] &= (~(1 << 1)); // set bit 1 to 0 + if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x220D98, data)) + return; + + if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x221198, data)) + return; + + data[0] &= (~(1 << 1)); // set bit 1 to 0 + if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x221198, data)) + return; + + // Step 3 and 5 + if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220998, data)) + return; + + data[0] |= (1 << 1); // set bit 1 to 1 + if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x220998, data)) + return; + + if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220D98, data)) + return; + + data[0] |= (1 << 1); // set bit 1 to 1 + return; + + if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x221198, data)) + return; + + data[0] |= (1 << 1); // set bit 1 to 1 + if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x221198, data)) + return; + + // Step 6 + if (!execute_synaptics_rc_command(aux, true, 0x02, 0, 0, NULL)) + return; + + DC_LOG_DC("Done apply_synaptics_fifo_reset_wa\n"); +} + +static uint8_t write_dsc_enable_synaptics_non_virtual_dpcd_mst( + struct drm_dp_aux *aux, + const struct dc_stream_state *stream, + bool enable) +{ + uint8_t ret = 0; + + DC_LOG_DC("Configure DSC to non-virtual dpcd synaptics\n"); + + if (enable) { + /* When DSC is enabled on previous boot and reboot with the hub, + * there is a chance that Synaptics hub gets stuck during reboot sequence. + * Applying a workaround to reset Synaptics SDP fifo before enabling the first stream + */ + if (!stream->link->link_status.link_active && + memcmp(stream->link->dpcd_caps.branch_dev_name, + (int8_t *)SYNAPTICS_DEVICE_ID, 4) == 0) + apply_synaptics_fifo_reset_wa(aux); + + ret = drm_dp_dpcd_write(aux, DP_DSC_ENABLE, &enable, 1); + DRM_INFO("Send DSC enable to synaptics\n"); + + } else { + /* Synaptics hub not support virtual dpcd, + * external monitor occur garbage while disable DSC, + * Disable DSC only when entire link status turn to false, + */ + if (!stream->link->link_status.link_active) { + ret = drm_dp_dpcd_write(aux, DP_DSC_ENABLE, &enable, 1); + DRM_INFO("Send DSC disable to synaptics\n"); + } + } + + return ret; +} +#endif + bool dm_helpers_dp_write_dsc_enable( struct dc_context *ctx, const struct dc_stream_state *stream, @@ -570,7 +726,16 @@ bool dm_helpers_dp_write_dsc_enable( if (!aconnector->dsc_aux) return false; +#if defined(CONFIG_DRM_AMD_DC_DCN) + // apply w/a to synaptics + if (needs_dsc_aux_workaround(aconnector->dc_link) && + (aconnector->mst_downstream_port_present.byte & 0x7) != 0x3) + return write_dsc_enable_synaptics_non_virtual_dpcd_mst( + aconnector->dsc_aux, stream, enable_dsc); +#endif + ret = drm_dp_dpcd_write(aconnector->dsc_aux, DP_DSC_ENABLE, &enable_dsc, 1); + DC_LOG_DC("Send DSC %s to MST RX\n", enable_dsc ? "enable" : "disable"); } if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || stream->signal == SIGNAL_TYPE_EDP) { @@ -648,14 +813,6 @@ enum dc_edid_status dm_helpers_read_local_edid( /* We don't need the original edid anymore */ kfree(edid); - /* connector->display_info is parsed from EDID and saved - * into drm_connector->display_info - * - * drm_connector->display_info will be used by amdgpu_dm funcs, - * like fill_stream_properties_from_drm_display_mode - */ - amdgpu_dm_update_connector_after_detect(aconnector); - edid_status = dm_helpers_parse_edid_caps( link, &sink->dc_edid, @@ -797,16 +954,12 @@ void dm_helpers_mst_enable_stream_features(const struct dc_stream_state *stream) sizeof(new_downspread)); } -#if defined(CONFIG_DRM_AMD_DC_DCN) void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz) { - // FPGA programming for this clock in diags framework that - // needs to go through dm layer, therefore leave dummy interace here + // TODO } - void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable) { /* TODO: add peridic detection implementation */ } -#endif |