diff options
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.c | 203 |
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; +} |
