diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 133 |
1 files changed, 130 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 6b72af2b3f4c..360f3199ea6f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -86,6 +86,7 @@ void dc_dmub_srv_cmd_queue(struct dc_dmub_srv *dc_dmub_srv, error: DC_ERROR("Error queuing DMUB command: status=%d\n", status); + dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); } void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv) @@ -95,8 +96,10 @@ void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv) enum dmub_status status; status = dmub_srv_cmd_execute(dmub); - if (status != DMUB_STATUS_OK) + if (status != DMUB_STATUS_OK) { DC_ERROR("Error starting DMUB execution: status=%d\n", status); + dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); + } } void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv) @@ -106,8 +109,19 @@ void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv) enum dmub_status status; status = dmub_srv_wait_for_idle(dmub, 100000); - if (status != DMUB_STATUS_OK) + if (status != DMUB_STATUS_OK) { DC_ERROR("Error waiting for DMUB idle: status=%d\n", status); + dc_dmub_srv_log_diagnostic_data(dc_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 } bool dc_dmub_srv_cmd_with_reply_data(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd) @@ -172,6 +186,28 @@ bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv, stream_mask, timeout) == DMUB_STATUS_OK; } +bool dc_dmub_srv_is_restore_required(struct dc_dmub_srv *dc_dmub_srv) +{ + struct dmub_srv *dmub; + struct dc_context *dc_ctx; + union dmub_fw_boot_status boot_status; + enum dmub_status status; + + if (!dc_dmub_srv || !dc_dmub_srv->dmub) + return false; + + dmub = dc_dmub_srv->dmub; + dc_ctx = dc_dmub_srv->ctx; + + status = dmub_srv_get_fw_boot_status(dmub, &boot_status); + if (status != DMUB_STATUS_OK) { + DC_ERROR("Error querying DMUB boot status: error=%d\n", status); + return false; + } + + return boot_status.bits.restore_required; +} + bool dc_dmub_srv_get_dmub_outbox0_msg(const struct dc *dc, struct dmcub_trace_buf_entry *entry) { struct dmub_srv *dmub = dc->ctx->dmub_srv->dmub; @@ -180,5 +216,96 @@ 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) { - dm_helpers_dmub_outbox0_interrupt_control(dc->ctx, enable); + dm_helpers_dmub_outbox_interrupt_control(dc->ctx, enable); +} + +bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *diag_data) +{ + if (!dc_dmub_srv || !dc_dmub_srv->dmub || !diag_data) + return false; + return dmub_srv_get_diagnostic_data(dc_dmub_srv->dmub, diag_data); +} + +void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv) +{ + struct dmub_diagnostic_data diag_data = {0}; + + if (!dc_dmub_srv || !dc_dmub_srv->dmub) { + DC_LOG_ERROR("%s: invalid parameters.", __func__); + return; + } + + if (!dc_dmub_srv_get_diagnostic_data(dc_dmub_srv, &diag_data)) { + DC_LOG_ERROR("%s: dc_dmub_srv_get_diagnostic_data failed.", __func__); + return; + } + + DC_LOG_DEBUG( + "DMCUB STATE\n" + " dmcub_version : %08x\n" + " scratch [0] : %08x\n" + " scratch [1] : %08x\n" + " scratch [2] : %08x\n" + " scratch [3] : %08x\n" + " scratch [4] : %08x\n" + " scratch [5] : %08x\n" + " scratch [6] : %08x\n" + " scratch [7] : %08x\n" + " scratch [8] : %08x\n" + " scratch [9] : %08x\n" + " scratch [10] : %08x\n" + " scratch [11] : %08x\n" + " scratch [12] : %08x\n" + " scratch [13] : %08x\n" + " scratch [14] : %08x\n" + " scratch [15] : %08x\n" + " pc : %08x\n" + " unk_fault_addr : %08x\n" + " inst_fault_addr : %08x\n" + " data_fault_addr : %08x\n" + " inbox1_rptr : %08x\n" + " inbox1_wptr : %08x\n" + " inbox1_size : %08x\n" + " inbox0_rptr : %08x\n" + " inbox0_wptr : %08x\n" + " inbox0_size : %08x\n" + " is_enabled : %d\n" + " is_soft_reset : %d\n" + " is_secure_reset : %d\n" + " is_traceport_en : %d\n" + " is_cw0_en : %d\n" + " is_cw6_en : %d\n", + diag_data.dmcub_version, + diag_data.scratch[0], + diag_data.scratch[1], + diag_data.scratch[2], + diag_data.scratch[3], + diag_data.scratch[4], + diag_data.scratch[5], + diag_data.scratch[6], + diag_data.scratch[7], + diag_data.scratch[8], + diag_data.scratch[9], + diag_data.scratch[10], + diag_data.scratch[11], + diag_data.scratch[12], + diag_data.scratch[13], + diag_data.scratch[14], + diag_data.scratch[15], + diag_data.pc, + diag_data.undefined_address_fault_addr, + diag_data.inst_fetch_fault_addr, + diag_data.data_write_fault_addr, + diag_data.inbox1_rptr, + diag_data.inbox1_wptr, + diag_data.inbox1_size, + diag_data.inbox0_rptr, + diag_data.inbox0_wptr, + diag_data.inbox0_size, + diag_data.is_dmcub_enabled, + diag_data.is_dmcub_soft_reset, + diag_data.is_dmcub_secure_reset, + diag_data.is_traceport_en, + diag_data.is_cw0_enabled, + diag_data.is_cw6_enabled); } |