mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 17:13:52 +02:00
drm/amd/display: Wait for ACK for INBOX0 HW Lock
[Why] In DC we want to wait for the INBOX0 HW Lock command to ACK before continuing. This is to ensure that the lock has been successfully acquired before programming HW in DC. [How] Add interfaces to send messages on INBOX0, poll for their completation and clear the ack. Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Anson Jacob <Anson.Jacob@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
7a47c8820a
commit
d493a0244f
|
|
@ -115,13 +115,44 @@ void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv)
|
|||
}
|
||||
}
|
||||
|
||||
void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dmub_srv)
|
||||
{
|
||||
struct dmub_srv *dmub = dmub_srv->dmub;
|
||||
struct dc_context *dc_ctx = dmub_srv->ctx;
|
||||
enum dmub_status status = DMUB_STATUS_OK;
|
||||
|
||||
status = dmub_srv_clear_inbox0_ack(dmub);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error clearing INBOX0 ack: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dmub_srv);
|
||||
}
|
||||
}
|
||||
|
||||
void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dmub_srv)
|
||||
{
|
||||
struct dmub_srv *dmub = dmub_srv->dmub;
|
||||
struct dc_context *dc_ctx = dmub_srv->ctx;
|
||||
enum dmub_status status = DMUB_STATUS_OK;
|
||||
|
||||
status = dmub_srv_wait_for_inbox0_ack(dmub, 100000);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error waiting for INBOX0 HW Lock Ack\n");
|
||||
dc_dmub_srv_log_diagnostic_data(dmub_srv);
|
||||
}
|
||||
}
|
||||
|
||||
void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
|
||||
union dmub_inbox0_data_register data)
|
||||
{
|
||||
struct dmub_srv *dmub = dmub_srv->dmub;
|
||||
if (dmub->hw_funcs.send_inbox0_cmd)
|
||||
dmub->hw_funcs.send_inbox0_cmd(dmub, data);
|
||||
// TODO: Add wait command -- poll register for ACK
|
||||
struct dc_context *dc_ctx = dmub_srv->ctx;
|
||||
enum dmub_status status = DMUB_STATUS_OK;
|
||||
|
||||
status = dmub_srv_send_inbox0_cmd(dmub, data);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error sending INBOX0 cmd\n");
|
||||
dc_dmub_srv_log_diagnostic_data(dmub_srv);
|
||||
}
|
||||
}
|
||||
|
||||
bool dc_dmub_srv_cmd_with_reply_data(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd)
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ bool dc_dmub_srv_get_dmub_outbox0_msg(const struct dc *dc, struct dmcub_trace_bu
|
|||
|
||||
void dc_dmub_trace_event_control(struct dc *dc, bool enable);
|
||||
|
||||
void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dmub_srv);
|
||||
void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dmub_srv);
|
||||
void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv, union dmub_inbox0_data_register data);
|
||||
|
||||
bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *dmub_oca);
|
||||
|
|
|
|||
|
|
@ -56,8 +56,11 @@ void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
|
|||
union dmub_inbox0_cmd_lock_hw hw_lock_cmd)
|
||||
{
|
||||
union dmub_inbox0_data_register data = { 0 };
|
||||
|
||||
data.inbox0_cmd_lock_hw = hw_lock_cmd;
|
||||
dc_dmub_srv_clear_inbox0_ack(dmub_srv);
|
||||
dc_dmub_srv_send_inbox0_cmd(dmub_srv, data);
|
||||
dc_dmub_srv_wait_for_inbox0_ack(dmub_srv);
|
||||
}
|
||||
|
||||
bool should_use_dmub_lock(struct dc_link *link)
|
||||
|
|
|
|||
|
|
@ -360,6 +360,8 @@ struct dmub_srv_hw_funcs {
|
|||
|
||||
uint32_t (*get_gpint_dataout)(struct dmub_srv *dmub);
|
||||
|
||||
void (*clear_inbox0_ack_register)(struct dmub_srv *dmub);
|
||||
uint32_t (*read_inbox0_ack_register)(struct dmub_srv *dmub);
|
||||
void (*send_inbox0_cmd)(struct dmub_srv *dmub, union dmub_inbox0_data_register data);
|
||||
uint32_t (*get_current_time)(struct dmub_srv *dmub);
|
||||
|
||||
|
|
@ -735,6 +737,45 @@ bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_
|
|||
|
||||
bool dmub_srv_should_detect(struct dmub_srv *dmub);
|
||||
|
||||
/**
|
||||
* dmub_srv_send_inbox0_cmd() - Send command to DMUB using INBOX0
|
||||
* @dmub: the dmub service
|
||||
* @data: the data to be sent in the INBOX0 command
|
||||
*
|
||||
* Send command by writing directly to INBOX0 WPTR
|
||||
*
|
||||
* Return:
|
||||
* DMUB_STATUS_OK - success
|
||||
* DMUB_STATUS_INVALID - hw_init false or hw function does not exist
|
||||
*/
|
||||
enum dmub_status dmub_srv_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data);
|
||||
|
||||
/**
|
||||
* dmub_srv_wait_for_inbox0_ack() - wait for DMUB to ACK INBOX0 command
|
||||
* @dmub: the dmub service
|
||||
* @timeout_us: the maximum number of microseconds to wait
|
||||
*
|
||||
* Wait for DMUB to ACK the INBOX0 message
|
||||
*
|
||||
* Return:
|
||||
* DMUB_STATUS_OK - success
|
||||
* DMUB_STATUS_INVALID - hw_init false or hw function does not exist
|
||||
* DMUB_STATUS_TIMEOUT - wait for ack timed out
|
||||
*/
|
||||
enum dmub_status dmub_srv_wait_for_inbox0_ack(struct dmub_srv *dmub, uint32_t timeout_us);
|
||||
|
||||
/**
|
||||
* dmub_srv_wait_for_inbox0_ack() - clear ACK register for INBOX0
|
||||
* @dmub: the dmub service
|
||||
*
|
||||
* Clear ACK register for INBOX0
|
||||
*
|
||||
* Return:
|
||||
* DMUB_STATUS_OK - success
|
||||
* DMUB_STATUS_INVALID - hw_init false or hw function does not exist
|
||||
*/
|
||||
enum dmub_status dmub_srv_clear_inbox0_ack(struct dmub_srv *dmub);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -842,3 +842,38 @@ bool dmub_srv_should_detect(struct dmub_srv *dmub)
|
|||
|
||||
return dmub->hw_funcs.should_detect(dmub);
|
||||
}
|
||||
|
||||
enum dmub_status dmub_srv_clear_inbox0_ack(struct dmub_srv *dmub)
|
||||
{
|
||||
if (!dmub->hw_init || dmub->hw_funcs.clear_inbox0_ack_register)
|
||||
return DMUB_STATUS_INVALID;
|
||||
|
||||
dmub->hw_funcs.clear_inbox0_ack_register(dmub);
|
||||
return DMUB_STATUS_OK;
|
||||
}
|
||||
|
||||
enum dmub_status dmub_srv_wait_for_inbox0_ack(struct dmub_srv *dmub, uint32_t timeout_us)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t ack = 0;
|
||||
|
||||
if (!dmub->hw_init || !dmub->hw_funcs.read_inbox0_ack_register)
|
||||
return DMUB_STATUS_INVALID;
|
||||
|
||||
for (i = 0; i <= timeout_us; i++) {
|
||||
ack = dmub->hw_funcs.read_inbox0_ack_register(dmub);
|
||||
if (ack)
|
||||
return DMUB_STATUS_OK;
|
||||
}
|
||||
return DMUB_STATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
enum dmub_status dmub_srv_send_inbox0_cmd(struct dmub_srv *dmub,
|
||||
union dmub_inbox0_data_register data)
|
||||
{
|
||||
if (!dmub->hw_init || dmub->hw_funcs.send_inbox0_cmd)
|
||||
return DMUB_STATUS_INVALID;
|
||||
|
||||
dmub->hw_funcs.send_inbox0_cmd(dmub, data);
|
||||
return DMUB_STATUS_OK;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user