Commit 5419a207 authored by Nicholas Kazlauskas's avatar Nicholas Kazlauskas Committed by Alex Deucher

drm/amd/display: Notify idle link detection through shared state

[Why]
We can hang in IPS2 checking DMCUB_SCRATCH0 for link detection state.

[How]
Replace the HW access with a check on the shared state bit. This will
work the same way as the SCRATCH0 but won't require a wake in the case
where link detection isn't required.
Reviewed-by: default avatarDuncan Ma <duncan.ma@amd.com>
Acked-by: default avatarWayne Lin <wayne.lin@amd.com>
Signed-off-by: default avatarNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent d2c5cb0c
...@@ -1460,6 +1460,36 @@ void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_c ...@@ -1460,6 +1460,36 @@ void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_c
dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D3); dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D3);
} }
bool dc_dmub_srv_should_detect(struct dc_dmub_srv *dc_dmub_srv)
{
volatile const struct dmub_shared_state_ips_fw *ips_fw;
bool reallow_idle = false, should_detect = false;
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
return false;
if (dc_dmub_srv->dmub->shared_state &&
dc_dmub_srv->dmub->meta_info.feature_bits.bits.shared_state_link_detection) {
ips_fw = &dc_dmub_srv->dmub->shared_state[DMUB_SHARED_SHARE_FEATURE__IPS_FW].data.ips_fw;
return ips_fw->signals.bits.detection_required;
}
/* Detection may require reading scratch 0 - exit out of idle prior to the read. */
if (dc_dmub_srv->idle_allowed) {
dc_dmub_srv_apply_idle_power_optimizations(dc_dmub_srv->ctx->dc, false);
reallow_idle = true;
}
should_detect = dmub_srv_should_detect(dc_dmub_srv->dmub);
/* Re-enter idle if we're not about to immediately redetect links. */
if (!should_detect && reallow_idle && dc_dmub_srv->idle_exit_counter == 0 &&
!dc_dmub_srv->ctx->dc->debug.disable_dmub_reallow_idle)
dc_dmub_srv_apply_idle_power_optimizations(dc_dmub_srv->ctx->dc, true);
return should_detect;
}
void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_idle) void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_idle)
{ {
struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv; struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv;
......
...@@ -111,6 +111,16 @@ void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_ ...@@ -111,6 +111,16 @@ void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_
void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState); void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState);
/**
* @dc_dmub_srv_should_detect() - Checks if link detection is required.
*
* While in idle power states we may need driver to manually redetect in
* the case of a missing hotplug. Should be called from a polling timer.
*
* Return: true if redetection is required.
*/
bool dc_dmub_srv_should_detect(struct dc_dmub_srv *dc_dmub_srv);
/** /**
* dc_wake_and_execute_dmub_cmd() - Wrapper for DMUB command execution. * dc_wake_and_execute_dmub_cmd() - Wrapper for DMUB command execution.
* *
......
...@@ -529,6 +529,7 @@ struct dmub_srv { ...@@ -529,6 +529,7 @@ struct dmub_srv {
uint32_t psp_version; uint32_t psp_version;
/* Feature capabilities reported by fw */ /* Feature capabilities reported by fw */
struct dmub_fw_meta_info meta_info;
struct dmub_feature_caps feature_caps; struct dmub_feature_caps feature_caps;
struct dmub_visual_confirm_color visual_confirm_color; struct dmub_visual_confirm_color visual_confirm_color;
......
...@@ -496,6 +496,17 @@ struct dmub_visual_confirm_color { ...@@ -496,6 +496,17 @@ struct dmub_visual_confirm_color {
/* Offset from the end of the file to the dmub_fw_meta_info */ /* Offset from the end of the file to the dmub_fw_meta_info */
#define DMUB_FW_META_OFFSET 0x24 #define DMUB_FW_META_OFFSET 0x24
/**
* union dmub_fw_meta_feature_bits - Static feature bits for pre-initialization
*/
union dmub_fw_meta_feature_bits {
struct {
uint32_t shared_state_link_detection : 1; /**< 1 supports link detection via shared state */
uint32_t reserved : 31;
} bits; /**< status bits */
uint32_t all; /**< 32-bit access to status bits */
};
/** /**
* struct dmub_fw_meta_info - metadata associated with fw binary * struct dmub_fw_meta_info - metadata associated with fw binary
* *
...@@ -521,6 +532,7 @@ struct dmub_fw_meta_info { ...@@ -521,6 +532,7 @@ struct dmub_fw_meta_info {
uint32_t shared_state_size; /**< size of the shared state region in bytes */ uint32_t shared_state_size; /**< size of the shared state region in bytes */
uint16_t shared_state_features; /**< number of shared state features */ uint16_t shared_state_features; /**< number of shared state features */
uint16_t reserved2; /**< padding bytes */ uint16_t reserved2; /**< padding bytes */
union dmub_fw_meta_feature_bits feature_bits; /**< static feature bits */
}; };
/** /**
...@@ -698,7 +710,8 @@ union dmub_shared_state_ips_fw_signals { ...@@ -698,7 +710,8 @@ union dmub_shared_state_ips_fw_signals {
uint32_t ips1_commit : 1; /**< 1 if in IPS1 */ uint32_t ips1_commit : 1; /**< 1 if in IPS1 */
uint32_t ips2_commit : 1; /**< 1 if in IPS2 */ uint32_t ips2_commit : 1; /**< 1 if in IPS2 */
uint32_t in_idle : 1; /**< 1 if DMCUB is in idle */ uint32_t in_idle : 1; /**< 1 if DMCUB is in idle */
uint32_t reserved_bits : 29; /**< Reversed */ uint32_t detection_required : 1; /**< 1 if detection is required */
uint32_t reserved_bits : 28; /**< Reversed */
} bits; } bits;
uint32_t all; uint32_t all;
}; };
......
...@@ -510,6 +510,8 @@ enum dmub_status ...@@ -510,6 +510,8 @@ enum dmub_status
fw_info = dmub_get_fw_meta_info(params); fw_info = dmub_get_fw_meta_info(params);
if (fw_info) { if (fw_info) {
memcpy(&dmub->meta_info, fw_info, sizeof(*fw_info));
fw_state_size = fw_info->fw_region_size; fw_state_size = fw_info->fw_region_size;
trace_buffer_size = fw_info->trace_buffer_size; trace_buffer_size = fw_info->trace_buffer_size;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment