diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dmub')
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/inc/dmub_fw_meta.h (renamed from drivers/gpu/drm/amd/display/dmub/inc/dmub_fw_state.h) | 64 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c | 84 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h | 117 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c | 107 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c | 57 |
8 files changed, 289 insertions, 170 deletions
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_fw_state.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_fw_meta.h index c87b1ba7590e..242ec257998c 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_fw_state.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_fw_meta.h @@ -22,52 +22,42 @@ * Authors: AMD * */ - -#ifndef _DMUB_FW_STATE_H_ -#define _DMUB_FW_STATE_H_ +#ifndef _DMUB_META_H_ +#define _DMUB_META_H_ #include "dmub_types.h" #pragma pack(push, 1) -struct dmub_fw_state { - /** - * @phy_initialized_during_fw_boot: - * - * Detects if VBIOS/VBL has ran before firmware boot. - * A value of 1 will usually mean S0i3 boot. - */ - uint8_t phy_initialized_during_fw_boot; - - /** - * @intialized_phy: - * - * Bit vector of initialized PHY. - */ - uint8_t initialized_phy; +/* Magic value for identifying dmub_fw_meta_info */ +#define DMUB_FW_META_MAGIC 0x444D5542 - /** - * @enabled_phy: - * - * Bit vector of enabled PHY for DP alt mode switch tracking. - */ - uint8_t enabled_phy; +/* Offset from the end of the file to the dmub_fw_meta_info */ +#define DMUB_FW_META_OFFSET 0x24 - /** - * @dmcu_fw_loaded: - * - * DMCU auto load state. - */ - uint8_t dmcu_fw_loaded; +/** + * struct dmub_fw_meta_info - metadata associated with fw binary + * + * NOTE: This should be considered a stable API. Fields should + * not be repurposed or reordered. New fields should be + * added instead to extend the structure. + * + * @magic_value: magic value identifying DMUB firmware meta info + * @fw_region_size: size of the firmware state region + * @trace_buffer_size: size of the tracebuffer region + */ +struct dmub_fw_meta_info { + uint32_t magic_value; + uint32_t fw_region_size; + uint32_t trace_buffer_size; +}; - /** - * @psr_state: - * - * PSR state tracking. - */ - uint8_t psr_state; +/* Ensure that the structure remains 64 bytes. */ +union dmub_fw_meta { + struct dmub_fw_meta_info info; + uint8_t reserved[64]; }; #pragma pack(pop) -#endif /* _DMUB_FW_STATE_H_ */ +#endif /* _DMUB_META_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h index 528243e35add..f34a50dd36ea 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h @@ -67,7 +67,6 @@ #include "dmub_types.h" #include "dmub_cmd.h" #include "dmub_rb.h" -#include "dmub_fw_state.h" #if defined(__cplusplus) extern "C" { @@ -76,7 +75,7 @@ extern "C" { /* Forward declarations */ struct dmub_srv; struct dmub_cmd_header; -struct dmcu; +struct dmub_srv_common_regs; /* enum dmub_status - return code for dmcub functions */ enum dmub_status { @@ -145,11 +144,13 @@ struct dmub_fb { * @inst_const_size: size of the fw inst const section * @bss_data_size: size of the fw bss data section * @vbios_size: size of the vbios data + * @fw_bss_data: raw firmware bss data section */ struct dmub_srv_region_params { uint32_t inst_const_size; uint32_t bss_data_size; uint32_t vbios_size; + const uint8_t *fw_bss_data; }; /** @@ -307,6 +308,8 @@ struct dmub_srv { volatile const struct dmub_fw_state *fw_state; /* private: internal use only */ + const struct dmub_srv_common_regs *regs; + struct dmub_srv_base_funcs funcs; struct dmub_srv_hw_funcs hw_funcs; struct dmub_rb inbox1_rb; 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 951ea7053c7e..f45e14ada685 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c @@ -25,6 +25,7 @@ #include "../inc/dmub_srv.h" #include "dmub_reg.h" +#include "dmub_dcn20.h" #include "dcn/dcn_2_0_0_offset.h" #include "dcn/dcn_2_0_0_sh_mask.h" @@ -33,6 +34,33 @@ #define BASE_INNER(seg) DCN_BASE__INST0_SEG##seg #define CTX dmub +#define REGS dmub->regs + +/* Registers. */ + +const struct dmub_srv_common_regs dmub_srv_dcn20_regs = { +#define DMUB_SR(reg) REG_OFFSET(reg), + { DMUB_COMMON_REGS() }, +#undef DMUB_SR + +#define DMUB_SF(reg, field) FD_MASK(reg, field), + { DMUB_COMMON_FIELDS() }, +#undef DMUB_SF + +#define DMUB_SF(reg, field) FD_SHIFT(reg, field), + { DMUB_COMMON_FIELDS() }, +#undef DMUB_SF +}; + +/* Shared functions. */ + +static inline void dmub_dcn20_translate_addr(const union dmub_addr *addr_in, + uint64_t fb_base, + uint64_t fb_offset, + union dmub_addr *addr_out) +{ + addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset; +} void dmub_dcn20_reset(struct dmub_srv *dmub) { @@ -47,22 +75,30 @@ void dmub_dcn20_reset_release(struct dmub_srv *dmub) REG_UPDATE(DMCUB_CNTL, DMCUB_SOFT_RESET, 0); } -void dmub_dcn20_backdoor_load(struct dmub_srv *dmub, struct dmub_window *cw0, - struct dmub_window *cw1) +void dmub_dcn20_backdoor_load(struct dmub_srv *dmub, + const struct dmub_window *cw0, + const struct dmub_window *cw1) { + union dmub_addr offset; + uint64_t fb_base = dmub->fb_base, fb_offset = dmub->fb_offset; + REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1); - REG_UPDATE_2(DMCUB_MEM_CNTL, DMCUB_MEM_READ_SPACE, 0x4, - DMCUB_MEM_WRITE_SPACE, 0x4); + REG_UPDATE_2(DMCUB_MEM_CNTL, DMCUB_MEM_READ_SPACE, 0x3, + DMCUB_MEM_WRITE_SPACE, 0x3); + + dmub_dcn20_translate_addr(&cw0->offset, fb_base, fb_offset, &offset); - REG_WRITE(DMCUB_REGION3_CW0_OFFSET, cw0->offset.u.low_part); - REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, cw0->offset.u.high_part); + REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part); REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base); REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0, DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top, DMCUB_REGION3_CW0_ENABLE, 1); - REG_WRITE(DMCUB_REGION3_CW1_OFFSET, cw1->offset.u.low_part); - REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, cw1->offset.u.high_part); + dmub_dcn20_translate_addr(&cw1->offset, fb_base, fb_offset, &offset); + + REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part); REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base); REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0, DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top, @@ -79,37 +115,49 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub, const struct dmub_window *cw5, const struct dmub_window *cw6) { - REG_WRITE(DMCUB_REGION3_CW2_OFFSET, cw2->offset.u.low_part); - REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, cw2->offset.u.high_part); + union dmub_addr offset; + uint64_t fb_base = dmub->fb_base, fb_offset = dmub->fb_offset; + + dmub_dcn20_translate_addr(&cw2->offset, fb_base, fb_offset, &offset); + + REG_WRITE(DMCUB_REGION3_CW2_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, offset.u.high_part); REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, cw2->region.base); REG_SET_2(DMCUB_REGION3_CW2_TOP_ADDRESS, 0, DMCUB_REGION3_CW2_TOP_ADDRESS, cw2->region.top, DMCUB_REGION3_CW2_ENABLE, 1); - REG_WRITE(DMCUB_REGION3_CW3_OFFSET, cw3->offset.u.low_part); - REG_WRITE(DMCUB_REGION3_CW3_OFFSET_HIGH, cw3->offset.u.high_part); + dmub_dcn20_translate_addr(&cw3->offset, fb_base, fb_offset, &offset); + + REG_WRITE(DMCUB_REGION3_CW3_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW3_OFFSET_HIGH, offset.u.high_part); REG_WRITE(DMCUB_REGION3_CW3_BASE_ADDRESS, cw3->region.base); REG_SET_2(DMCUB_REGION3_CW3_TOP_ADDRESS, 0, DMCUB_REGION3_CW3_TOP_ADDRESS, cw3->region.top, DMCUB_REGION3_CW3_ENABLE, 1); /* TODO: Move this to CW4. */ + dmub_dcn20_translate_addr(&cw4->offset, fb_base, fb_offset, &offset); - REG_WRITE(DMCUB_REGION4_OFFSET, cw4->offset.u.low_part); - REG_WRITE(DMCUB_REGION4_OFFSET_HIGH, cw4->offset.u.high_part); + 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); - REG_WRITE(DMCUB_REGION3_CW5_OFFSET, cw5->offset.u.low_part); - REG_WRITE(DMCUB_REGION3_CW5_OFFSET_HIGH, cw5->offset.u.high_part); + dmub_dcn20_translate_addr(&cw5->offset, fb_base, fb_offset, &offset); + + REG_WRITE(DMCUB_REGION3_CW5_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW5_OFFSET_HIGH, offset.u.high_part); REG_WRITE(DMCUB_REGION3_CW5_BASE_ADDRESS, cw5->region.base); REG_SET_2(DMCUB_REGION3_CW5_TOP_ADDRESS, 0, DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top, DMCUB_REGION3_CW5_ENABLE, 1); - REG_WRITE(DMCUB_REGION3_CW6_OFFSET, cw6->offset.u.low_part); - REG_WRITE(DMCUB_REGION3_CW6_OFFSET_HIGH, cw6->offset.u.high_part); + dmub_dcn20_translate_addr(&cw6->offset, fb_base, fb_offset, &offset); + + REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW6_OFFSET_HIGH, offset.u.high_part); REG_WRITE(DMCUB_REGION3_CW6_BASE_ADDRESS, cw6->region.base); REG_SET_2(DMCUB_REGION3_CW6_TOP_ADDRESS, 0, DMCUB_REGION3_CW6_TOP_ADDRESS, cw6->region.top, 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 e70a57573467..68af9b190288 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h @@ -30,6 +30,123 @@ struct dmub_srv; +/* DCN20 register definitions. */ + +#define DMUB_COMMON_REGS() \ + DMUB_SR(DMCUB_CNTL) \ + DMUB_SR(DMCUB_MEM_CNTL) \ + DMUB_SR(DMCUB_SEC_CNTL) \ + DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \ + DMUB_SR(DMCUB_INBOX1_SIZE) \ + DMUB_SR(DMCUB_INBOX1_RPTR) \ + DMUB_SR(DMCUB_INBOX1_WPTR) \ + DMUB_SR(DMCUB_REGION3_CW0_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW1_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW2_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW3_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW4_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW5_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW6_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW7_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW0_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW1_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW2_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW3_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW4_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW5_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW6_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW7_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW0_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW1_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW2_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW3_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW4_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW5_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW6_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW7_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW0_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW1_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW2_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW3_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW4_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW5_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW6_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW7_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION4_OFFSET) \ + DMUB_SR(DMCUB_REGION4_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION4_TOP_ADDRESS) \ + DMUB_SR(DMCUB_SCRATCH0) \ + DMUB_SR(DMCUB_SCRATCH1) \ + DMUB_SR(DMCUB_SCRATCH2) \ + DMUB_SR(DMCUB_SCRATCH3) \ + DMUB_SR(DMCUB_SCRATCH4) \ + DMUB_SR(DMCUB_SCRATCH5) \ + DMUB_SR(DMCUB_SCRATCH6) \ + DMUB_SR(DMCUB_SCRATCH7) \ + DMUB_SR(DMCUB_SCRATCH8) \ + DMUB_SR(DMCUB_SCRATCH9) \ + DMUB_SR(DMCUB_SCRATCH10) \ + DMUB_SR(DMCUB_SCRATCH11) \ + DMUB_SR(DMCUB_SCRATCH12) \ + DMUB_SR(DMCUB_SCRATCH13) \ + DMUB_SR(DMCUB_SCRATCH14) \ + DMUB_SR(DMCUB_SCRATCH15) \ + DMUB_SR(CC_DC_PIPE_DIS) + +#define DMUB_COMMON_FIELDS() \ + DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \ + DMUB_SF(DMCUB_CNTL, DMCUB_SOFT_RESET) \ + DMUB_SF(DMCUB_CNTL, DMCUB_TRACEPORT_EN) \ + DMUB_SF(DMCUB_MEM_CNTL, DMCUB_MEM_READ_SPACE) \ + DMUB_SF(DMCUB_MEM_CNTL, DMCUB_MEM_WRITE_SPACE) \ + DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET) \ + DMUB_SF(DMCUB_SEC_CNTL, DMCUB_MEM_UNIT_ID) \ + DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW2_TOP_ADDRESS, DMCUB_REGION3_CW2_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW2_TOP_ADDRESS, DMCUB_REGION3_CW2_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW3_TOP_ADDRESS, DMCUB_REGION3_CW3_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW3_TOP_ADDRESS, DMCUB_REGION3_CW3_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW4_TOP_ADDRESS, DMCUB_REGION3_CW4_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW4_TOP_ADDRESS, DMCUB_REGION3_CW4_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW5_TOP_ADDRESS, DMCUB_REGION3_CW5_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW5_TOP_ADDRESS, DMCUB_REGION3_CW5_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW7_TOP_ADDRESS, DMCUB_REGION3_CW7_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW7_TOP_ADDRESS, DMCUB_REGION3_CW7_ENABLE) \ + DMUB_SF(DMCUB_REGION4_TOP_ADDRESS, DMCUB_REGION4_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION4_TOP_ADDRESS, DMCUB_REGION4_ENABLE) \ + DMUB_SF(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE) + +struct dmub_srv_common_reg_offset { +#define DMUB_SR(reg) uint32_t reg; + DMUB_COMMON_REGS() +#undef DMUB_SR +}; + +struct dmub_srv_common_reg_shift { +#define DMUB_SF(reg, field) uint8_t reg##__##field; + DMUB_COMMON_FIELDS() +#undef DMUB_SF +}; + +struct dmub_srv_common_reg_mask { +#define DMUB_SF(reg, field) uint32_t reg##__##field; + DMUB_COMMON_FIELDS() +#undef DMUB_SF +}; + +struct dmub_srv_common_regs { + const struct dmub_srv_common_reg_offset offset; + const struct dmub_srv_common_reg_mask mask; + const struct dmub_srv_common_reg_shift shift; +}; + +extern const struct dmub_srv_common_regs dmub_srv_dcn20_regs; + /* Hardware functions. */ void dmub_dcn20_init(struct dmub_srv *dmub); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c index 9cea7a2d8dbf..5bed9fcd6b5c 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c @@ -25,6 +25,7 @@ #include "../inc/dmub_srv.h" #include "dmub_reg.h" +#include "dmub_dcn21.h" #include "dcn/dcn_2_1_0_offset.h" #include "dcn/dcn_2_1_0_sh_mask.h" @@ -32,103 +33,25 @@ #define BASE_INNER(seg) DMU_BASE__INST0_SEG##seg #define CTX dmub +#define REGS dmub->regs -static inline void dmub_dcn21_translate_addr(const union dmub_addr *addr_in, - uint64_t fb_base, - uint64_t fb_offset, - union dmub_addr *addr_out) -{ - addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset; -} - -void dmub_dcn21_backdoor_load(struct dmub_srv *dmub, - const struct dmub_window *cw0, - const struct dmub_window *cw1) -{ - union dmub_addr offset; - uint64_t fb_base = dmub->fb_base, fb_offset = dmub->fb_offset; - - REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1); - REG_UPDATE_2(DMCUB_MEM_CNTL, DMCUB_MEM_READ_SPACE, 0x3, - DMCUB_MEM_WRITE_SPACE, 0x3); - - dmub_dcn21_translate_addr(&cw0->offset, fb_base, fb_offset, &offset); - - REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part); - REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part); - REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base); - REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0, - DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top, - DMCUB_REGION3_CW0_ENABLE, 1); - - dmub_dcn21_translate_addr(&cw1->offset, fb_base, fb_offset, &offset); - - REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part); - REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part); - REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base); - REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0, - DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top, - DMCUB_REGION3_CW1_ENABLE, 1); - - REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID, - 0x20); -} - -void dmub_dcn21_setup_windows(struct dmub_srv *dmub, - const struct dmub_window *cw2, - const struct dmub_window *cw3, - const struct dmub_window *cw4, - const struct dmub_window *cw5, - const struct dmub_window *cw6) -{ - union dmub_addr offset; - uint64_t fb_base = dmub->fb_base, fb_offset = dmub->fb_offset; - - dmub_dcn21_translate_addr(&cw2->offset, fb_base, fb_offset, &offset); - - REG_WRITE(DMCUB_REGION3_CW2_OFFSET, offset.u.low_part); - REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, offset.u.high_part); - REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, cw2->region.base); - REG_SET_2(DMCUB_REGION3_CW2_TOP_ADDRESS, 0, - DMCUB_REGION3_CW2_TOP_ADDRESS, cw2->region.top, - DMCUB_REGION3_CW2_ENABLE, 1); +/* Registers. */ - dmub_dcn21_translate_addr(&cw3->offset, fb_base, fb_offset, &offset); +const struct dmub_srv_common_regs dmub_srv_dcn21_regs = { +#define DMUB_SR(reg) REG_OFFSET(reg), + { DMUB_COMMON_REGS() }, +#undef DMUB_SR - REG_WRITE(DMCUB_REGION3_CW3_OFFSET, offset.u.low_part); - REG_WRITE(DMCUB_REGION3_CW3_OFFSET_HIGH, offset.u.high_part); - REG_WRITE(DMCUB_REGION3_CW3_BASE_ADDRESS, cw3->region.base); - REG_SET_2(DMCUB_REGION3_CW3_TOP_ADDRESS, 0, - DMCUB_REGION3_CW3_TOP_ADDRESS, cw3->region.top, - DMCUB_REGION3_CW3_ENABLE, 1); +#define DMUB_SF(reg, field) FD_MASK(reg, field), + { DMUB_COMMON_FIELDS() }, +#undef DMUB_SF - /* TODO: Move this to CW4. */ - dmub_dcn21_translate_addr(&cw4->offset, fb_base, fb_offset, &offset); +#define DMUB_SF(reg, field) FD_SHIFT(reg, field), + { DMUB_COMMON_FIELDS() }, +#undef DMUB_SF +}; - 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_dcn21_translate_addr(&cw5->offset, fb_base, fb_offset, &offset); - - REG_WRITE(DMCUB_REGION3_CW5_OFFSET, offset.u.low_part); - REG_WRITE(DMCUB_REGION3_CW5_OFFSET_HIGH, offset.u.high_part); - REG_WRITE(DMCUB_REGION3_CW5_BASE_ADDRESS, cw5->region.base); - REG_SET_2(DMCUB_REGION3_CW5_TOP_ADDRESS, 0, - DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top, - DMCUB_REGION3_CW5_ENABLE, 1); - - dmub_dcn21_translate_addr(&cw6->offset, fb_base, fb_offset, &offset); - - REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part); - REG_WRITE(DMCUB_REGION3_CW6_OFFSET_HIGH, offset.u.high_part); - REG_WRITE(DMCUB_REGION3_CW6_BASE_ADDRESS, cw6->region.base); - REG_SET_2(DMCUB_REGION3_CW6_TOP_ADDRESS, 0, - DMCUB_REGION3_CW6_TOP_ADDRESS, cw6->region.top, - DMCUB_REGION3_CW6_ENABLE, 1); -} +/* Shared functions. */ bool dmub_dcn21_is_auto_load_done(struct dmub_srv *dmub) { diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h index f7a93a5dcfa5..2bbea237137b 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h @@ -28,18 +28,11 @@ #include "dmub_dcn20.h" -/* Hardware functions. */ +/* Registers. */ -void dmub_dcn21_backdoor_load(struct dmub_srv *dmub, - const struct dmub_window *cw0, - const struct dmub_window *cw1); +extern const struct dmub_srv_common_regs dmub_srv_dcn21_regs; -void dmub_dcn21_setup_windows(struct dmub_srv *dmub, - const struct dmub_window *cw2, - const struct dmub_window *cw3, - const struct dmub_window *cw4, - const struct dmub_window *cw5, - const struct dmub_window *cw6); +/* Hardware functions. */ bool dmub_dcn21_is_auto_load_done(struct dmub_srv *dmub); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h index bac4ee8f745f..c1f4030929a4 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h @@ -34,11 +34,15 @@ struct dmub_srv; #define BASE(seg) BASE_INNER(seg) -#define REG_OFFSET(base_index, addr) (BASE(base_index) + addr) +#define REG_OFFSET(reg_name) (BASE(mm##reg_name##_BASE_IDX) + mm##reg_name) -#define REG(reg_name) REG_OFFSET(mm ## reg_name ## _BASE_IDX, mm ## reg_name) +#define FD_SHIFT(reg_name, field) reg_name##__##field##__SHIFT -#define FD(reg_field) reg_field ## __SHIFT, reg_field ## _MASK +#define FD_MASK(reg_name, field) reg_name##__##field##_MASK + +#define REG(reg) (REGS)->offset.reg + +#define FD(reg_field) (REGS)->shift.reg_field, (REGS)->mask.reg_field #define FN(reg_name, field) FD(reg_name##__##field) 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 5f39166d3c08..9a959f871f11 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -26,7 +26,7 @@ #include "../inc/dmub_srv.h" #include "dmub_dcn20.h" #include "dmub_dcn21.h" -#include "dmub_trace_buffer.h" +#include "dmub_fw_meta.h" #include "os_types.h" /* * Note: the DMUB service is standalone. No additional headers should be @@ -46,6 +46,11 @@ /* Mailbox size */ #define DMUB_MAILBOX_SIZE (DMUB_RB_SIZE) +/* Default state size if meta is absent. */ +#define DMUB_FW_STATE_SIZE (1024) + +/* Default tracebuffer size if meta is absent. */ +#define DMUB_TRACE_BUFFER_SIZE (1024) /* Number of windows in use. */ #define DMUB_NUM_WINDOWS (DMUB_WINDOW_6_FW_STATE + 1) @@ -62,6 +67,27 @@ static inline uint32_t dmub_align(uint32_t val, uint32_t factor) return (val + factor - 1) / factor * factor; } +static const struct dmub_fw_meta_info * +dmub_get_fw_meta_info(const uint8_t *fw_bss_data, uint32_t fw_bss_data_size) +{ + const union dmub_fw_meta *meta; + + if (fw_bss_data == NULL) + return NULL; + + if (fw_bss_data_size < sizeof(union dmub_fw_meta) + DMUB_FW_META_OFFSET) + return NULL; + + meta = (const union dmub_fw_meta *)(fw_bss_data + fw_bss_data_size - + DMUB_FW_META_OFFSET - + sizeof(union dmub_fw_meta)); + + if (meta->info.magic_value != DMUB_FW_META_MAGIC) + return NULL; + + return &meta->info; +} + static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) { struct dmub_srv_hw_funcs *funcs = &dmub->hw_funcs; @@ -69,6 +95,8 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) switch (asic) { case DMUB_ASIC_DCN20: case DMUB_ASIC_DCN21: + dmub->regs = &dmub_srv_dcn20_regs; + funcs->reset = dmub_dcn20_reset; funcs->reset_release = dmub_dcn20_reset_release; funcs->backdoor_load = dmub_dcn20_backdoor_load; @@ -80,8 +108,8 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) funcs->is_hw_init = dmub_dcn20_is_hw_init; if (asic == DMUB_ASIC_DCN21) { - funcs->backdoor_load = dmub_dcn21_backdoor_load; - funcs->setup_windows = dmub_dcn21_setup_windows; + dmub->regs = &dmub_srv_dcn21_regs; + funcs->is_auto_load_done = dmub_dcn21_is_auto_load_done; funcs->is_phy_init = dmub_dcn21_is_phy_init; } @@ -160,6 +188,9 @@ dmub_srv_calc_region_info(struct dmub_srv *dmub, struct dmub_region *mail = &out->regions[DMUB_WINDOW_4_MAILBOX]; struct dmub_region *trace_buff = &out->regions[DMUB_WINDOW_5_TRACEBUFF]; struct dmub_region *fw_state = &out->regions[DMUB_WINDOW_6_FW_STATE]; + const struct dmub_fw_meta_info *fw_info; + uint32_t fw_state_size = DMUB_FW_STATE_SIZE; + uint32_t trace_buffer_size = DMUB_TRACE_BUFFER_SIZE; if (!dmub->sw_init) return DMUB_STATUS_INVALID; @@ -174,6 +205,11 @@ dmub_srv_calc_region_info(struct dmub_srv *dmub, data->base = dmub_align(inst->top, 256); data->top = data->base + params->bss_data_size; + /* + * All cache windows below should be aligned to the size + * of the DMCUB cache line, 64 bytes. + */ + stack->base = dmub_align(data->top, 256); stack->top = stack->base + DMUB_STACK_SIZE + DMUB_CONTEXT_SIZE; @@ -183,14 +219,19 @@ dmub_srv_calc_region_info(struct dmub_srv *dmub, mail->base = dmub_align(bios->top, 256); mail->top = mail->base + DMUB_MAILBOX_SIZE; + fw_info = dmub_get_fw_meta_info(params->fw_bss_data, + params->bss_data_size); + + if (fw_info) { + fw_state_size = fw_info->fw_region_size; + trace_buffer_size = fw_info->trace_buffer_size; + } + trace_buff->base = dmub_align(mail->top, 256); - trace_buff->top = trace_buff->base + TRACE_BUF_SIZE; + trace_buff->top = trace_buff->base + dmub_align(trace_buffer_size, 64); fw_state->base = dmub_align(trace_buff->top, 256); - - /* Align firmware state to size of cache line. */ - fw_state->top = - fw_state->base + dmub_align(sizeof(struct dmub_fw_state), 64); + fw_state->top = fw_state->base + dmub_align(fw_state_size, 64); out->fb_size = dmub_align(fw_state->top, 4096); |