diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dmub')
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 499 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd_dal.h | 56 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/inc/dmub_fw_meta.h | 63 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/inc/dmub_gpint_cmd.h | 75 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/inc/dmub_rb.h | 152 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/inc/dmub_types.h | 75 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/src/Makefile | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c | 34 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c | 195 | ||||
-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.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c | 55 |
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; |