summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c')
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c203
1 files changed, 193 insertions, 10 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 edc73d6d7ba2..73888c1bea93 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
@@ -40,7 +40,10 @@
const struct dmub_srv_common_regs dmub_srv_dcn20_regs = {
#define DMUB_SR(reg) REG_OFFSET(reg),
- { DMUB_COMMON_REGS() },
+ {
+ DMUB_COMMON_REGS()
+ DMCUB_INTERNAL_REGS()
+ },
#undef DMUB_SR
#define DMUB_SF(reg, field) FD_MASK(reg, field),
@@ -81,6 +84,13 @@ static inline void dmub_dcn20_translate_addr(const union dmub_addr *addr_in,
addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset;
}
+bool dmub_dcn20_use_cached_inbox(struct dmub_srv *dmub)
+{
+ /* Cached inbox is not supported in this fw version range */
+ return !(dmub->fw_version >= DMUB_FW_VERSION(1, 0, 0) &&
+ dmub->fw_version <= DMUB_FW_VERSION(1, 10, 0));
+}
+
void dmub_dcn20_reset(struct dmub_srv *dmub)
{
union dmub_gpint_data_register cmd;
@@ -128,6 +138,8 @@ void dmub_dcn20_reset(struct dmub_srv *dmub)
REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1);
REG_WRITE(DMCUB_INBOX1_RPTR, 0);
REG_WRITE(DMCUB_INBOX1_WPTR, 0);
+ REG_WRITE(DMCUB_OUTBOX1_RPTR, 0);
+ REG_WRITE(DMCUB_OUTBOX1_WPTR, 0);
REG_WRITE(DMCUB_SCRATCH0, 0);
}
@@ -179,7 +191,8 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw3,
const struct dmub_window *cw4,
const struct dmub_window *cw5,
- const struct dmub_window *cw6)
+ const struct dmub_window *cw6,
+ const struct dmub_window *region6)
{
union dmub_addr offset;
uint64_t fb_base, fb_offset;
@@ -215,11 +228,22 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
/* TODO: Move this to CW4. */
dmub_dcn20_translate_addr(&cw4->offset, fb_base, fb_offset, &offset);
- REG_WRITE(DMCUB_REGION4_OFFSET, offset.u.low_part);
- REG_WRITE(DMCUB_REGION4_OFFSET_HIGH, offset.u.high_part);
- REG_SET_2(DMCUB_REGION4_TOP_ADDRESS, 0, DMCUB_REGION4_TOP_ADDRESS,
- cw4->region.top - cw4->region.base - 1, DMCUB_REGION4_ENABLE,
- 1);
+ /* New firmware can support CW4. */
+ if (dmub_dcn20_use_cached_inbox(dmub)) {
+ REG_WRITE(DMCUB_REGION3_CW4_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION3_CW4_OFFSET_HIGH, offset.u.high_part);
+ REG_WRITE(DMCUB_REGION3_CW4_BASE_ADDRESS, cw4->region.base);
+ REG_SET_2(DMCUB_REGION3_CW4_TOP_ADDRESS, 0,
+ DMCUB_REGION3_CW4_TOP_ADDRESS, cw4->region.top,
+ DMCUB_REGION3_CW4_ENABLE, 1);
+ } else {
+ REG_WRITE(DMCUB_REGION4_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION4_OFFSET_HIGH, offset.u.high_part);
+ REG_SET_2(DMCUB_REGION4_TOP_ADDRESS, 0,
+ DMCUB_REGION4_TOP_ADDRESS,
+ cw4->region.top - cw4->region.base - 1,
+ DMCUB_REGION4_ENABLE, 1);
+ }
dmub_dcn20_translate_addr(&cw5->offset, fb_base, fb_offset, &offset);
@@ -230,6 +254,13 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top,
DMCUB_REGION3_CW5_ENABLE, 1);
+ REG_WRITE(DMCUB_REGION5_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION5_OFFSET_HIGH, offset.u.high_part);
+ REG_SET_2(DMCUB_REGION5_TOP_ADDRESS, 0,
+ DMCUB_REGION5_TOP_ADDRESS,
+ cw5->region.top - cw5->region.base - 1,
+ DMCUB_REGION5_ENABLE, 1);
+
dmub_dcn20_translate_addr(&cw6->offset, fb_base, fb_offset, &offset);
REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part);
@@ -243,12 +274,20 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
void dmub_dcn20_setup_mailbox(struct dmub_srv *dmub,
const struct dmub_region *inbox1)
{
- /* TODO: Use CW4 instead of region 4. */
+ /* New firmware can support CW4 for the inbox. */
+ if (dmub_dcn20_use_cached_inbox(dmub))
+ REG_WRITE(DMCUB_INBOX1_BASE_ADDRESS, inbox1->base);
+ else
+ REG_WRITE(DMCUB_INBOX1_BASE_ADDRESS, 0x80000000);
- REG_WRITE(DMCUB_INBOX1_BASE_ADDRESS, 0x80000000);
REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
}
+uint32_t dmub_dcn20_get_inbox1_wptr(struct dmub_srv *dmub)
+{
+ return REG_READ(DMCUB_INBOX1_WPTR);
+}
+
uint32_t dmub_dcn20_get_inbox1_rptr(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_INBOX1_RPTR);
@@ -259,9 +298,61 @@ void dmub_dcn20_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset)
REG_WRITE(DMCUB_INBOX1_WPTR, wptr_offset);
}
+void dmub_dcn20_setup_out_mailbox(struct dmub_srv *dmub,
+ const struct dmub_region *outbox1)
+{
+ /* New firmware can support CW4 for the outbox. */
+ if (dmub_dcn20_use_cached_inbox(dmub))
+ REG_WRITE(DMCUB_OUTBOX1_BASE_ADDRESS, outbox1->base);
+ else
+ REG_WRITE(DMCUB_OUTBOX1_BASE_ADDRESS, 0x80002000);
+
+ REG_WRITE(DMCUB_OUTBOX1_SIZE, outbox1->top - outbox1->base);
+}
+
+uint32_t dmub_dcn20_get_outbox1_wptr(struct dmub_srv *dmub)
+{
+ /**
+ * outbox1 wptr register is accessed without locks (dal & dc)
+ * and to be called only by dmub_srv_stat_get_notification()
+ */
+ return REG_READ(DMCUB_OUTBOX1_WPTR);
+}
+
+void dmub_dcn20_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
+{
+ /**
+ * outbox1 rptr register is accessed without locks (dal & dc)
+ * and to be called only by dmub_srv_stat_get_notification()
+ */
+ 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)
{
- return REG_READ(DMCUB_REGION3_CW2_BASE_ADDRESS) != 0;
+ uint32_t is_hw_init;
+
+ REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_hw_init);
+
+ return is_hw_init != 0;
}
bool dmub_dcn20_is_supported(struct dmub_srv *dmub)
@@ -294,3 +385,95 @@ uint32_t dmub_dcn20_get_gpint_response(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_SCRATCH7);
}
+
+union dmub_fw_boot_status dmub_dcn20_get_fw_boot_status(struct dmub_srv *dmub)
+{
+ union dmub_fw_boot_status status;
+
+ status.all = REG_READ(DMCUB_SCRATCH0);
+ return status;
+}
+
+void dmub_dcn20_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params)
+{
+ union dmub_fw_boot_options boot_options = {0};
+
+ REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
+}
+
+void dmub_dcn20_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip)
+{
+ union dmub_fw_boot_options boot_options;
+ boot_options.all = REG_READ(DMCUB_SCRATCH14);
+ boot_options.bits.skip_phy_init_panel_sequence = skip;
+ REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
+}
+
+uint32_t dmub_dcn20_get_current_time(struct dmub_srv *dmub)
+{
+ return REG_READ(DMCUB_TIMER_CURRENT);
+}
+
+void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub)
+{
+ uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset;
+ uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled;
+ struct dmub_timeout_info timeout = {0};
+
+ if (!dmub)
+ return;
+
+ /* timeout data filled externally, cache before resetting memory */
+ timeout = dmub->debug.timeout_info;
+ memset(&dmub->debug, 0, sizeof(dmub->debug));
+ dmub->debug.timeout_info = timeout;
+
+ dmub->debug.dmcub_version = dmub->fw_version;
+
+ dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0);
+ dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1);
+ dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2);
+ dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3);
+ dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4);
+ dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5);
+ dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6);
+ dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7);
+ dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8);
+ dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9);
+ dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10);
+ dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11);
+ dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12);
+ dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13);
+ dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14);
+ dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15);
+
+ dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR);
+ dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR);
+ dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR);
+
+ dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR);
+ dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR);
+ dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE);
+
+ dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR);
+ dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR);
+ dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE);
+
+ REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
+ dmub->debug.is_dmcub_enabled = is_dmub_enabled;
+
+ REG_GET(DMCUB_CNTL, DMCUB_SOFT_RESET, &is_soft_reset);
+ dmub->debug.is_dmcub_soft_reset = is_soft_reset;
+
+ REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
+ dmub->debug.is_dmcub_secure_reset = is_sec_reset;
+
+ REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
+ dmub->debug.is_traceport_en = is_traceport_enabled;
+
+ REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
+ dmub->debug.is_cw0_enabled = is_cw0_enabled;
+
+ REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
+ dmub->debug.is_cw6_enabled = is_cw6_enabled;
+}