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/dmub_srv.h22
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h499
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd_dal.h56
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_fw_meta.h63
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h75
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_rb.h152
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_types.h75
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/Makefile3
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c34
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h2
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c195
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.h (renamed from drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd_vbios.h)37
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h2
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c55
14 files changed, 792 insertions, 478 deletions
diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
index 26d94eb5ab58..c6a8d6c54621 100644
--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
@@ -64,11 +64,7 @@
* other component within DAL.
*/
-#include "inc/dmub_types.h"
#include "inc/dmub_cmd.h"
-#include "inc/dmub_gpint_cmd.h"
-#include "inc/dmub_cmd_dal.h"
-#include "inc/dmub_rb.h"
#if defined(__cplusplus)
extern "C" {
@@ -92,6 +88,9 @@ enum dmub_asic {
DMUB_ASIC_NONE = 0,
DMUB_ASIC_DCN20,
DMUB_ASIC_DCN21,
+#ifdef CONFIG_DRM_AMD_DC_DCN3_0
+ DMUB_ASIC_DCN30,
+#endif
DMUB_ASIC_MAX,
};
@@ -257,6 +256,10 @@ struct dmub_srv_hw_funcs {
void (*set_inbox1_wptr)(struct dmub_srv *dmub, uint32_t wptr_offset);
+ uint32_t (*emul_get_inbox1_rptr)(struct dmub_srv *dmub);
+
+ void (*emul_set_inbox1_wptr)(struct dmub_srv *dmub, uint32_t wptr_offset);
+
bool (*is_supported)(struct dmub_srv *dmub);
bool (*is_hw_init)(struct dmub_srv *dmub);
@@ -280,6 +283,7 @@ struct dmub_srv_hw_funcs {
* @hw_funcs: optional overrides for hw funcs
* @user_ctx: context data for callback funcs
* @asic: driver supplied asic
+ * @fw_version: the current firmware version, if any
* @is_virtual: false for hw support only
*/
struct dmub_srv_create_params {
@@ -287,6 +291,7 @@ struct dmub_srv_create_params {
struct dmub_srv_hw_funcs *hw_funcs;
void *user_ctx;
enum dmub_asic asic;
+ uint32_t fw_version;
bool is_virtual;
};
@@ -310,12 +315,14 @@ struct dmub_srv_hw_params {
* struct dmub_srv - software state for dmcub
* @asic: dmub asic identifier
* @user_ctx: user provided context for the dmub_srv
+ * @fw_version: the current firmware version, if any
* @is_virtual: false if hardware support only
* @fw_state: dmub firmware state pointer
*/
struct dmub_srv {
enum dmub_asic asic;
void *user_ctx;
+ uint32_t fw_version;
bool is_virtual;
struct dmub_fb scratch_mem_fb;
volatile const struct dmub_fw_state *fw_state;
@@ -336,6 +343,13 @@ struct dmub_srv {
};
/**
+ * DMUB firmware version helper macro - useful for checking if the version
+ * of a firmware to know if feature or functionality is supported or present.
+ */
+#define DMUB_FW_VERSION(major, minor, revision) \
+ ((((major) & 0xFF) << 24) | (((minor) & 0xFF) << 16) | ((revision) & 0xFFFF))
+
+/**
* dmub_srv_create() - creates the DMUB service.
* @dmub: the dmub service
* @params: creation parameters for the service
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
index 599bf2055bcb..e013875b89ed 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -26,17 +26,252 @@
#ifndef _DMUB_CMD_H_
#define _DMUB_CMD_H_
-#include "dmub_types.h"
-#include "dmub_cmd_dal.h"
-#include "dmub_cmd_vbios.h"
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <stdarg.h>
+
#include "atomfirmware.h"
+/* Firmware versioning. */
+#ifdef DMUB_EXPOSE_VERSION
+#define DMUB_FW_VERSION_GIT_HASH 0xe6d590b09
+#define DMUB_FW_VERSION_MAJOR 0
+#define DMUB_FW_VERSION_MINOR 0
+#define DMUB_FW_VERSION_REVISION 25
+#define DMUB_FW_VERSION_UCODE ((DMUB_FW_VERSION_MAJOR << 24) | (DMUB_FW_VERSION_MINOR << 16) | DMUB_FW_VERSION_REVISION)
+#endif
+
+//<DMUB_TYPES>==================================================================
+/* Basic type definitions. */
+
+#define SET_ABM_PIPE_GRADUALLY_DISABLE 0
+#define SET_ABM_PIPE_IMMEDIATELY_DISABLE 255
+#define SET_ABM_PIPE_NORMAL 1
+
+/* Maximum number of streams on any ASIC. */
+#define DMUB_MAX_STREAMS 6
+
+/* Maximum number of planes on any ASIC. */
+#define DMUB_MAX_PLANES 6
+
+#ifndef PHYSICAL_ADDRESS_LOC
+#define PHYSICAL_ADDRESS_LOC union large_integer
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef dmub_memcpy
+#define dmub_memcpy(dest, source, bytes) memcpy((dest), (source), (bytes))
+#endif
+
+#ifndef dmub_memset
+#define dmub_memset(dest, val, bytes) memset((dest), (val), (bytes))
+#endif
+
+#ifndef dmub_udelay
+#define dmub_udelay(microseconds) udelay(microseconds)
+#endif
+
+union dmub_addr {
+ struct {
+ uint32_t low_part;
+ uint32_t high_part;
+ } u;
+ uint64_t quad_part;
+};
+
+union dmub_psr_debug_flags {
+ struct {
+ uint32_t visual_confirm : 1;
+ uint32_t use_hw_lock_mgr : 1;
+ } bitfields;
+
+ uint32_t u32All;
+};
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+
+//==============================================================================
+//</DMUB_TYPES>=================================================================
+//==============================================================================
+//< DMUB_META>==================================================================
+//==============================================================================
+#pragma pack(push, 1)
+
+/* Magic value for identifying dmub_fw_meta_info */
+#define DMUB_FW_META_MAGIC 0x444D5542
+
+/* Offset from the end of the file to the dmub_fw_meta_info */
+#define DMUB_FW_META_OFFSET 0x24
+
+/**
+ * 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
+ * @fw_version: the firmware version information
+ * @dal_fw: 1 if the firmware is DAL
+ */
+struct dmub_fw_meta_info {
+ uint32_t magic_value;
+ uint32_t fw_region_size;
+ uint32_t trace_buffer_size;
+ uint32_t fw_version;
+ uint8_t dal_fw;
+ uint8_t reserved[3];
+};
+
+/* Ensure that the structure remains 64 bytes. */
+union dmub_fw_meta {
+ struct dmub_fw_meta_info info;
+ uint8_t reserved[64];
+};
+
+#pragma pack(pop)
+
+//==============================================================================
+//< DMUB_STATUS>================================================================
+//==============================================================================
+
+/**
+ * DMCUB scratch registers can be used to determine firmware status.
+ * Current scratch register usage is as follows:
+ *
+ * SCRATCH0: FW Boot Status register
+ * SCRATCH15: FW Boot Options register
+ */
+
+/* Register bit definition for SCRATCH0 */
+union dmub_fw_boot_status {
+ struct {
+ uint32_t dal_fw : 1;
+ uint32_t mailbox_rdy : 1;
+ uint32_t optimized_init_done : 1;
+ uint32_t reserved : 29;
+ } bits;
+ uint32_t all;
+};
+
+enum dmub_fw_boot_status_bit {
+ DMUB_FW_BOOT_STATUS_BIT_DAL_FIRMWARE = (1 << 0),
+ DMUB_FW_BOOT_STATUS_BIT_MAILBOX_READY = (1 << 1),
+ DMUB_FW_BOOT_STATUS_BIT_OPTIMIZED_INIT_DONE = (1 << 2),
+};
+
+/* Register bit definition for SCRATCH15 */
+union dmub_fw_boot_options {
+ struct {
+ uint32_t pemu_env : 1;
+ uint32_t fpga_env : 1;
+ uint32_t optimized_init : 1;
+ uint32_t reserved : 29;
+ } bits;
+ uint32_t all;
+};
+
+enum dmub_fw_boot_options_bit {
+ DMUB_FW_BOOT_OPTION_BIT_PEMU_ENV = (1 << 0),
+ DMUB_FW_BOOT_OPTION_BIT_FPGA_ENV = (1 << 1),
+ DMUB_FW_BOOT_OPTION_BIT_OPTIMIZED_INIT_DONE = (1 << 2),
+};
+
+//==============================================================================
+//</DMUB_STATUS>================================================================
+//==============================================================================
+//< DMUB_VBIOS>=================================================================
+//==============================================================================
+
+/*
+ * Command IDs should be treated as stable ABI.
+ * Do not reuse or modify IDs.
+ */
+
+enum dmub_cmd_vbios_type {
+ DMUB_CMD__VBIOS_DIGX_ENCODER_CONTROL = 0,
+ DMUB_CMD__VBIOS_DIG1_TRANSMITTER_CONTROL = 1,
+ DMUB_CMD__VBIOS_SET_PIXEL_CLOCK = 2,
+ DMUB_CMD__VBIOS_ENABLE_DISP_POWER_GATING = 3,
+};
+
+//==============================================================================
+//</DMUB_VBIOS>=================================================================
+//==============================================================================
+//< DMUB_GPINT>=================================================================
+//==============================================================================
+
+/**
+ * The shifts and masks below may alternatively be used to format and read
+ * the command register bits.
+ */
+
+#define DMUB_GPINT_DATA_PARAM_MASK 0xFFFF
+#define DMUB_GPINT_DATA_PARAM_SHIFT 0
+
+#define DMUB_GPINT_DATA_COMMAND_CODE_MASK 0xFFF
+#define DMUB_GPINT_DATA_COMMAND_CODE_SHIFT 16
+
+#define DMUB_GPINT_DATA_STATUS_MASK 0xF
+#define DMUB_GPINT_DATA_STATUS_SHIFT 28
+
+/**
+ * Command responses.
+ */
+
+#define DMUB_GPINT__STOP_FW_RESPONSE 0xDEADDEAD
+
+/**
+ * The register format for sending a command via the GPINT.
+ */
+union dmub_gpint_data_register {
+ struct {
+ uint32_t param : 16;
+ uint32_t command_code : 12;
+ uint32_t status : 4;
+ } bits;
+ uint32_t all;
+};
+
+/*
+ * Command IDs should be treated as stable ABI.
+ * Do not reuse or modify IDs.
+ */
+
+enum dmub_gpint_command {
+ DMUB_GPINT__INVALID_COMMAND = 0,
+ DMUB_GPINT__GET_FW_VERSION = 1,
+ DMUB_GPINT__STOP_FW = 2,
+ DMUB_GPINT__GET_PSR_STATE = 7,
+ /**
+ * DESC: Notifies DMCUB of the currently active streams.
+ * ARGS: Stream mask, 1 bit per active stream index.
+ */
+ DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK = 8,
+};
+
+//==============================================================================
+//</DMUB_GPINT>=================================================================
+//==============================================================================
+//< DMUB_CMD>===================================================================
+//==============================================================================
+
#define DMUB_RB_CMD_SIZE 64
#define DMUB_RB_MAX_ENTRY 128
#define DMUB_RB_SIZE (DMUB_RB_CMD_SIZE * DMUB_RB_MAX_ENTRY)
#define REG_SET_MASK 0xFFFF
-
/*
* Command IDs should be treated as stable ABI.
* Do not reuse or modify IDs.
@@ -51,6 +286,7 @@ enum dmub_cmd_type {
DMUB_CMD__PLAT_54186_WA = 5,
DMUB_CMD__PSR = 64,
DMUB_CMD__ABM = 66,
+ DMUB_CMD__HW_LOCK = 69,
DMUB_CMD__VBIOS = 128,
};
@@ -106,14 +342,12 @@ struct dmub_cmd_reg_field_update_sequence {
};
#define DMUB_REG_FIELD_UPDATE_SEQ__MAX 7
-
struct dmub_rb_cmd_reg_field_update_sequence {
struct dmub_cmd_header header;
uint32_t addr;
struct dmub_cmd_reg_field_update_sequence seq[DMUB_REG_FIELD_UPDATE_SEQ__MAX];
};
-
/*
* Burst write
*
@@ -148,10 +382,6 @@ struct dmub_rb_cmd_reg_wait {
struct dmub_cmd_reg_wait_data reg_wait;
};
-#ifndef PHYSICAL_ADDRESS_LOC
-#define PHYSICAL_ADDRESS_LOC union large_integer
-#endif
-
struct dmub_cmd_PLAT_54186_wa {
uint32_t DCSURF_SURFACE_CONTROL;
uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH;
@@ -215,7 +445,26 @@ struct dmub_rb_cmd_dpphy_init {
uint8_t reserved[60];
};
+/*
+ * Command IDs should be treated as stable ABI.
+ * Do not reuse or modify IDs.
+ */
+
+enum dmub_cmd_psr_type {
+ DMUB_CMD__PSR_SET_VERSION = 0,
+ DMUB_CMD__PSR_COPY_SETTINGS = 1,
+ DMUB_CMD__PSR_ENABLE = 2,
+ DMUB_CMD__PSR_DISABLE = 3,
+ DMUB_CMD__PSR_SET_LEVEL = 4,
+};
+
+enum psr_version {
+ PSR_VERSION_1 = 0,
+ PSR_VERSION_UNSUPPORTED = 0xFFFFFFFF,
+};
+
struct dmub_cmd_psr_copy_settings_data {
+ union dmub_psr_debug_flags debug;
uint16_t psr_level;
uint8_t dpp_inst;
uint8_t mpcc_inst;
@@ -228,7 +477,9 @@ struct dmub_cmd_psr_copy_settings_data {
uint8_t smu_optimizations_en;
uint8_t frame_delay;
uint8_t frame_cap_ind;
- struct dmub_psr_debug_flags debug;
+ uint8_t pad[3];
+ uint16_t init_sdp_deadline;
+ uint16_t pad2;
};
struct dmub_rb_cmd_psr_copy_settings {
@@ -238,6 +489,7 @@ struct dmub_rb_cmd_psr_copy_settings {
struct dmub_cmd_psr_set_level_data {
uint16_t psr_level;
+ uint8_t pad[2];
};
struct dmub_rb_cmd_psr_set_level {
@@ -258,11 +510,93 @@ struct dmub_rb_cmd_psr_set_version {
struct dmub_cmd_psr_set_version_data psr_set_version_data;
};
+union dmub_hw_lock_flags {
+ struct {
+ uint8_t lock_pipe : 1;
+ uint8_t lock_cursor : 1;
+ uint8_t lock_dig : 1;
+ uint8_t triple_buffer_lock : 1;
+ } bits;
+
+ uint8_t u8All;
+};
+
+struct dmub_hw_lock_inst_flags {
+ uint8_t otg_inst;
+ uint8_t opp_inst;
+ uint8_t dig_inst;
+ uint8_t pad;
+};
+
+enum hw_lock_client {
+ HW_LOCK_CLIENT_DRIVER = 0,
+ HW_LOCK_CLIENT_FW,
+ HW_LOCK_CLIENT_INVALID = 0xFFFFFFFF,
+};
+
+struct dmub_cmd_lock_hw_data {
+ enum hw_lock_client client;
+ struct dmub_hw_lock_inst_flags inst_flags;
+ union dmub_hw_lock_flags hw_locks;
+ uint8_t lock;
+ uint8_t should_release;
+ uint8_t pad;
+};
+
+struct dmub_rb_cmd_lock_hw {
+ struct dmub_cmd_header header;
+ struct dmub_cmd_lock_hw_data lock_hw_data;
+};
+
+enum dmub_cmd_abm_type {
+ DMUB_CMD__ABM_INIT_CONFIG = 0,
+ DMUB_CMD__ABM_SET_PIPE = 1,
+ DMUB_CMD__ABM_SET_BACKLIGHT = 2,
+ DMUB_CMD__ABM_SET_LEVEL = 3,
+ DMUB_CMD__ABM_SET_AMBIENT_LEVEL = 4,
+ DMUB_CMD__ABM_SET_PWM_FRAC = 5,
+};
+
+#define NUM_AMBI_LEVEL 5
+#define NUM_AGGR_LEVEL 4
+#define NUM_POWER_FN_SEGS 8
+#define NUM_BL_CURVE_SEGS 16
+
+/*
+ * Parameters for ABM2.4 algorithm.
+ * Padded explicitly to 32-bit boundary.
+ */
+struct abm_config_table {
+ /* Parameters for crgb conversion */
+ uint16_t crgb_thresh[NUM_POWER_FN_SEGS]; // 0B
+ uint16_t crgb_offset[NUM_POWER_FN_SEGS]; // 15B
+ uint16_t crgb_slope[NUM_POWER_FN_SEGS]; // 31B
+
+ /* Parameters for custom curve */
+ uint16_t backlight_thresholds[NUM_BL_CURVE_SEGS]; // 47B
+ uint16_t backlight_offsets[NUM_BL_CURVE_SEGS]; // 79B
+
+ uint16_t ambient_thresholds_lux[NUM_AMBI_LEVEL]; // 111B
+ uint16_t min_abm_backlight; // 121B
+
+ uint8_t min_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; // 123B
+ uint8_t max_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; // 143B
+ uint8_t bright_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; // 163B
+ uint8_t dark_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; // 183B
+ uint8_t hybrid_factor[NUM_AGGR_LEVEL]; // 203B
+ uint8_t contrast_factor[NUM_AGGR_LEVEL]; // 207B
+ uint8_t deviation_gain[NUM_AGGR_LEVEL]; // 211B
+ uint8_t min_knee[NUM_AGGR_LEVEL]; // 215B
+ uint8_t max_knee[NUM_AGGR_LEVEL]; // 219B
+ uint8_t iir_curve[NUM_AMBI_LEVEL]; // 223B
+ uint8_t pad3[3]; // 228B
+};
+
struct dmub_cmd_abm_set_pipe_data {
- uint32_t ramping_boundary;
- uint32_t otg_inst;
- uint32_t panel_inst;
- uint32_t set_pipe_option;
+ uint8_t otg_inst;
+ uint8_t panel_inst;
+ uint8_t set_pipe_option;
+ uint8_t ramping_boundary; // TODO: Remove this
};
struct dmub_rb_cmd_abm_set_pipe {
@@ -272,6 +606,7 @@ struct dmub_rb_cmd_abm_set_pipe {
struct dmub_cmd_abm_set_backlight_data {
uint32_t frame_ramp;
+ uint32_t backlight_user_level;
};
struct dmub_rb_cmd_abm_set_backlight {
@@ -317,6 +652,7 @@ struct dmub_rb_cmd_abm_init_config {
};
union dmub_rb_cmd {
+ struct dmub_rb_cmd_lock_hw lock_hw;
struct dmub_rb_cmd_read_modify_write read_modify_write;
struct dmub_rb_cmd_reg_field_update_sequence reg_field_update_seq;
struct dmub_rb_cmd_burst_write burst_write;
@@ -342,4 +678,137 @@ union dmub_rb_cmd {
#pragma pack(pop)
+
+//==============================================================================
+//</DMUB_CMD>===================================================================
+//==============================================================================
+//< DMUB_RB>====================================================================
+//==============================================================================
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct dmub_rb_init_params {
+ void *ctx;
+ void *base_address;
+ uint32_t capacity;
+ uint32_t read_ptr;
+ uint32_t write_ptr;
+};
+
+struct dmub_rb {
+ void *base_address;
+ uint32_t data_count;
+ uint32_t rptr;
+ uint32_t wrpt;
+ uint32_t capacity;
+
+ void *ctx;
+ void *dmub;
+};
+
+
+static inline bool dmub_rb_empty(struct dmub_rb *rb)
+{
+ return (rb->wrpt == rb->rptr);
+}
+
+static inline bool dmub_rb_full(struct dmub_rb *rb)
+{
+ uint32_t data_count;
+
+ if (rb->wrpt >= rb->rptr)
+ data_count = rb->wrpt - rb->rptr;
+ else
+ data_count = rb->capacity - (rb->rptr - rb->wrpt);
+
+ return (data_count == (rb->capacity - DMUB_RB_CMD_SIZE));
+}
+
+static inline bool dmub_rb_push_front(struct dmub_rb *rb,
+ const union dmub_rb_cmd *cmd)
+{
+ uint64_t volatile *dst = (uint64_t volatile *)(rb->base_address) + rb->wrpt / sizeof(uint64_t);
+ const uint64_t *src = (const uint64_t *)cmd;
+ int i;
+
+ if (dmub_rb_full(rb))
+ return false;
+
+ // copying data
+ for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++)
+ *dst++ = *src++;
+
+ rb->wrpt += DMUB_RB_CMD_SIZE;
+
+ if (rb->wrpt >= rb->capacity)
+ rb->wrpt %= rb->capacity;
+
+ return true;
+}
+
+static inline bool dmub_rb_front(struct dmub_rb *rb,
+ union dmub_rb_cmd *cmd)
+{
+ uint8_t *rd_ptr = (uint8_t *)rb->base_address + rb->rptr;
+
+ if (dmub_rb_empty(rb))
+ return false;
+
+ dmub_memcpy(cmd, rd_ptr, DMUB_RB_CMD_SIZE);
+
+ return true;
+}
+
+static inline bool dmub_rb_pop_front(struct dmub_rb *rb)
+{
+ if (dmub_rb_empty(rb))
+ return false;
+
+ rb->rptr += DMUB_RB_CMD_SIZE;
+
+ if (rb->rptr >= rb->capacity)
+ rb->rptr %= rb->capacity;
+
+ return true;
+}
+
+static inline void dmub_rb_flush_pending(const struct dmub_rb *rb)
+{
+ uint32_t rptr = rb->rptr;
+ uint32_t wptr = rb->wrpt;
+
+ while (rptr != wptr) {
+ uint64_t volatile *data = (uint64_t volatile *)rb->base_address + rptr / sizeof(uint64_t);
+ //uint64_t volatile *p = (uint64_t volatile *)data;
+ uint64_t temp;
+ int i;
+
+ for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++)
+ temp = *data++;
+
+ rptr += DMUB_RB_CMD_SIZE;
+ if (rptr >= rb->capacity)
+ rptr %= rb->capacity;
+ }
+}
+
+static inline void dmub_rb_init(struct dmub_rb *rb,
+ struct dmub_rb_init_params *init_params)
+{
+ rb->base_address = init_params->base_address;
+ rb->capacity = init_params->capacity;
+ rb->rptr = init_params->read_ptr;
+ rb->wrpt = init_params->write_ptr;
+}
+
+#if defined(__cplusplus)
+}
+#endif
+
+//==============================================================================
+//</DMUB_RB>====================================================================
+//==============================================================================
+
#endif /* _DMUB_CMD_H_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd_dal.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd_dal.h
deleted file mode 100644
index e42de9ded275..000000000000
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd_dal.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2019 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#ifndef _DMUB_CMD_DAL_H_
-#define _DMUB_CMD_DAL_H_
-
-/*
- * Command IDs should be treated as stable ABI.
- * Do not reuse or modify IDs.
- */
-
-enum dmub_cmd_psr_type {
- DMUB_CMD__PSR_SET_VERSION = 0,
- DMUB_CMD__PSR_COPY_SETTINGS = 1,
- DMUB_CMD__PSR_ENABLE = 2,
- DMUB_CMD__PSR_DISABLE = 3,
- DMUB_CMD__PSR_SET_LEVEL = 4,
-};
-
-enum psr_version {
- PSR_VERSION_1 = 0,
- PSR_VERSION_UNSUPPORTED = 0xFFFFFFFF,
-};
-
-enum dmub_cmd_abm_type {
- DMUB_CMD__ABM_INIT_CONFIG = 0,
- DMUB_CMD__ABM_SET_PIPE = 1,
- DMUB_CMD__ABM_SET_BACKLIGHT = 2,
- DMUB_CMD__ABM_SET_LEVEL = 3,
- DMUB_CMD__ABM_SET_AMBIENT_LEVEL = 4,
- DMUB_CMD__ABM_SET_PWM_FRAC = 5,
-};
-
-#endif /* _DMUB_CMD_DAL_H_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_fw_meta.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_fw_meta.h
deleted file mode 100644
index 242ec257998c..000000000000
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_fw_meta.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2019 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-#ifndef _DMUB_META_H_
-#define _DMUB_META_H_
-
-#include "dmub_types.h"
-
-#pragma pack(push, 1)
-
-/* Magic value for identifying dmub_fw_meta_info */
-#define DMUB_FW_META_MAGIC 0x444D5542
-
-/* Offset from the end of the file to the dmub_fw_meta_info */
-#define DMUB_FW_META_OFFSET 0x24
-
-/**
- * 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;
-};
-
-/* 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_META_H_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h
deleted file mode 100644
index 652d6fc061b6..000000000000
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2019 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#ifndef _DMUB_GPINT_CMD_H_
-#define _DMUB_GPINT_CMD_H_
-
-#include "dmub_types.h"
-
-/**
- * The register format for sending a command via the GPINT.
- */
-union dmub_gpint_data_register {
- struct {
- uint32_t param : 16;
- uint32_t command_code : 12;
- uint32_t status : 4;
- } bits;
- uint32_t all;
-};
-
-/**
- * The shifts and masks below may alternatively be used to format and read
- * the command register bits.
- */
-
-#define DMUB_GPINT_DATA_PARAM_MASK 0xFFFF
-#define DMUB_GPINT_DATA_PARAM_SHIFT 0
-
-#define DMUB_GPINT_DATA_COMMAND_CODE_MASK 0xFFF
-#define DMUB_GPINT_DATA_COMMAND_CODE_SHIFT 16
-
-#define DMUB_GPINT_DATA_STATUS_MASK 0xF
-#define DMUB_GPINT_DATA_STATUS_SHIFT 28
-
-/*
- * Command IDs should be treated as stable ABI.
- * Do not reuse or modify IDs.
- */
-
-enum dmub_gpint_command {
- DMUB_GPINT__INVALID_COMMAND = 0,
- DMUB_GPINT__GET_FW_VERSION = 1,
- DMUB_GPINT__STOP_FW = 2,
- DMUB_GPINT__GET_PSR_STATE = 7,
-};
-
-/**
- * Command responses.
- */
-
-#define DMUB_GPINT__STOP_FW_RESPONSE 0xDEADDEAD
-
-#endif /* _DMUB_GPINT_CMD_H_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_rb.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_rb.h
deleted file mode 100644
index 2ae48c18bb5b..000000000000
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_rb.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright 2019 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#ifndef _DMUB_RB_H_
-#define _DMUB_RB_H_
-
-#include "dmub_types.h"
-#include "dmub_cmd.h"
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-struct dmub_rb_init_params {
- void *ctx;
- void *base_address;
- uint32_t capacity;
-};
-
-struct dmub_rb {
- void *base_address;
- uint32_t data_count;
- uint32_t rptr;
- uint32_t wrpt;
- uint32_t capacity;
-
- void *ctx;
- void *dmub;
-};
-
-
-static inline bool dmub_rb_empty(struct dmub_rb *rb)
-{
- return (rb->wrpt == rb->rptr);
-}
-
-static inline bool dmub_rb_full(struct dmub_rb *rb)
-{
- uint32_t data_count;
-
- if (rb->wrpt >= rb->rptr)
- data_count = rb->wrpt - rb->rptr;
- else
- data_count = rb->capacity - (rb->rptr - rb->wrpt);
-
- return (data_count == (rb->capacity - DMUB_RB_CMD_SIZE));
-}
-
-static inline bool dmub_rb_push_front(struct dmub_rb *rb,
- const union dmub_rb_cmd *cmd)
-{
- uint64_t volatile *dst = (uint64_t volatile *)(rb->base_address) + rb->wrpt / sizeof(uint64_t);
- const uint64_t *src = (const uint64_t *)cmd;
- int i;
-
- if (dmub_rb_full(rb))
- return false;
-
- // copying data
- for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++)
- *dst++ = *src++;
-
- rb->wrpt += DMUB_RB_CMD_SIZE;
-
- if (rb->wrpt >= rb->capacity)
- rb->wrpt %= rb->capacity;
-
- return true;
-}
-
-static inline bool dmub_rb_front(struct dmub_rb *rb,
- union dmub_rb_cmd *cmd)
-{
- uint8_t *rd_ptr = (uint8_t *)rb->base_address + rb->rptr;
-
- if (dmub_rb_empty(rb))
- return false;
-
- dmub_memcpy(cmd, rd_ptr, DMUB_RB_CMD_SIZE);
-
- return true;
-}
-
-static inline bool dmub_rb_pop_front(struct dmub_rb *rb)
-{
- if (dmub_rb_empty(rb))
- return false;
-
- rb->rptr += DMUB_RB_CMD_SIZE;
-
- if (rb->rptr >= rb->capacity)
- rb->rptr %= rb->capacity;
-
- return true;
-}
-
-static inline void dmub_rb_flush_pending(const struct dmub_rb *rb)
-{
- uint32_t rptr = rb->rptr;
- uint32_t wptr = rb->wrpt;
-
- while (rptr != wptr) {
- uint64_t volatile *data = (uint64_t volatile *)rb->base_address + rptr / sizeof(uint64_t);
- //uint64_t volatile *p = (uint64_t volatile *)data;
- uint64_t temp;
- int i;
-
- for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++)
- temp = *data++;
-
- rptr += DMUB_RB_CMD_SIZE;
- if (rptr >= rb->capacity)
- rptr %= rb->capacity;
- }
-}
-
-static inline void dmub_rb_init(struct dmub_rb *rb,
- struct dmub_rb_init_params *init_params)
-{
- rb->base_address = init_params->base_address;
- rb->capacity = init_params->capacity;
- rb->rptr = 0;
- rb->wrpt = 0;
-}
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* _DMUB_RB_H_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_types.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_types.h
deleted file mode 100644
index bed5b023a396..000000000000
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_types.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2019 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#ifndef _DMUB_TYPES_H_
-#define _DMUB_TYPES_H_
-
-/* Basic type definitions. */
-#include <asm/byteorder.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <stdarg.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#ifndef dmub_memcpy
-#define dmub_memcpy(dest, source, bytes) memcpy((dest), (source), (bytes))
-#endif
-
-#ifndef dmub_memset
-#define dmub_memset(dest, val, bytes) memset((dest), (val), (bytes))
-#endif
-
-#ifndef dmub_udelay
-#define dmub_udelay(microseconds) udelay(microseconds)
-#endif
-
-/* Maximum number of streams on any ASIC. */
-#define DMUB_MAX_STREAMS 6
-
-/* Maximum number of planes on any ASIC. */
-#define DMUB_MAX_PLANES 6
-
-union dmub_addr {
- struct {
- uint32_t low_part;
- uint32_t high_part;
- } u;
- uint64_t quad_part;
-};
-
-struct dmub_psr_debug_flags {
- uint8_t visual_confirm : 1;
- uint8_t reserved : 7;
-};
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* _DMUB_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/src/Makefile b/drivers/gpu/drm/amd/display/dmub/src/Makefile
index e08dfeea24b0..bb584f39cad0 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/Makefile
+++ b/drivers/gpu/drm/amd/display/dmub/src/Makefile
@@ -21,6 +21,9 @@
#
DMUB = dmub_srv.o dmub_reg.o dmub_dcn20.o dmub_dcn21.o
+ifdef CONFIG_DRM_AMD_DC_DCN3_0
+DMUB += dmub_dcn30.o
+endif
AMD_DAL_DMUB = $(addprefix $(AMDDALPATH)/dmub/src/,$(DMUB))
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..2c4a2fe9311d 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
@@ -215,11 +215,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->fw_version > DMUB_FW_VERSION(1, 0, 10)) {
+ 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);
@@ -243,9 +254,12 @@ 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->fw_version > DMUB_FW_VERSION(1, 0, 10))
+ 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);
}
@@ -261,7 +275,11 @@ void dmub_dcn20_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_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)
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 7f046c73927e..a316f260f6ac 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
@@ -26,7 +26,7 @@
#ifndef _DMUB_DCN20_H_
#define _DMUB_DCN20_H_
-#include "../inc/dmub_types.h"
+#include "../inc/dmub_cmd.h"
struct dmub_srv;
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
new file mode 100644
index 000000000000..215178b8d415
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "../dmub_srv.h"
+#include "dmub_reg.h"
+#include "dmub_dcn20.h"
+
+#include "sienna_cichlid_ip_offset.h"
+#include "dcn/dcn_3_0_0_offset.h"
+#include "dcn/dcn_3_0_0_sh_mask.h"
+
+#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_dcn30_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 void dmub_dcn30_get_fb_base_offset(struct dmub_srv *dmub,
+ uint64_t *fb_base,
+ uint64_t *fb_offset)
+{
+ uint32_t tmp;
+
+ if (dmub->fb_base || dmub->fb_offset) {
+ *fb_base = dmub->fb_base;
+ *fb_offset = dmub->fb_offset;
+ return;
+ }
+
+ REG_GET(DCN_VM_FB_LOCATION_BASE, FB_BASE, &tmp);
+ *fb_base = (uint64_t)tmp << 24;
+
+ REG_GET(DCN_VM_FB_OFFSET, FB_OFFSET, &tmp);
+ *fb_offset = (uint64_t)tmp << 24;
+}
+
+static inline void dmub_dcn30_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_dcn30_backdoor_load(struct dmub_srv *dmub,
+ const struct dmub_window *cw0,
+ const struct dmub_window *cw1)
+{
+ union dmub_addr offset;
+ uint64_t fb_base, fb_offset;
+
+ dmub_dcn30_get_fb_base_offset(dmub, &fb_base, &fb_offset);
+
+ REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1);
+
+ /* MEM_CTNL read/write space doesn't exist. */
+
+ dmub_dcn30_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_dcn30_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_dcn30_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;
+
+ /* sienna_cichlid has hardwired virtual addressing for CW2-CW7 */
+
+ offset = cw2->offset;
+
+ if (cw2->region.base != cw2->region.top) {
+ 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);
+ } else {
+ REG_WRITE(DMCUB_REGION3_CW2_OFFSET, 0);
+ REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, 0);
+ REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, 0);
+ REG_WRITE(DMCUB_REGION3_CW2_TOP_ADDRESS, 0);
+ }
+
+ offset = cw3->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);
+
+ offset = cw4->offset;
+
+ /* New firmware can support CW4. */
+ if (dmub->fw_version > DMUB_FW_VERSION(1, 0, 10)) {
+ 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);
+ }
+
+ offset = cw5->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);
+
+ offset = cw6->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);
+}
+
+bool dmub_dcn30_is_auto_load_done(struct dmub_srv *dmub)
+{
+ return (REG_READ(DMCUB_SCRATCH0) > 0);
+}
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd_vbios.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.h
index b6deb8e2590f..4d8f52b8f12c 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd_vbios.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 Advanced Micro Devices, Inc.
+ * Copyright 2020 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -23,19 +23,28 @@
*
*/
-#ifndef _DMUB_CMD_VBIOS_H_
-#define _DMUB_CMD_VBIOS_H_
+#ifndef _DMUB_DCN30_H_
+#define _DMUB_DCN30_H_
-/*
- * Command IDs should be treated as stable ABI.
- * Do not reuse or modify IDs.
- */
+#include "dmub_dcn20.h"
+
+/* Registers. */
+
+extern const struct dmub_srv_common_regs dmub_srv_dcn30_regs;
+
+/* Hardware functions. */
+
+void dmub_dcn30_backdoor_load(struct dmub_srv *dmub,
+ const struct dmub_window *cw0,
+ const struct dmub_window *cw1);
+
+void dmub_dcn30_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);
-enum dmub_cmd_vbios_type {
- DMUB_CMD__VBIOS_DIGX_ENCODER_CONTROL = 0,
- DMUB_CMD__VBIOS_DIG1_TRANSMITTER_CONTROL = 1,
- DMUB_CMD__VBIOS_SET_PIXEL_CLOCK = 2,
- DMUB_CMD__VBIOS_ENABLE_DISP_POWER_GATING = 3,
-};
+bool dmub_dcn30_is_auto_load_done(struct dmub_srv *dmub);
-#endif /* _DMUB_CMD_VBIOS_H_ */
+#endif /* _DMUB_DCN30_H_ */
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 c1f4030929a4..96603d07c23d 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h
@@ -26,7 +26,7 @@
#ifndef _DMUB_REG_H_
#define _DMUB_REG_H_
-#include "../inc/dmub_types.h"
+#include "../inc/dmub_cmd.h"
struct dmub_srv;
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 0e3751d94cb0..08da423b24a1 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,10 @@
#include "../dmub_srv.h"
#include "dmub_dcn20.h"
#include "dmub_dcn21.h"
-#include "dmub_fw_meta.h"
+#include "dmub_cmd.h"
+#ifdef CONFIG_DRM_AMD_DC_DCN3_0
+#include "dmub_dcn30.h"
+#endif
#include "os_types.h"
/*
* Note: the DMUB service is standalone. No additional headers should be
@@ -47,10 +50,10 @@
#define DMUB_MAILBOX_SIZE (DMUB_RB_SIZE)
/* Default state size if meta is absent. */
-#define DMUB_FW_STATE_SIZE (1024)
+#define DMUB_FW_STATE_SIZE (64 * 1024)
/* Default tracebuffer size if meta is absent. */
-#define DMUB_TRACE_BUFFER_SIZE (1024)
+#define DMUB_TRACE_BUFFER_SIZE (64 * 1024)
/* Default scratch mem size. */
#define DMUB_SCRATCH_MEM_SIZE (256)
@@ -62,6 +65,7 @@
#define DMUB_CW0_BASE (0x60000000)
#define DMUB_CW1_BASE (0x61000000)
#define DMUB_CW3_BASE (0x63000000)
+#define DMUB_CW4_BASE (0x64000000)
#define DMUB_CW5_BASE (0x65000000)
#define DMUB_CW6_BASE (0x66000000)
@@ -98,12 +102,12 @@ dmub_get_fw_meta_info(const struct dmub_srv_region_params *params)
uint32_t blob_size = 0;
uint32_t meta_offset = 0;
- if (params->fw_bss_data) {
+ if (params->fw_bss_data && params->bss_data_size) {
/* Legacy metadata region. */
blob = params->fw_bss_data;
blob_size = params->bss_data_size;
meta_offset = DMUB_FW_META_OFFSET;
- } else if (params->fw_inst_const) {
+ } else if (params->fw_inst_const && params->inst_const_size) {
/* Combined metadata region. */
blob = params->fw_inst_const;
blob_size = params->inst_const_size;
@@ -132,6 +136,9 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
switch (asic) {
case DMUB_ASIC_DCN20:
case DMUB_ASIC_DCN21:
+#ifdef CONFIG_DRM_AMD_DC_DCN3_0
+ case DMUB_ASIC_DCN30:
+#endif
dmub->regs = &dmub_srv_dcn20_regs;
funcs->reset = dmub_dcn20_reset;
@@ -153,6 +160,15 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
funcs->is_auto_load_done = dmub_dcn21_is_auto_load_done;
funcs->is_phy_init = dmub_dcn21_is_phy_init;
}
+#ifdef CONFIG_DRM_AMD_DC_DCN3_0
+ if (asic == DMUB_ASIC_DCN30) {
+ dmub->regs = &dmub_srv_dcn30_regs;
+
+ funcs->is_auto_load_done = dmub_dcn30_is_auto_load_done;
+ funcs->backdoor_load = dmub_dcn30_backdoor_load;
+ funcs->setup_windows = dmub_dcn30_setup_windows;
+ }
+#endif
break;
default:
@@ -172,6 +188,7 @@ enum dmub_status dmub_srv_create(struct dmub_srv *dmub,
dmub->funcs = params->funcs;
dmub->user_ctx = params->user_ctx;
dmub->asic = params->asic;
+ dmub->fw_version = params->fw_version;
dmub->is_virtual = params->is_virtual;
/* Setup asic dependent hardware funcs. */
@@ -182,13 +199,13 @@ enum dmub_status dmub_srv_create(struct dmub_srv *dmub,
/* Override (some) hardware funcs based on user params. */
if (params->hw_funcs) {
- if (params->hw_funcs->get_inbox1_rptr)
- dmub->hw_funcs.get_inbox1_rptr =
- params->hw_funcs->get_inbox1_rptr;
+ if (params->hw_funcs->emul_get_inbox1_rptr)
+ dmub->hw_funcs.emul_get_inbox1_rptr =
+ params->hw_funcs->emul_get_inbox1_rptr;
- if (params->hw_funcs->set_inbox1_wptr)
- dmub->hw_funcs.set_inbox1_wptr =
- params->hw_funcs->set_inbox1_wptr;
+ if (params->hw_funcs->emul_set_inbox1_wptr)
+ dmub->hw_funcs.emul_set_inbox1_wptr =
+ params->hw_funcs->emul_set_inbox1_wptr;
if (params->hw_funcs->is_supported)
dmub->hw_funcs.is_supported =
@@ -266,6 +283,16 @@ dmub_srv_calc_region_info(struct dmub_srv *dmub,
if (fw_info) {
fw_state_size = fw_info->fw_region_size;
trace_buffer_size = fw_info->trace_buffer_size;
+
+ /**
+ * If DM didn't fill in a version, then fill it in based on
+ * the firmware meta now that we have it.
+ *
+ * TODO: Make it easier for driver to extract this out to
+ * pass during creation.
+ */
+ if (dmub->fw_version == 0)
+ dmub->fw_version = fw_info->fw_version;
}
trace_buff->base = dmub_align(mail->top, 256);
@@ -402,7 +429,7 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
cw3.region.top = cw3.region.base + bios_fb->size;
cw4.offset.quad_part = mail_fb->gpu_addr;
- cw4.region.base = cw3.region.top + 1;
+ cw4.region.base = DMUB_CW4_BASE;
cw4.region.top = cw4.region.base + mail_fb->size;
inbox1.base = cw4.region.base;
@@ -485,7 +512,7 @@ enum dmub_status dmub_srv_cmd_execute(struct dmub_srv *dmub)
*/
dmub_rb_flush_pending(&dmub->inbox1_rb);
- dmub->hw_funcs.set_inbox1_wptr(dmub, dmub->inbox1_rb.wrpt);
+ dmub->hw_funcs.set_inbox1_wptr(dmub, dmub->inbox1_rb.wrpt);
return DMUB_STATUS_OK;
}
@@ -540,7 +567,7 @@ enum dmub_status dmub_srv_wait_for_idle(struct dmub_srv *dmub,
return DMUB_STATUS_INVALID;
for (i = 0; i <= timeout_us; ++i) {
- dmub->inbox1_rb.rptr = dmub->hw_funcs.get_inbox1_rptr(dmub);
+ dmub->inbox1_rb.rptr = dmub->hw_funcs.get_inbox1_rptr(dmub);
if (dmub_rb_empty(&dmub->inbox1_rb))
return DMUB_STATUS_OK;