Commit 08502ceb authored by Aurabindo Pillai's avatar Aurabindo Pillai Committed by Alex Deucher
Browse files

drm/amd/display: Add DCN401 dependant changes for DMCUB

parent a64a5212
Loading
Loading
Loading
Loading
+36 −8
Original line number Diff line number Diff line
@@ -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_ */
+225 −16
Original line number Diff line number Diff line
@@ -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

//==============================================================================
//</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>====================================================================
//==============================================================================
+1 −0
Original line number Diff line number Diff line
@@ -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))

+0 −1
Original line number Diff line number Diff line
@@ -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)

+87 −0
Original line number Diff line number Diff line
@@ -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)