drm/amd/display: do not send commands to DMUB if DMUB is inactive from S3
[Why] On resume from S3, may get apply_idle_optimizations call while DMUB is inactive which will just time out. [How] Set and track power state in dmub_srv and check power state before sending commands to DMUB. Add interface in both dmub_srv and dc_dmub_srv Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Acked-by: Wayne Lin <wayne.lin@amd.com> Signed-off-by: Samson Tam <samson.tam@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
7046ca9c1b
commit
0f657938e4
@ -2687,6 +2687,7 @@ static int dm_suspend(void *handle)
|
|||||||
hpd_rx_irq_work_suspend(dm);
|
hpd_rx_irq_work_suspend(dm);
|
||||||
|
|
||||||
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3);
|
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3);
|
||||||
|
dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D3);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2882,6 +2883,7 @@ static int dm_resume(void *handle)
|
|||||||
if (r)
|
if (r)
|
||||||
DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r);
|
DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r);
|
||||||
|
|
||||||
|
dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0);
|
||||||
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);
|
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);
|
||||||
|
|
||||||
dc_resume(dm->dc);
|
dc_resume(dm->dc);
|
||||||
@ -2932,6 +2934,7 @@ static int dm_resume(void *handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* power on hardware */
|
/* power on hardware */
|
||||||
|
dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0);
|
||||||
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);
|
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);
|
||||||
|
|
||||||
/* program HPD filter */
|
/* program HPD filter */
|
||||||
|
@ -1268,3 +1268,17 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
|
|||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState)
|
||||||
|
{
|
||||||
|
struct dmub_srv *dmub;
|
||||||
|
|
||||||
|
if (!dc_dmub_srv)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dmub = dc_dmub_srv->dmub;
|
||||||
|
|
||||||
|
if (powerState == DC_ACPI_CM_POWER_STATE_D0)
|
||||||
|
dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D0);
|
||||||
|
else
|
||||||
|
dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D3);
|
||||||
|
}
|
||||||
|
@ -102,4 +102,6 @@ void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, con
|
|||||||
bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait);
|
bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait);
|
||||||
void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle);
|
void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle);
|
||||||
void dc_dmub_srv_exit_low_power_state(const struct dc *dc);
|
void dc_dmub_srv_exit_low_power_state(const struct dc *dc);
|
||||||
|
|
||||||
|
void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState);
|
||||||
#endif /* _DMUB_DC_SRV_H_ */
|
#endif /* _DMUB_DC_SRV_H_ */
|
||||||
|
@ -150,6 +150,13 @@ enum dmub_memory_access_type {
|
|||||||
DMUB_MEMORY_ACCESS_DMA
|
DMUB_MEMORY_ACCESS_DMA
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* enum dmub_power_state type - to track DC power state in dmub_srv */
|
||||||
|
enum dmub_srv_power_state_type {
|
||||||
|
DMUB_POWER_STATE_UNDEFINED = 0,
|
||||||
|
DMUB_POWER_STATE_D0 = 1,
|
||||||
|
DMUB_POWER_STATE_D3 = 8
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct dmub_region - dmub hw memory region
|
* struct dmub_region - dmub hw memory region
|
||||||
* @base: base address for region, must be 256 byte aligned
|
* @base: base address for region, must be 256 byte aligned
|
||||||
@ -485,6 +492,8 @@ struct dmub_srv {
|
|||||||
/* Feature capabilities reported by fw */
|
/* Feature capabilities reported by fw */
|
||||||
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;
|
||||||
|
|
||||||
|
enum dmub_srv_power_state_type power_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -889,6 +898,18 @@ enum dmub_status dmub_srv_clear_inbox0_ack(struct dmub_srv *dmub);
|
|||||||
*/
|
*/
|
||||||
void dmub_srv_subvp_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_address *addr, uint8_t subvp_index);
|
void dmub_srv_subvp_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_address *addr, uint8_t subvp_index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dmub_srv_set_power_state() - Track DC power state in dmub_srv
|
||||||
|
* @dmub: The dmub service
|
||||||
|
* @power_state: DC power state setting
|
||||||
|
*
|
||||||
|
* Store DC power state in dmub_srv. If dmub_srv is in D3, then don't send messages to DMUB
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* void
|
||||||
|
*/
|
||||||
|
void dmub_srv_set_power_state(struct dmub_srv *dmub, enum dmub_srv_power_state_type dmub_srv_power_state);
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -713,6 +713,7 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
|
|||||||
dmub->hw_funcs.reset_release(dmub);
|
dmub->hw_funcs.reset_release(dmub);
|
||||||
|
|
||||||
dmub->hw_init = true;
|
dmub->hw_init = true;
|
||||||
|
dmub->power_state = DMUB_POWER_STATE_D0;
|
||||||
|
|
||||||
return DMUB_STATUS_OK;
|
return DMUB_STATUS_OK;
|
||||||
}
|
}
|
||||||
@ -766,6 +767,9 @@ enum dmub_status dmub_srv_cmd_queue(struct dmub_srv *dmub,
|
|||||||
if (!dmub->hw_init)
|
if (!dmub->hw_init)
|
||||||
return DMUB_STATUS_INVALID;
|
return DMUB_STATUS_INVALID;
|
||||||
|
|
||||||
|
if (dmub->power_state != DMUB_POWER_STATE_D0)
|
||||||
|
return DMUB_STATUS_INVALID;
|
||||||
|
|
||||||
if (dmub->inbox1_rb.rptr > dmub->inbox1_rb.capacity ||
|
if (dmub->inbox1_rb.rptr > dmub->inbox1_rb.capacity ||
|
||||||
dmub->inbox1_rb.wrpt > dmub->inbox1_rb.capacity) {
|
dmub->inbox1_rb.wrpt > dmub->inbox1_rb.capacity) {
|
||||||
return DMUB_STATUS_HW_FAILURE;
|
return DMUB_STATUS_HW_FAILURE;
|
||||||
@ -784,6 +788,9 @@ enum dmub_status dmub_srv_cmd_execute(struct dmub_srv *dmub)
|
|||||||
if (!dmub->hw_init)
|
if (!dmub->hw_init)
|
||||||
return DMUB_STATUS_INVALID;
|
return DMUB_STATUS_INVALID;
|
||||||
|
|
||||||
|
if (dmub->power_state != DMUB_POWER_STATE_D0)
|
||||||
|
return DMUB_STATUS_INVALID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read back all the queued commands to ensure that they've
|
* Read back all the queued commands to ensure that they've
|
||||||
* been flushed to framebuffer memory. Otherwise DMCUB might
|
* been flushed to framebuffer memory. Otherwise DMCUB might
|
||||||
@ -1100,3 +1107,11 @@ void dmub_srv_subvp_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_
|
|||||||
subvp_index);
|
subvp_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dmub_srv_set_power_state(struct dmub_srv *dmub, enum dmub_srv_power_state_type dmub_srv_power_state)
|
||||||
|
{
|
||||||
|
if (!dmub || !dmub->hw_init)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dmub->power_state = dmub_srv_power_state;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user