[PATCH 14/24] drm/amd/display: ACPI Re-timer Programming

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: "Ostrowski, Rafal" <rostrows@xxxxxxx>

[Why]
We must implement an ACPI re-timer programming interface and notify
ACPI driver whenever a PHY transition is about to take place.

Because some trace lengths on certain platforms are very long,
then a re-timer may need to be programmed whenever a PHY transition
takes place. The implementation of this re-timer programming interface
will notify ACPI driver that PHY transition is taking place and it
will trigger the re-timer as needed.

First we need to gather retimer information from ACPI interface.

Then, in the PRE case, the re-timer interface needs to be called before we call
transmitter ENABLE.
In the POST case, it has to be called after we call transmitter DISABLE.

[How]
Implemented ACPI retimer programming interface.

Reviewed-by: Alvin Lee <alvin.lee2@xxxxxxx>
Signed-off-by: Rafal Ostrowski <rostrows@xxxxxxx>
Signed-off-by: Zaeem Mohamed <zaeem.mohamed@xxxxxxx>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  7 +++
 .../drm/amd/display/dc/bios/command_table2.c  | 47 +++++++++++++++++++
 drivers/gpu/drm/amd/display/dc/dc.h           |  2 +
 drivers/gpu/drm/amd/display/dc/dm_services.h  |  7 +++
 .../drm/amd/display/dc/dm_services_types.h    | 26 ++++++++++
 5 files changed, 89 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 9f53d88ad7ca..bb8ba30994b6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -12696,3 +12696,10 @@ bool dm_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count,
 {
 	return dc_dmub_srv_cmd_run_list(ctx->dmub_srv, count, cmd, wait_type);
 }
+
+void dm_acpi_process_phy_transition_interlock(
+	const struct dc_context *ctx,
+	struct dm_process_phy_transition_init_params process_phy_transition_init_params)
+{
+	// Not yet implemented
+}
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
index 7d18f372ce7a..2c96a5e64567 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
@@ -210,6 +210,7 @@ static enum bp_result encoder_control_fallback(
  ******************************************************************************
  *****************************************************************************/
 
+
 static enum bp_result transmitter_control_v1_6(
 	struct bios_parser *bp,
 	struct bp_transmitter_control *cntl);
@@ -325,6 +326,21 @@ static void transmitter_control_dmcub_v1_7(
 	dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
 }
 
+static struct dc_link *get_link_by_phy_id(struct dc *p_dc, uint32_t phy_id)
+{
+	struct dc_link *link = NULL;
+
+	// Get Transition Bitmask from dc_link structure associated with PHY
+	for (uint8_t link_id = 0; link_id < MAX_LINKS; link_id++) {
+		if (phy_id == p_dc->links[link_id]->link_enc->transmitter) {
+			link = p_dc->links[link_id];
+			break;
+		}
+	}
+
+	return link;
+}
+
 static enum bp_result transmitter_control_v1_7(
 	struct bios_parser *bp,
 	struct bp_transmitter_control *cntl)
@@ -363,7 +379,37 @@ static enum bp_result transmitter_control_v1_7(
 
 	if (bp->base.ctx->dc->ctx->dmub_srv &&
 		bp->base.ctx->dc->debug.dmub_command_table) {
+		struct dm_process_phy_transition_init_params process_phy_transition_init_params = {0};
+		struct dc_link *link = get_link_by_phy_id(bp->base.ctx->dc, dig_v1_7.phyid);
+		bool is_phy_transition_interlock_allowed = false;
+		uint8_t action = dig_v1_7.action;
+
+		if (link) {
+			if (link->phy_transition_bitmask &&
+				(action == TRANSMITTER_CONTROL_ENABLE || action == TRANSMITTER_CONTROL_DISABLE)) {
+				is_phy_transition_interlock_allowed = true;
+
+				// Prepare input parameters for processing ACPI retimers
+				process_phy_transition_init_params.action                   = action;
+				process_phy_transition_init_params.display_port_lanes_count = cntl->lanes_number;
+				process_phy_transition_init_params.phy_id                   = dig_v1_7.phyid;
+				process_phy_transition_init_params.signal                   = cntl->signal;
+				process_phy_transition_init_params.sym_clock_10khz          = dig_v1_7.symclk_units.symclk_10khz;
+				process_phy_transition_init_params.display_port_link_rate   = link->cur_link_settings.link_rate;
+				process_phy_transition_init_params.transition_bitmask       = link->phy_transition_bitmask;
+			}
+		}
+
+		// Handle PRE_OFF_TO_ON: Process ACPI PHY Transition Interlock
+		if (is_phy_transition_interlock_allowed && action == TRANSMITTER_CONTROL_ENABLE)
+			dm_acpi_process_phy_transition_interlock(bp->base.ctx, process_phy_transition_init_params);
+
 		transmitter_control_dmcub_v1_7(bp->base.ctx->dmub_srv, &dig_v1_7);
+
+		// Handle POST_ON_TO_OFF: Process ACPI PHY Transition Interlock
+		if (is_phy_transition_interlock_allowed && action == TRANSMITTER_CONTROL_DISABLE)
+			dm_acpi_process_phy_transition_interlock(bp->base.ctx, process_phy_transition_init_params);
+
 		return BP_RESULT_OK;
 	}
 
@@ -1046,3 +1092,4 @@ void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp)
 
 	init_enable_lvtma_control(bp);
 }
+
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 5e96913bcab1..f76884fe86e3 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1083,6 +1083,7 @@ struct dc_debug_options {
 	unsigned int enable_oled_edp_power_up_opt;
 	bool enable_hblank_borrow;
 	bool force_subvp_df_throttle;
+	uint32_t acpi_transition_bitmasks[MAX_PIPES];
 };
 
 
@@ -1806,6 +1807,7 @@ struct dc_link {
 
 	struct dc_panel_config panel_config;
 	struct phy_state phy_state;
+	uint32_t phy_transition_bitmask;
 	// BW ALLOCATON USB4 ONLY
 	struct dc_dpia_bw_alloc dpia_bw_alloc_config;
 	bool skip_implict_edp_power_control;
diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h
index f81e5a4e1d6d..7b9c22c45453 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services.h
@@ -290,6 +290,13 @@ void dm_trace_smu_delay(uint32_t delay, struct dc_context *ctx);
 bool dm_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type);
 bool dm_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type);
 
+/*
+ * ACPI Interfaces
+ */
+void dm_acpi_process_phy_transition_interlock(
+	const struct dc_context *ctx,
+	struct dm_process_phy_transition_init_params process_phy_transition_init_params);
+
 /*
  * Debug and verification hooks
  */
diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
index facf269c4326..bf63da266a18 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
@@ -275,4 +275,30 @@ enum dm_dmub_wait_type {
 	DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY,
 };
 
+enum dm_acpi_transition_link_type {
+	hdmi_tmds,
+	hdmi_frl,
+	dp_8b_10b,
+	dp_128b_132b,
+	none
+};
+
+struct dm_process_phy_transition_init_params {
+	uint32_t phy_id;
+	uint8_t action;
+	uint32_t sym_clock_10khz;
+	enum signal_type signal;
+	enum dc_lane_count display_port_lanes_count;
+	enum dc_link_rate display_port_link_rate;
+	uint32_t transition_bitmask;
+	uint8_t hdmi_frl_num_lanes;
+};
+
+struct dm_process_phy_transition_input_params {
+	uint32_t phy_id;
+	uint32_t transition_id;
+	uint32_t phy_configuration;
+	uint32_t data_rate;
+};
+
 #endif
-- 
2.34.1




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux