drm/amd/display: Add DCN401 dependant changes for DMCUB
authorAurabindo Pillai <aurabindo.pillai@amd.com>
Wed, 20 Mar 2024 17:11:15 +0000 (13:11 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 26 Apr 2024 21:23:26 +0000 (17:23 -0400)
Update for DCN 4.0.1.

Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Acked-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dmub/dmub_srv.h
drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
drivers/gpu/drm/amd/display/dmub/src/Makefile
drivers/gpu/drm/amd/display/dmub/src/dmub_reg.h
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c

index 2fde1f0..cec8aa1 100644 (file)
 #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_ */
index e85fd3a..bb4aed3 100644 (file)
 #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
-
 //==============================================================================
 //</DMUB_TYPES>=================================================================
 //==============================================================================
@@ -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
-
 //==============================================================================
 //</DMUB_RB>====================================================================
 //==============================================================================
index 50a9844..a00b9e9 100644 (file)
@@ -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))
 
index 96603d0..123d170 100644 (file)
@@ -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)
 
index 90e8781..9bb4c51 100644 (file)
@@ -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)