summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dmub/src
diff options
context:
space:
mode:
authorYongqiang Sun <yongqiang.sun@amd.com>2021-02-19 14:50:23 -0500
committerAlex Deucher <alexander.deucher@amd.com>2021-03-02 14:07:10 -0500
commit70732504c53b2d3aae2cebc457515a304672d5bb (patch)
tree4ab85b325e0118c62913a0334743757a095557a2 /drivers/gpu/drm/amd/display/dmub/src
parent8039bc7130ef4206a58e4dc288621bc97eba08eb (diff)
drm/amd/display: Implement dmub trace event
[Why & How] DMUB FW send trace event via outbox0 interrupt. Driver will handle it. Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com> Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dmub/src')
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c18
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h17
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c48
3 files changed, 79 insertions, 4 deletions
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
index 071331bcc427..6934906c665e 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
@@ -319,6 +319,24 @@ void dmub_dcn20_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
REG_WRITE(DMCUB_OUTBOX1_RPTR, rptr_offset);
}
+void dmub_dcn20_setup_outbox0(struct dmub_srv *dmub,
+ const struct dmub_region *outbox0)
+{
+ REG_WRITE(DMCUB_OUTBOX0_BASE_ADDRESS, outbox0->base);
+
+ REG_WRITE(DMCUB_OUTBOX0_SIZE, outbox0->top - outbox0->base);
+}
+
+uint32_t dmub_dcn20_get_outbox0_wptr(struct dmub_srv *dmub)
+{
+ return REG_READ(DMCUB_OUTBOX0_WPTR);
+}
+
+void dmub_dcn20_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
+{
+ REG_WRITE(DMCUB_OUTBOX0_RPTR, rptr_offset);
+}
+
bool dmub_dcn20_is_hw_init(struct dmub_srv *dmub)
{
uint32_t is_hw_init;
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
index df85c3b86607..de5351cd5abc 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
@@ -40,6 +40,10 @@ struct dmub_srv;
DMUB_SR(DMCUB_INBOX1_SIZE) \
DMUB_SR(DMCUB_INBOX1_RPTR) \
DMUB_SR(DMCUB_INBOX1_WPTR) \
+ DMUB_SR(DMCUB_OUTBOX0_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_OUTBOX0_SIZE) \
+ DMUB_SR(DMCUB_OUTBOX0_RPTR) \
+ DMUB_SR(DMCUB_OUTBOX0_WPTR) \
DMUB_SR(DMCUB_OUTBOX1_BASE_ADDRESS) \
DMUB_SR(DMCUB_OUTBOX1_SIZE) \
DMUB_SR(DMCUB_OUTBOX1_RPTR) \
@@ -102,7 +106,8 @@ struct dmub_srv;
DMUB_SR(CC_DC_PIPE_DIS) \
DMUB_SR(MMHUBBUB_SOFT_RESET) \
DMUB_SR(DCN_VM_FB_LOCATION_BASE) \
- DMUB_SR(DCN_VM_FB_OFFSET)
+ DMUB_SR(DCN_VM_FB_OFFSET) \
+ DMUB_SR(DMCUB_INTERRUPT_ACK)
#define DMUB_COMMON_FIELDS() \
DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \
@@ -135,7 +140,8 @@ struct dmub_srv;
DMUB_SF(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE) \
DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \
DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \
- DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET)
+ DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \
+ DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX0_READY_INT_ACK)
struct dmub_srv_common_reg_offset {
#define DMUB_SR(reg) uint32_t reg;
@@ -196,6 +202,13 @@ uint32_t dmub_dcn20_get_outbox1_wptr(struct dmub_srv *dmub);
void dmub_dcn20_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset);
+void dmub_dcn20_setup_outbox0(struct dmub_srv *dmub,
+ const struct dmub_region *outbox0);
+
+uint32_t dmub_dcn20_get_outbox0_wptr(struct dmub_srv *dmub);
+
+void dmub_dcn20_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset);
+
bool dmub_dcn20_is_hw_init(struct dmub_srv *dmub);
bool dmub_dcn20_is_supported(struct dmub_srv *dmub);
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
index 6943bf679b42..eb9bf4da088a 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
@@ -31,6 +31,7 @@
#include "dmub_dcn301.h"
#include "dmub_dcn302.h"
#include "os_types.h"
+#include "dmub_trace_buffer.h"
/*
* Note: the DMUB service is standalone. No additional headers should be
* added below or above this line unless they reside within the DMUB
@@ -55,6 +56,7 @@
/* Default tracebuffer size if meta is absent. */
#define DMUB_TRACE_BUFFER_SIZE (64 * 1024)
+
/* Default scratch mem size. */
#define DMUB_SCRATCH_MEM_SIZE (256)
@@ -69,6 +71,8 @@
#define DMUB_CW5_BASE (0x65000000)
#define DMUB_CW6_BASE (0x66000000)
+#define DMUB_REGION5_BASE (0xA0000000)
+
static inline uint32_t dmub_align(uint32_t val, uint32_t factor)
{
return (val + factor - 1) / factor * factor;
@@ -162,6 +166,11 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
funcs->get_outbox1_wptr = dmub_dcn20_get_outbox1_wptr;
funcs->set_outbox1_rptr = dmub_dcn20_set_outbox1_rptr;
+ //outbox0 call stacks
+ funcs->setup_outbox0 = dmub_dcn20_setup_outbox0;
+ funcs->get_outbox0_wptr = dmub_dcn20_get_outbox0_wptr;
+ funcs->set_outbox0_rptr = dmub_dcn20_set_outbox0_rptr;
+
if (asic == DMUB_ASIC_DCN21) {
dmub->regs = &dmub_srv_dcn21_regs;
@@ -400,9 +409,9 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
struct dmub_fb *fw_state_fb = params->fb[DMUB_WINDOW_6_FW_STATE];
struct dmub_fb *scratch_mem_fb = params->fb[DMUB_WINDOW_7_SCRATCH_MEM];
- struct dmub_rb_init_params rb_params;
+ struct dmub_rb_init_params rb_params, outbox0_rb_params;
struct dmub_window cw0, cw1, cw2, cw3, cw4, cw5, cw6;
- struct dmub_region inbox1, outbox1;
+ struct dmub_region inbox1, outbox1, outbox0;
if (!dmub->sw_init)
return DMUB_STATUS_INVALID;
@@ -465,6 +474,10 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
cw5.region.base = DMUB_CW5_BASE;
cw5.region.top = cw5.region.base + tracebuff_fb->size;
+ outbox0.base = DMUB_REGION5_BASE + TRACE_BUFFER_ENTRY_OFFSET;
+ outbox0.top = outbox0.base + sizeof(struct dmcub_trace_buf_entry) * PERF_TRACE_MAX_ENTRY;
+
+
cw6.offset.quad_part = fw_state_fb->gpu_addr;
cw6.region.base = DMUB_CW6_BASE;
cw6.region.top = cw6.region.base + fw_state_fb->size;
@@ -477,6 +490,9 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
dmub->hw_funcs.setup_windows(dmub, &cw2, &cw3, &cw4,
&cw5, &cw6);
+ if (dmub->hw_funcs.setup_outbox0)
+ dmub->hw_funcs.setup_outbox0(dmub, &outbox0);
+
if (dmub->hw_funcs.setup_mailbox)
dmub->hw_funcs.setup_mailbox(dmub, &inbox1);
if (dmub->hw_funcs.setup_out_mailbox)
@@ -499,6 +515,12 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
}
+ dmub_memset(&outbox0_rb_params, 0, sizeof(outbox0_rb_params));
+ outbox0_rb_params.ctx = dmub;
+ outbox0_rb_params.base_address = (void *)((uint64_t)(tracebuff_fb->cpu_addr) + TRACE_BUFFER_ENTRY_OFFSET);
+ outbox0_rb_params.capacity = sizeof(struct dmcub_trace_buf_entry) * PERF_TRACE_MAX_ENTRY;
+ dmub_rb_init(&dmub->outbox0_rb, &outbox0_rb_params);
+
if (dmub->hw_funcs.reset_release)
dmub->hw_funcs.reset_release(dmub);
@@ -697,3 +719,25 @@ enum dmub_status dmub_srv_cmd_with_reply_data(struct dmub_srv *dmub,
return status;
}
+
+static inline void dmub_rb_out_trace_buffer_front(struct dmub_rb *rb,
+ void *entry)
+{
+ const uint64_t *src = (const uint64_t *)(rb->base_address) + rb->rptr / sizeof(uint64_t);
+ uint64_t *dst = (uint64_t *)entry;
+ uint8_t i;
+
+ // copying data
+ for (i = 0; i < sizeof(struct dmcub_trace_buf_entry) / sizeof(uint64_t); i++)
+ *dst++ = *src++;
+
+}
+
+enum dmub_status dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entry *entry)
+{
+ dmub->outbox0_rb.wrpt = dmub->hw_funcs.get_outbox0_wptr(dmub);
+
+ dmub_rb_out_trace_buffer_front(&dmub->outbox0_rb, (void *)entry);
+
+ return DMUB_STATUS_OK;
+}