summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dmub
diff options
context:
space:
mode:
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.h7
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c84
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h117
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c107
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.h13
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h10
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c57
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);