From 08502cebee7c54d58fee0a54a98064dade4cc4de Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Wed, 20 Mar 2024 13:11:15 -0400 Subject: [PATCH] drm/amd/display: Add DCN401 dependant changes for DMCUB Update for DCN 4.0.1. Signed-off-by: Aurabindo Pillai Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 44 +++- .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 241 ++++++++++++++++-- drivers/gpu/drm/amd/display/dmub/src/Makefile | 1 + .../gpu/drm/amd/display/dmub/src/dmub_reg.h | 1 - .../gpu/drm/amd/display/dmub/src/dmub_srv.c | 87 +++++++ 5 files changed, 349 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index 2fde1f043d505..cec8aa1face5b 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -67,10 +67,6 @@ #include "inc/dmub_cmd.h" #include "dc/dc_types.h" -#if defined(__cplusplus) -extern "C" { -#endif - #define DMUB_PC_SNAPSHOT_COUNT 10 /* Forward declarations */ @@ -115,6 +111,7 @@ enum dmub_asic { DMUB_ASIC_DCN321, DMUB_ASIC_DCN35, DMUB_ASIC_DCN351, + DMUB_ASIC_DCN401, DMUB_ASIC_MAX, }; @@ -300,6 +297,7 @@ struct dmub_srv_hw_params { bool ips_sequential_ono; enum dmub_memory_access_type mem_access_type; enum dmub_ips_disable_type disable_ips; + bool disallow_phy_access; }; /** @@ -453,6 +451,19 @@ struct dmub_srv_hw_funcs { void (*init_reg_offsets)(struct dmub_srv *dmub, struct dc_context *ctx); void (*subvp_save_surf_addr)(struct dmub_srv *dmub, const struct dc_plane_address *addr, uint8_t subvp_index); + void (*send_reg_inbox0_cmd_msg)(struct dmub_srv *dmub, + union dmub_rb_cmd *cmd); + uint32_t (*read_reg_inbox0_rsp_int_status)(struct dmub_srv *dmub); + void (*read_reg_inbox0_cmd_rsp)(struct dmub_srv *dmub, + union dmub_rb_cmd *cmd); + void (*write_reg_inbox0_rsp_int_ack)(struct dmub_srv *dmub); + uint32_t (*read_reg_outbox0_rdy_int_status)(struct dmub_srv *dmub); + void (*write_reg_outbox0_rdy_int_ack)(struct dmub_srv *dmub); + void (*read_reg_outbox0_msg)(struct dmub_srv *dmub, uint32_t *msg); + void (*write_reg_outbox0_rsp)(struct dmub_srv *dmub, uint32_t *rsp); + uint32_t (*read_reg_outbox0_rsp_int_status)(struct dmub_srv *dmub); + void (*enable_reg_inbox0_rsp_int)(struct dmub_srv *dmub, bool enable); + void (*enable_reg_outbox0_rdy_int)(struct dmub_srv *dmub, bool enable); }; /** @@ -496,6 +507,7 @@ struct dmub_srv { const struct dmub_srv_dcn31_regs *regs_dcn31; struct dmub_srv_dcn32_regs *regs_dcn32; struct dmub_srv_dcn35_regs *regs_dcn35; + const struct dmub_srv_dcn401_regs *regs_dcn401; struct dmub_srv_base_funcs funcs; struct dmub_srv_hw_funcs hw_funcs; @@ -926,6 +938,26 @@ enum dmub_status dmub_srv_clear_inbox0_ack(struct dmub_srv *dmub); */ void dmub_srv_subvp_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_address *addr, uint8_t subvp_index); +/** + * dmub_srv_send_reg_inbox0_cmd() - send a dmub command and wait for the command + * being processed by DMUB. + * @dmub: The dmub service + * @cmd: The dmub command being sent. If with_replay is true, the function will + * update cmd with replied data. + * @with_reply: true if DMUB reply needs to be copied back to cmd. false if the + * cmd doesn't need to be replied. + * @timeout_us: timeout in microseconds. + * + * Return: + * DMUB_STATUS_OK - success + * DMUB_STATUS_TIMEOUT - DMUB fails to process the command within the timeout + * interval. + */ +enum dmub_status dmub_srv_send_reg_inbox0_cmd( + struct dmub_srv *dmub, + union dmub_rb_cmd *cmd, + bool with_reply, uint32_t timeout_us); + /** * dmub_srv_set_power_state() - Track DC power state in dmub_srv * @dmub: The dmub service @@ -938,8 +970,4 @@ void dmub_srv_subvp_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_ */ void dmub_srv_set_power_state(struct dmub_srv *dmub, enum dmub_srv_power_state_type dmub_srv_power_state); -#if defined(__cplusplus) -} -#endif - #endif /* _DMUB_SRV_H_ */ 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 e85fd3ac52c7c..bb4aed3293939 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -150,10 +150,6 @@ #define dmub_memset(dest, val, bytes) memset((dest), (val), (bytes)) #endif -#if defined(__cplusplus) -extern "C" { -#endif - /** * OS/FW agnostic udelay */ @@ -487,10 +483,6 @@ struct dmub_visual_confirm_color { uint16_t panel_inst; }; -#if defined(__cplusplus) -} -#endif - //============================================================================== //================================================================= //============================================================================== @@ -1582,6 +1574,223 @@ struct dmub_rb_cmd_fw_assisted_mclk_switch_v2 { struct dmub_cmd_fw_assisted_mclk_switch_config_v2 config_data; }; +struct dmub_flip_addr_info { + uint32_t surf_addr_lo; + uint32_t surf_addr_c_lo; + uint32_t meta_addr_lo; + uint32_t meta_addr_c_lo; + uint16_t surf_addr_hi; + uint16_t surf_addr_c_hi; + uint16_t meta_addr_hi; + uint16_t meta_addr_c_hi; +}; + +struct dmub_fams2_flip_info { + union { + struct { + uint8_t is_immediate: 1; + } bits; + uint8_t all; + } config; + uint8_t otg_inst; + uint8_t pipe_mask; + uint8_t pad; + struct dmub_flip_addr_info addr_info; +}; + +struct dmub_rb_cmd_fams2_flip { + struct dmub_cmd_header header; + struct dmub_fams2_flip_info flip_info; +}; + +struct dmub_optc_state_v2 { + uint32_t v_total_min; + uint32_t v_total_max; + uint32_t v_total_mid; + uint32_t v_total_mid_frame_num; + uint8_t program_manual_trigger; + uint8_t tg_inst; + uint8_t pad[2]; +}; + +struct dmub_optc_position { + uint32_t vpos; + uint32_t hpos; + uint32_t frame; +}; + +struct dmub_rb_cmd_fams2_drr_update { + struct dmub_cmd_header header; + struct dmub_optc_state_v2 dmub_optc_state_req; +}; + +/* HW and FW global configuration data for FAMS2 */ +/* FAMS2 types and structs */ +enum fams2_stream_type { + FAMS2_STREAM_TYPE_NONE = 0, + FAMS2_STREAM_TYPE_VBLANK = 1, + FAMS2_STREAM_TYPE_VACTIVE = 2, + FAMS2_STREAM_TYPE_DRR = 3, + FAMS2_STREAM_TYPE_SUBVP = 4, +}; + +/* dynamic stream state */ +struct dmub_fams2_legacy_stream_dynamic_state { + uint8_t force_allow_at_vblank; + uint8_t pad[3]; +}; + +struct dmub_fams2_subvp_stream_dynamic_state { + uint16_t viewport_start_hubp_vline; + uint16_t viewport_height_hubp_vlines; + uint16_t viewport_start_c_hubp_vline; + uint16_t viewport_height_c_hubp_vlines; + uint16_t phantom_viewport_height_hubp_vlines; + uint16_t phantom_viewport_height_c_hubp_vlines; + uint16_t microschedule_start_otg_vline; + uint16_t mall_start_otg_vline; + uint16_t mall_start_hubp_vline; + uint16_t mall_start_c_hubp_vline; + uint8_t force_allow_at_vblank_only; + uint8_t pad[3]; +}; + +struct dmub_fams2_drr_stream_dynamic_state { + uint16_t stretched_vtotal; + uint8_t use_cur_vtotal; + uint8_t pad; +}; + +struct dmub_fams2_stream_dynamic_state { + uint64_t ref_tick; + uint32_t cur_vtotal; + uint16_t adjusted_allow_end_otg_vline; + uint8_t pad[2]; + struct dmub_optc_position ref_otg_pos; + struct dmub_optc_position target_otg_pos; + union { + struct dmub_fams2_legacy_stream_dynamic_state legacy; + struct dmub_fams2_subvp_stream_dynamic_state subvp; + struct dmub_fams2_drr_stream_dynamic_state drr; + } sub_state; +}; + +/* static stream state */ +struct dmub_fams2_legacy_stream_static_state { + uint8_t vactive_det_fill_delay_otg_vlines; + uint8_t programming_delay_otg_vlines; +}; + +struct dmub_fams2_subvp_stream_static_state { + uint16_t vratio_numerator; + uint16_t vratio_denominator; + uint16_t phantom_vtotal; + uint16_t phantom_vactive; + union { + struct { + uint8_t is_multi_planar : 1; + uint8_t is_yuv420 : 1; + } bits; + uint8_t all; + } config; + uint8_t programming_delay_otg_vlines; + uint8_t prefetch_to_mall_otg_vlines; + uint8_t phantom_otg_inst; + uint8_t phantom_pipe_mask; + uint8_t phantom_plane_pipe_masks[DMUB_MAX_PHANTOM_PLANES]; // phantom pipe mask per plane (for flip passthrough) +}; + +struct dmub_fams2_drr_stream_static_state { + uint16_t nom_stretched_vtotal; + uint8_t programming_delay_otg_vlines; + uint8_t only_stretch_if_required; + uint8_t pad[2]; +}; + +struct dmub_fams2_stream_static_state { + enum fams2_stream_type type; + uint32_t otg_vline_time_ns; + uint32_t otg_vline_time_ticks; + uint16_t htotal; + uint16_t vtotal; // nominal vtotal + uint16_t vblank_start; + uint16_t vblank_end; + uint16_t max_vtotal; + uint16_t allow_start_otg_vline; + uint16_t allow_end_otg_vline; + uint16_t drr_keepout_otg_vline; // after this vline, vtotal cannot be changed + uint8_t scheduling_delay_otg_vlines; // min time to budget for ready to microschedule start + uint8_t contention_delay_otg_vlines; // time to budget for contention on execution + uint8_t vline_int_ack_delay_otg_vlines; // min time to budget for vertical interrupt firing + uint8_t allow_to_target_delay_otg_vlines; // time from allow vline to target vline + union { + struct { + uint8_t is_drr: 1; // stream is DRR enabled + uint8_t clamp_vtotal_min: 1; // clamp vtotal to min instead of nominal + uint8_t min_ttu_vblank_usable: 1; // if min ttu vblank is above wm, no force pstate is needed in blank + } bits; + uint8_t all; + } config; + uint8_t otg_inst; + uint8_t pipe_mask; // pipe mask for the whole config + uint8_t num_planes; + uint8_t plane_pipe_masks[DMUB_MAX_PLANES]; // pipe mask per plane (for flip passthrough) + uint8_t pad[DMUB_MAX_PLANES % 4]; + union { + struct dmub_fams2_legacy_stream_static_state legacy; + struct dmub_fams2_subvp_stream_static_state subvp; + struct dmub_fams2_drr_stream_static_state drr; + } sub_state; +}; + +/** + * enum dmub_fams2_allow_delay_check_mode - macroscheduler mode for breaking on excessive + * p-state request to allow latency + */ +enum dmub_fams2_allow_delay_check_mode { + /* No check for request to allow delay */ + FAMS2_ALLOW_DELAY_CHECK_NONE = 0, + /* Check for request to allow delay */ + FAMS2_ALLOW_DELAY_CHECK_FROM_START = 1, + /* Check for prepare to allow delay */ + FAMS2_ALLOW_DELAY_CHECK_FROM_PREPARE = 2, +}; + +union dmub_fams2_global_feature_config { + struct { + uint32_t enable: 1; + uint32_t enable_ppt_check: 1; + uint32_t enable_stall_recovery: 1; + uint32_t enable_debug: 1; + uint32_t enable_offload_flip: 1; + uint32_t enable_visual_confirm: 1; + uint32_t allow_delay_check_mode: 2; + uint32_t reserved: 24; + } bits; + uint32_t all; +}; + +struct dmub_cmd_fams2_global_config { + uint32_t max_allow_delay_us; // max delay to assert allow from uclk change begin + uint32_t lock_wait_time_us; // time to forecast acquisition of lock + uint32_t num_streams; + union dmub_fams2_global_feature_config features; + uint8_t pad[3]; +}; + +union dmub_cmd_fams2_config { + struct dmub_cmd_fams2_global_config global; + struct dmub_fams2_stream_static_state stream; +}; + +/** + * DMUB rb command definition for FAMS2 (merged SubVP, FPO, Legacy) + */ +struct dmub_rb_cmd_fams2 { + struct dmub_cmd_header header; + union dmub_cmd_fams2_config config; +}; + /** * enum dmub_cmd_idle_opt_type - Idle optimization command type. */ @@ -2263,6 +2472,9 @@ enum dmub_cmd_fams_type { * on (for any SubVP cases that use a DRR display) */ DMUB_CMD__FAMS_SET_MANUAL_TRIGGER = 3, + DMUB_CMD__FAMS2_CONFIG = 4, + DMUB_CMD__FAMS2_DRR_UPDATE = 5, + DMUB_CMD__FAMS2_FLIP = 6, }; /** @@ -3547,6 +3759,7 @@ enum hw_lock_client { * Replay is the client of HW Lock Manager. */ HW_LOCK_CLIENT_REPLAY = 4, + HW_LOCK_CLIENT_FAMS2 = 5, /** * Invalid client. */ @@ -4722,7 +4935,11 @@ union dmub_rb_cmd { * Definition of a DMUB_CMD__PSP_ASSR_ENABLE command. */ struct dmub_rb_cmd_assr_enable assr_enable; + struct dmub_rb_cmd_fams2 fams2_config; + + struct dmub_rb_cmd_fams2_drr_update fams2_drr_update; + struct dmub_rb_cmd_fams2_flip fams2_flip; }; /** @@ -4759,10 +4976,6 @@ union dmub_rb_out_cmd { //< DMUB_RB>==================================================================== //============================================================================== -#if defined(__cplusplus) -extern "C" { -#endif - /** * struct dmub_rb_init_params - Initialization params for DMUB ringbuffer */ @@ -5039,10 +5252,6 @@ static inline void dmub_rb_get_return_data(struct dmub_rb *rb, dmub_memcpy(cmd, rd_ptr, DMUB_RB_CMD_SIZE); } -#if defined(__cplusplus) -} -#endif - //============================================================================== //==================================================================== //============================================================================== diff --git a/drivers/gpu/drm/amd/display/dmub/src/Makefile b/drivers/gpu/drm/amd/display/dmub/src/Makefile index 50a98448e2e80..a00b9e9922926 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/Makefile +++ b/drivers/gpu/drm/amd/display/dmub/src/Makefile @@ -26,6 +26,7 @@ DMUB += dmub_dcn31.o dmub_dcn314.o dmub_dcn315.o dmub_dcn316.o DMUB += dmub_dcn32.o DMUB += dmub_dcn35.o DMUB += dmub_dcn351.o +DMUB += dmub_dcn401.o AMD_DAL_DMUB = $(addprefix $(AMDDALPATH)/dmub/src/,$(DMUB)) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h index 96603d07c23d5..123d1704670ee 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h @@ -108,7 +108,6 @@ struct dmub_srv; FN(reg, f4), v4) /* Register field getting. */ - #define REG_GET(reg_name, field, val) \ dmub_reg_get(CTX, REG(reg_name), FN(reg_name, field), val) 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 90e878195d95f..9bb4c51b1f5bf 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -38,6 +38,7 @@ #include "dmub_dcn32.h" #include "dmub_dcn35.h" #include "dmub_dcn351.h" +#include "dmub_dcn401.h" #include "os_types.h" /* * Note: the DMUB service is standalone. No additional headers should be @@ -360,6 +361,52 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) funcs->should_detect = dmub_dcn35_should_detect; break; + case DMUB_ASIC_DCN401: + dmub->regs_dcn401 = &dmub_srv_dcn401_regs; + funcs->configure_dmub_in_system_memory = dmub_dcn401_configure_dmub_in_system_memory; + funcs->send_inbox0_cmd = dmub_dcn401_send_inbox0_cmd; + funcs->clear_inbox0_ack_register = dmub_dcn401_clear_inbox0_ack_register; + funcs->read_inbox0_ack_register = dmub_dcn401_read_inbox0_ack_register; + funcs->reset = dmub_dcn401_reset; + funcs->reset_release = dmub_dcn401_reset_release; + funcs->backdoor_load = dmub_dcn401_backdoor_load; + funcs->backdoor_load_zfb_mode = dmub_dcn401_backdoor_load_zfb_mode; + funcs->setup_windows = dmub_dcn401_setup_windows; + funcs->setup_mailbox = dmub_dcn401_setup_mailbox; + funcs->get_inbox1_wptr = dmub_dcn401_get_inbox1_wptr; + funcs->get_inbox1_rptr = dmub_dcn401_get_inbox1_rptr; + funcs->set_inbox1_wptr = dmub_dcn401_set_inbox1_wptr; + funcs->setup_out_mailbox = dmub_dcn401_setup_out_mailbox; + funcs->get_outbox1_wptr = dmub_dcn401_get_outbox1_wptr; + funcs->set_outbox1_rptr = dmub_dcn401_set_outbox1_rptr; + funcs->is_supported = dmub_dcn401_is_supported; + funcs->is_hw_init = dmub_dcn401_is_hw_init; + funcs->set_gpint = dmub_dcn401_set_gpint; + funcs->is_gpint_acked = dmub_dcn401_is_gpint_acked; + funcs->get_gpint_response = dmub_dcn401_get_gpint_response; + funcs->get_gpint_dataout = dmub_dcn401_get_gpint_dataout; + funcs->get_fw_status = dmub_dcn401_get_fw_boot_status; + funcs->enable_dmub_boot_options = dmub_dcn401_enable_dmub_boot_options; + funcs->skip_dmub_panel_power_sequence = dmub_dcn401_skip_dmub_panel_power_sequence; + //outbox0 call stacks + funcs->setup_outbox0 = dmub_dcn401_setup_outbox0; + funcs->get_outbox0_wptr = dmub_dcn401_get_outbox0_wptr; + funcs->set_outbox0_rptr = dmub_dcn401_set_outbox0_rptr; + + funcs->get_current_time = dmub_dcn401_get_current_time; + funcs->get_diagnostic_data = dmub_dcn401_get_diagnostic_data; + funcs->send_reg_inbox0_cmd_msg = dmub_dcn401_send_reg_inbox0_cmd_msg; + funcs->read_reg_inbox0_rsp_int_status = dmub_dcn401_read_reg_inbox0_rsp_int_status; + funcs->read_reg_inbox0_cmd_rsp = dmub_dcn401_read_reg_inbox0_cmd_rsp; + funcs->write_reg_inbox0_rsp_int_ack = dmub_dcn401_write_reg_inbox0_rsp_int_ack; + funcs->write_reg_outbox0_rdy_int_ack = dmub_dcn401_write_reg_outbox0_rdy_int_ack; + funcs->read_reg_outbox0_msg = dmub_dcn401_read_reg_outbox0_msg; + funcs->write_reg_outbox0_rsp = dmub_dcn401_write_reg_outbox0_rsp; + funcs->read_reg_outbox0_rdy_int_status = dmub_dcn401_read_reg_outbox0_rdy_int_status; + funcs->read_reg_outbox0_rsp_int_status = dmub_dcn401_read_reg_outbox0_rsp_int_status; + funcs->enable_reg_inbox0_rsp_int = dmub_dcn401_enable_reg_inbox0_rsp_int; + funcs->enable_reg_outbox0_rdy_int = dmub_dcn401_enable_reg_outbox0_rdy_int; + break; default: return false; } @@ -677,6 +724,10 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, dmub->hw_funcs.setup_mailbox(dmub, &inbox1); if (dmub->hw_funcs.setup_out_mailbox) dmub->hw_funcs.setup_out_mailbox(dmub, &outbox1); + if (dmub->hw_funcs.enable_reg_inbox0_rsp_int) + dmub->hw_funcs.enable_reg_inbox0_rsp_int(dmub, true); + if (dmub->hw_funcs.enable_reg_outbox0_rdy_int) + dmub->hw_funcs.enable_reg_outbox0_rdy_int(dmub, true); dmub_memset(&rb_params, 0, sizeof(rb_params)); rb_params.ctx = dmub; @@ -1105,6 +1156,42 @@ void dmub_srv_subvp_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_ } } +enum dmub_status dmub_srv_send_reg_inbox0_cmd( + struct dmub_srv *dmub, + union dmub_rb_cmd *cmd, + bool with_reply, uint32_t timeout_us) +{ + uint32_t rsp_ready = 0; + uint32_t i; + + dmub->hw_funcs.send_reg_inbox0_cmd_msg(dmub, cmd); + + for (i = 0; i < timeout_us; i++) { + rsp_ready = dmub->hw_funcs.read_reg_inbox0_rsp_int_status(dmub); + if (rsp_ready) + break; + udelay(1); + } + if (rsp_ready == 0) + return DMUB_STATUS_TIMEOUT; + + if (with_reply) + dmub->hw_funcs.read_reg_inbox0_cmd_rsp(dmub, cmd); + + dmub->hw_funcs.write_reg_inbox0_rsp_int_ack(dmub); + + /* wait for rsp int status is cleared to initial state before exit */ + for (; i <= timeout_us; i++) { + rsp_ready = dmub->hw_funcs.read_reg_inbox0_rsp_int_status(dmub); + if (rsp_ready == 0) + break; + udelay(1); + } + ASSERT(rsp_ready == 0); + + return DMUB_STATUS_OK; +} + void dmub_srv_set_power_state(struct dmub_srv *dmub, enum dmub_srv_power_state_type dmub_srv_power_state) { if (!dmub || !dmub->hw_init)