AMD-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Harry Wentland <harry.wentland@amd.com>
To: <amd-gfx@lists.freedesktop.org>
Cc: <Jerry.Zuo@amd.com>, Harry Wentland <harry.wentland@amd.com>
Subject: [PATCH v5 01/13] drm/amd/display: Add HDMI FRL definitions to includes
Date: Tue, 12 May 2026 11:52:32 -0400	[thread overview]
Message-ID: <20260512155244.403854-2-harry.wentland@amd.com> (raw)
In-Reply-To: <20260512155244.403854-1-harry.wentland@amd.com>

This patch adds all relevant includes in DC that are
used by the HDMI FRL implementation in DC.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
---
 drivers/gpu/drm/amd/display/dc/dc.h           | 121 ++++++++++
 .../gpu/drm/amd/display/dc/dc_hdmi_types.h    | 162 ++++++++++++-
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |   8 +
 drivers/gpu/drm/amd/display/dc/dc_types.h     |  24 ++
 drivers/gpu/drm/amd/display/dc/dm_cp_psp.h    |   1 +
 .../drm/amd/display/dc/dm_services_types.h    |   1 +
 .../drm/amd/display/dc/dml/dml1_frl_cap_chk.h | 173 +++++++++++++
 .../gpu/drm/amd/display/dc/inc/core_status.h  |   2 +
 .../gpu/drm/amd/display/dc/inc/core_types.h   |  12 +
 drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h  |  10 +
 .../gpu/drm/amd/display/dc/inc/hw/hw_shared.h |   1 +
 .../drm/amd/display/dc/inc/hw/link_encoder.h  | 176 ++++++++++++++
 .../amd/display/dc/inc/hw/stream_encoder.h    | 227 ++++++++++++++++++
 .../amd/display/dc/inc/hw/timing_generator.h  |   6 +
 .../gpu/drm/amd/display/dc/inc/link_service.h |  15 ++
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   7 +
 .../gpu/drm/amd/display/include/audio_types.h |   1 +
 .../amd/display/include/bios_parser_types.h   |  14 +-
 .../drm/amd/display/include/logger_types.h    |   2 +
 .../drm/amd/display/include/signal_types.h    |  12 +-
 20 files changed, 966 insertions(+), 9 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml1_frl_cap_chk.h

diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index d0b6fad65bc0..0cbb60325875 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -46,6 +46,8 @@
 
 #include "dmub/inc/dmub_cmd.h"
 
+#include "dml/dml1_frl_cap_chk.h"
+
 #include "sspl/dc_spl_types.h"
 
 struct abm_save_restore;
@@ -84,6 +86,49 @@ struct dcn_dccg_reg_state;
 
 #define NUM_FAST_FLIPS_TO_STEADY_STATE 20
 
+struct frl_cap_chk_intermediates_fixed31_32 {
+	int      c_frl_sb;
+	struct fixed31_32   overhead_sb;
+	struct fixed31_32   overhead_rs;
+	struct fixed31_32   overhead_map;
+	struct fixed31_32   overhead_min;
+	struct fixed31_32   overhead_max;
+	struct fixed31_32   f_pixel_clock_max;
+	struct fixed31_32   t_line;
+	struct fixed31_32   r_bit_min;
+	struct fixed31_32   r_frl_char_min;
+	struct fixed31_32   c_frl_line;
+	struct fixed31_32   ap;
+	struct fixed31_32   r_ap;
+	struct fixed31_32   avg_audio_packets_line;
+	struct fixed31_32   margin;
+	int      audio_packets_line;
+	int      blank_audio_min;
+};
+
+struct frl_cap_chk_params_fixed31_32 {
+	int      lanes;
+	struct fixed31_32   f_pixel_clock_nominal;   /* Pixel Clock rate (Hz)  */
+	struct fixed31_32   r_bit_nominal;           /* FRL bitrate (bps) */
+	int      audio_packet_type;
+	struct fixed31_32   f_audio;                 /* Audio rate (Hz) */
+	int      h_active;                /* Active pixels per line */
+	int      h_blank;                 /* Blanking pixels per line */
+	int      bpc;                     /* Bits per component */
+	int      vic;                     /* Video Identification Code */
+
+	enum hdmi_frl_pixel_encoding    pixel_encoding;
+
+	bool     compressed;              /* set to true if DSC is enabled */
+	bool     bypass_hc_target_calc;   /* debug only */
+	int      layout;
+	int      acat;    /* not supported */
+
+	/* outputs */
+	struct frl_dml_borrow_params borrow_params;
+	int      average_tribyte_rate;
+};
+
 /* Display Core Interfaces */
 struct dc_versions {
 	const char *dc_ver;
@@ -332,6 +377,7 @@ struct dc_caps {
 	bool ips_v2_support;
 	uint32_t num_of_internal_disp;
 	enum dp_protocol_version max_dp_protocol_version;
+	bool hdmi_hpo;
 	unsigned int mall_size_per_mem_channel;
 	unsigned int mall_size_total;
 	unsigned int cursor_cache_size;
@@ -537,6 +583,8 @@ struct dc_config {
 	int smart_mux_version;
 	bool ignore_dpref_ss;
 	bool enable_mipi_converter_optimization;
+	bool force_hdmi21_frl_enc_enable;
+	bool skip_frl_pretraining;
 	bool use_default_clock_table;
 	bool force_bios_enable_lttpr;
 	uint8_t force_bios_fixed_vs;
@@ -1096,6 +1144,18 @@ struct dc_debug_options {
 	bool validate_dml_output;
 	bool enable_dmcub_surface_flip;
 	bool usbc_combo_phy_reset_wa;
+	bool force_vrr;
+	bool force_fva;
+	int max_frl_rate;
+	int  force_frl_rate;
+	bool ignore_ffe;
+	int  select_ffe;
+	int  limit_ffe;
+	bool force_frl_always;
+	bool force_frl_max;
+	bool apply_vsdb_rcc_wa;
+	bool enable_hdmi_idcc;
+
 	bool enable_dram_clock_change_one_display_vactive;
 	/* TODO - remove once tested */
 	bool legacy_dp2_lt;
@@ -1635,6 +1695,7 @@ struct dc_scratch_space {
 	bool edp_sink_present;
 
 	struct dp_trace dp_trace;
+	volatile bool is_link_locked;
 
 	/* caps is the same as reported_link_cap. link_traing use
 	 * reported_link_cap. Will clean up.  TODO
@@ -1649,6 +1710,7 @@ struct dc_scratch_space {
 	 * management of the override pointers.
 	 */
 	struct dc_link_training_overrides preferred_training_settings;
+	struct dc_hdmi_frl_link_training_overrides preferred_hdmi_frl_settings;
 	struct dp_audio_test_data audio_test_data;
 
 	enum gpio_ddc_line ddc_hw_inst;
@@ -1694,6 +1756,12 @@ struct dc_scratch_space {
 
 	struct panel_cntl *panel_cntl;
 	struct link_encoder *link_enc;
+	struct hpo_frl_link_encoder *hpo_frl_link_enc;
+	struct dc_hdmi_frl_link_settings frl_reported_link_cap;
+	struct dc_hdmi_frl_link_settings frl_verified_link_cap;
+	struct dc_hdmi_frl_link_settings frl_link_settings;
+	struct dc_hdmi_frl_flags frl_flags;
+	union hdmi_idcc_cable_id hdmi_cable_id;
 	struct graphics_object_id link_id;
 
 	/* External encoder eg. NUTMEG or TRAVIS used on CIK APUs. */
@@ -2033,6 +2101,17 @@ struct dc_plane_state *dc_get_surface_for_mpcc(struct dc *dc,
 
 
 uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane);
+bool dc_set_fva_vrr_adjust(struct dc *dc,
+	struct dc_stream_state *stream,
+	struct fva_adj *fva_adj,
+	struct dc_crtc_timing_adjust *vrr_adj);
+
+int dc_get_hw_max_fva_factor(struct dc *dc,
+		struct dc_stream_state *stream,
+		unsigned int max_pixel_clock);
+
+void dc_set_vstartup_start(struct dc *dc,
+		struct dc_stream_state *stream);
 
 void dc_set_disable_128b_132b_stream_overhead(bool disable);
 
@@ -2244,6 +2323,12 @@ enum dc_status dc_link_dp_read_hpd_rx_irq_data(
 	struct dc_link *link,
 	union hpd_irq_data *irq_data);
 
+bool dc_link_frl_poll_status_flag(struct dc_link *link);
+bool dc_link_frl_margin_check_uncompressed_video(
+		const struct dc_link *link,
+		struct frl_cap_chk_params_fixed31_32 *params,
+		struct frl_cap_chk_intermediates_fixed31_32 *inter);
+
 /* The function clears recorded DP RX states in the link. DM should call this
  * function when it is resuming from S3 power state to previously connected links.
  *
@@ -2268,6 +2353,12 @@ uint32_t dc_link_bandwidth_kbps(
 	const struct dc_link *link,
 	const struct dc_link_settings *link_setting);
 
+/* The function returns effective HDMI FRL bandwidth given link rate.
+ * return - total effective link bandwidth in kbps.
+ */
+uint32_t dc_link_frl_bandwidth_kbps(const struct dc_link *link,
+		enum hdmi_frl_link_rate link_rate);
+
 struct dp_audio_bandwidth_params {
 	const struct dc_crtc_timing *crtc_timing;
 	enum dp_link_encoding link_encoding;
@@ -2319,6 +2410,8 @@ void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map);
  */
 void dc_restore_link_res_map(const struct dc *dc, uint32_t *map);
 
+void dc_link_wait_for_unlocked(struct dc_link *link);
+
 /* TODO: this is not meant to be exposed to DM. Should switch to stream update
  * interface i.e stream_update->dsc_config
  */
@@ -2372,6 +2465,16 @@ const struct dc_link_settings *dc_link_get_link_cap(const struct dc_link *link);
  */
 enum dc_link_encoding_format dc_link_get_highest_encoding_format(const struct dc_link *link);
 
+/* get max frl link settings the link can enable with all things considered.
+ * (i.e TX/RX capabilities and link verification result.
+ *
+ * @link - a link with FRL RX connection
+ * return - max frl link settings the link can enable.
+ *
+ */
+struct dc_hdmi_frl_link_settings *dc_link_get_frl_link_cap(
+		struct dc_link *link);
+
 /* Check if a RX (ex. DP sink, MST hub, passive or active dongle) is connected
  * to a link with dp connector signal type.
  * @link - a link with dp connector signal type
@@ -2421,6 +2524,16 @@ void dc_link_set_preferred_link_settings(struct dc *dc,
 		struct dc_link_settings *link_setting,
 		struct dc_link *link);
 
+/* Force FRL link settings to always use a specific value until reboot to a
+ * specific link. If link has already been enabled, the interface will also
+ * switch to desired link settings immediately. This is a debug interface to
+ * generic FRL issue trouble shooting.
+ */
+void dc_link_set_preferred_frl_link_settings(struct dc *dc,
+		struct dc_hdmi_frl_link_settings *link_setting,
+		struct dc_hdmi_frl_link_training_overrides *lt_overrides,
+		struct dc_link *link);
+
 /* Force DP link to customize a specific link training behavior by overriding to
  * standard DP specs defined protocol. This is a debug interface to trouble shoot
  * display specific link training issues or apply some display specific
@@ -3094,6 +3207,14 @@ struct dc_register_software_state {
 		uint32_t symclk32_le_enable[2];          /* SYMCLK32_LE_CNTL->SYMCLK32_LE0_EN from dccg31_enable_symclk32_le() enable */
 		uint32_t symclk32_le_gate_disable[2];    /* DCCG_GATE_DISABLE_CNTL3->SYMCLK32_LE0_GATE_DISABLE from debug.root_clock_optimization.bits.symclk32_le */
 
+		/* HDMI Clock Control */
+		uint32_t hdmicharclk_enable;             /* HDMICHARCLK0_CLOCK_CNTL->HDMICHARCLK0_EN from dccg31_enable_hdmicharclk() */
+		uint32_t hdmicharclk_src_sel;            /* HDMICHARCLK0_CLOCK_CNTL->HDMICHARCLK0_SRC_SEL from dccg31_enable_hdmicharclk() phypll_inst source */
+		uint32_t hdmistreamclk_src_sel;          /* HDMISTREAMCLK_CNTL->HDMISTREAMCLK0_SRC_SEL from dccg31_set_hdmistreamclk() src selection */
+		uint32_t hdmistreamclk_dto_force_dis;    /* HDMISTREAMCLK_CNTL->HDMISTREAMCLK0_DTO_FORCE_DIS from dccg31_set_hdmistreamclk() DTO force bypass */
+		uint32_t hdmistreamclk_dto_phase;        /* HDMISTREAMCLK0_DTO_PARAM->HDMISTREAMCLK0_DTO_PHASE from dccg31_disable_hdmistreamclk() */
+		uint32_t hdmistreamclk_dto_modulo;       /* HDMISTREAMCLK0_DTO_PARAM->HDMISTREAMCLK0_DTO_MODULO from dccg31_disable_hdmistreamclk() */
+
 		/* DPIA Clock Control */
 		uint32_t dpiaclk_540m_dto_modulo;        /* DPIACLK_540M_DTO_MODULO->DPIA 540MHz DTO modulo */
 		uint32_t dpiaclk_540m_dto_phase;         /* DPIACLK_540M_DTO_PHASE->DPIA 540MHz DTO phase */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h b/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h
index fcd3ab4b0045..afd21eb6bbcd 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h
@@ -65,19 +65,65 @@ struct dp_hdmi_dongle_signature_data {
 #define HDMI_SCDC_CONFIG_1 0x31
 #define HDMI_SCDC_SOURCE_TEST_REQ 0x35
 #define HDMI_SCDC_STATUS_FLAGS 0x40
+#define HDMI_SCDC_LTP_REQ 0x41
 #define HDMI_SCDC_ERR_DETECT 0x50
 #define HDMI_SCDC_TEST_CONFIG 0xC0
 
 #define HDMI_SCDC_MANUFACTURER_OUI 0xD0
 #define HDMI_SCDC_DEVICE_ID 0xDB
 
+/* IDCC defines (HDMI 2.0) */
+#define HDMI_IDCC_ADDRESS 0x50
+#define HDMI_IDCC_MARKER0 0xAE
+#define HDMI_IDCC_MARKER1 0x6E
+#define HDMI_IDCC_MARKER2 0x60
+
+enum hdmi_idcc_scope {
+	HDMI_IDCC_SCOPE_WRITE = 0x00,
+	HDMI_IDCC_SCOPE_RW_CA = 0x01,
+	HDMI_IDCC_SCOPE_RW_SINK = 0x02,
+};
+
+union hdmi_idcc_source_id {
+	struct {
+		uint8_t SI_PCA_n:1;
+		uint8_t AC_n:1;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union hdmi_idcc_cable_id {
+	struct {
+		uint8_t Cat1_n:1;
+		uint8_t Cat2_n:1;
+		uint8_t Cat3_n:1;
+		uint8_t Cat4_n:1;
+		uint8_t RESERVED:4;
+		uint8_t HEAC_n:1;
+		uint8_t PCA_DEP_n:1;
+		uint8_t MonoDir_n:1;
+		uint8_t MonoDirErr_n:1;
+		uint8_t PCA_ON_n:1;
+		uint8_t no_DeEmphasis_n:1;
+		uint8_t no_PreShoot_n:1;
+		uint8_t RESERVED2:1;
+		uint8_t RND_bits_7_0:8;
+		uint8_t RND_bits_15_8:8;
+	} bits;
+	uint8_t raw[4];
+};
 union hdmi_scdc_update_read_data {
 	uint8_t byte[2];
 	struct {
 		uint8_t STATUS_UPDATE:1;
 		uint8_t CED_UPDATE:1;
 		uint8_t RR_TEST:1;
-		uint8_t RESERVED:5;
+		uint8_t SOURCE_TEST_UPDATE:1;
+		uint8_t FRL_START:1;
+		uint8_t FLT_UPDATE:1;
+		uint8_t RSED_UPDATE:1;
+		uint8_t RESERVED:1;
 		uint8_t RESERVED2:8;
 	} fields;
 };
@@ -89,7 +135,19 @@ union hdmi_scdc_status_flags_data {
 		uint8_t CH0_LOCKED:1;
 		uint8_t CH1_LOCKED:1;
 		uint8_t CH2_LOCKED:1;
-		uint8_t RESERVED:4;
+		uint8_t LANE3_LOCKED:1;
+		uint8_t RESERVED:1;
+		uint8_t FLT_READY:1;
+	} fields;
+};
+
+union hdmi_scdc_LTP_req_data {
+	uint8_t byte[2];
+	struct {
+		uint8_t LN0_LTP_REQ:4;
+		uint8_t LN1_LTP_REQ:4;
+		uint8_t LN2_LTP_REQ:4;
+		uint8_t LN3_LTP_REQ:4;
 	} fields;
 };
 
@@ -106,10 +164,12 @@ union hdmi_scdc_ced_data {
 		uint8_t CH2_7HIGH:7;
 		uint8_t CH2_VALID:1;
 		uint8_t CHECKSUM:8;
-		uint8_t RESERVED:8;
-		uint8_t RESERVED2:8;
-		uint8_t RESERVED3:8;
-		uint8_t RESERVED4:4;
+		uint8_t LN3_8LOW:8;
+		uint8_t LN3_7HIGH:7;
+		uint8_t LN3_VALID:1;
+		uint8_t RSC_8LOW:8;
+		uint8_t RSC_7HIGH:7;
+		uint8_t RSC_VALID:1;
 	} fields;
 };
 
@@ -130,4 +190,94 @@ union hdmi_scdc_device_id_data {
 	} fields;
 };
 
+union hdmi_scdc_configuration {
+	uint8_t byte[2];
+	struct {
+		uint8_t RR_ENABLE:1;
+		uint8_t FLT_NO_RETRAIN:1;
+		uint8_t RESERVED:6;
+		uint8_t FRL_RATE:4;
+		uint8_t FFE_LEVELS:4;
+	} fields;
+};
+
+union hdmi_scdc_source_test_req {
+	uint8_t byte;
+	struct {
+		uint8_t RESERVED:1;
+		uint8_t TXFFE_PRESHOOT:1;
+		uint8_t TXFFE_DEEMPHASIS:1;
+		uint8_t TXFFE_NOFFE:1;
+		uint8_t RESERVED2:1;
+		uint8_t FLT_NO_TIMEOUT:1;
+		uint8_t DSC_FRL_MAX:1;
+		uint8_t FRL_MAX:1;
+	} fields;
+};
+
+union hdmi_scdc_test_config_Data {
+	uint8_t byte;
+	struct {
+		uint8_t TEST_READ_REQUEST_DELAY:7;
+		uint8_t TEST_READ_REQUEST: 1;
+	} fields;
+};
+
+enum hdmi_frl_borrow_mode {
+	BORROW_MODE_NONE,
+	BORROW_MODE_FROM_ACTIVE,
+	BORROW_MODE_FROM_BLANK
+};
+
+enum link_result {
+	LINK_RESULT_UNKNOWN = 0,
+	LINK_RESULT_SUCCESS,
+	LINK_RESULT_LOWER_LINKRATE,
+	LINK_RESULT_TIMEOUT,
+	LINK_RESULT_FALLBACK
+};
+
+enum hdmi_frl_link_rate {
+	HDMI_FRL_LINK_RATE_DISABLE = 0,
+	HDMI_FRL_LINK_RATE_3GBPS,
+	HDMI_FRL_LINK_RATE_6GBPS,
+	HDMI_FRL_LINK_RATE_6GBPS_4LANE,
+	HDMI_FRL_LINK_RATE_8GBPS,
+	HDMI_FRL_LINK_RATE_10GBPS,
+	HDMI_FRL_LINK_RATE_12GBPS,
+	HDMI_FRL_LINK_RATE_16GBPS,
+	HDMI_FRL_LINK_RATE_20GBPS,
+	HDMI_FRL_LINK_RATE_24GBPS
+};
+
+struct frl_borrow_params {
+	int audio_packets_line;
+	int hc_active_target;
+	int hc_blank_target;
+	enum hdmi_frl_borrow_mode borrow_mode;
+};
+
+struct dc_hdmi_frl_link_settings {
+	enum hdmi_frl_link_rate frl_link_rate;
+	uint8_t frl_num_lanes;
+	struct frl_borrow_params borrow_params;
+	int average_tribyte_rate;
+};
+
+struct dc_hdmi_frl_flags {
+	int  force_frl_rate;
+	bool ignore_ffe;
+	int  select_ffe;
+	int  limit_ffe;
+	bool force_frl_always;
+	bool force_frl_max;
+	bool apply_vsdb_rcc_wa;
+};
+
+struct dc_hdmi_frl_link_training_overrides {
+	bool force_frl_always;
+	bool force_frl_max;
+	uint8_t max_retries;
+	bool valid;
+};
 #endif /* DC_HDMI_TYPES_H */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index c2ca08d26e37..c13a824c9d35 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -886,6 +886,8 @@ struct dc_dsc_config {
 	bool ycbcr422_simple; /* Tell DSC engine to convert YCbCr 4:2:2 to 'YCbCr 4:2:2 simple'. */
 	int32_t rc_buffer_size; /* DSC RC buffer block size in bytes */
 	bool is_frl; /* indicate if DSC is applied based on HDMI FRL sink's capability */
+	bool is_vic_all_bpp; /* indicate of DSC_ALL_BPP = 1 */
+	uint32_t total_chunk_kbytes; /* total chunk kbytes in EDID */
 	bool is_dp; /* indicate if DSC is applied based on DP's capability */
 	uint32_t mst_pbn; /* pbn of display on dsc mst hub */
 	const struct dc_dsc_rc_params_override *rc_params_ovrd; /* DM owned memory. If not NULL, apply custom dsc rc params */
@@ -1162,6 +1164,12 @@ struct tg_color {
 	uint16_t color_b_cb;
 };
 
+struct fva_adj {
+	unsigned int pixel_clock_100hz;
+	unsigned int max_pixel_clock_100hz;
+	unsigned int fva_factor;
+};
+
 enum symclk_state {
 	SYMCLK_OFF_TX_OFF,
 	SYMCLK_ON_TX_ON,
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 3ec49f4e277f..4ed1efa17270 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -77,6 +77,7 @@ struct dc_perf_trace {
 };
 
 #define NUM_PIXEL_FORMATS 10
+#define DTBCLK_LIMIT 2920
 
 enum tiling_mode {
 	TILING_MODE_INVALID,
@@ -174,6 +175,14 @@ struct dc_panel_patch {
 	unsigned int max_dsc_target_bpp_limit;
 	unsigned int embedded_tiled_slave;
 	unsigned int disable_fams;
+	unsigned int hdmi_spe_handling;
+	unsigned int block_420_Freesync;
+	unsigned int block_10g;
+	unsigned int hdmi_comp_manual;
+	unsigned int hdmi_comp_auto;
+	unsigned int force_frl;
+	unsigned int vsdb_rcc_wa;
+	unsigned int delay_hdmi_link_training;
 	unsigned int skip_avmute;
 	unsigned int skip_audio_sab_check;
 	unsigned int mst_start_top_delay;
@@ -221,6 +230,17 @@ struct dc_edid_caps {
 	bool scdc_present;
 	bool analog;
 
+	/*HDMI 2.1 caps*/
+	uint8_t max_frl_rate;
+	bool frl_dsc_support;
+	bool frl_dsc_10bpc;
+	bool frl_dsc_12bpc;
+	bool frl_dsc_all_bpp;
+	bool frl_dsc_native_420;
+	uint8_t frl_dsc_max_slices;
+	uint8_t frl_dsc_max_frl_rate;
+	uint8_t frl_dsc_total_chunk_kbytes;
+
 	struct dc_panel_patch panel_patch;
 };
 
@@ -545,6 +565,7 @@ struct audio_info {
 struct audio_check {
 	unsigned int audio_packet_type;
 	unsigned int max_audiosample_rate;
+	unsigned int max_channel_count;
 	unsigned int acat;
 };
 enum dc_infoframe_type {
@@ -929,6 +950,9 @@ struct dsc_dec_dpcd_caps {
 	uint32_t branch_overall_throughput_0_mps; /* In MPs */
 	uint32_t branch_overall_throughput_1_mps; /* In MPs */
 	uint32_t branch_max_line_width;
+	bool is_frl; /* Decoded format */
+	bool is_vic_all_bpp;
+	uint32_t total_chunk_kbytes;
 	bool is_dp; /* Decoded format */
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h b/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h
index f4d3f04ec857..cb20bfe9c1c8 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h
@@ -41,6 +41,7 @@ struct cp_psp_stream_config {
 	uint8_t phy_idx;
 	uint8_t assr_enabled;
 	uint8_t mst_enabled;
+	uint8_t frl_enabled;
 	uint8_t dp2_enabled;
 	uint8_t usb4_enabled;
 	void *dm_stream_ctx;
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 3b093b8699ab..e676e395cabf 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
@@ -292,6 +292,7 @@ struct dm_process_phy_transition_init_params {
 	enum dc_link_rate display_port_link_rate;
 	uint32_t transition_bitmask;
 	uint8_t hdmi_frl_num_lanes;
+	enum hdmi_frl_link_rate hdmi_frl_link_rate;
 };
 
 struct dm_process_phy_transition_input_params {
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_frl_cap_chk.h b/drivers/gpu/drm/amd/display/dc/dml/dml1_frl_cap_chk.h
new file mode 100644
index 000000000000..debe4c1dc0f7
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_frl_cap_chk.h
@@ -0,0 +1,173 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2022 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 __DML1_FRL_CAP_CHK_H__
+#define __DML1_FRL_CAP_CHK_H__
+
+#include "os_types.h"
+
+#define TB_BORROWED_MAX	  400
+#define C_FRL_CB	  510
+#define TOLERANCE_FRL_BIT 300    /* ppm */
+#define ACR_RATE_MAX	  1500
+
+enum hdmi_frl_pixel_encoding {
+	HDMI_FRL_PIXEL_ENCODING_444,
+	HDMI_FRL_PIXEL_ENCODING_422,
+	HDMI_FRL_PIXEL_ENCODING_420
+};
+
+enum frl_cap_chk_result {
+	FRL_CAP_CHK_OK = 0,
+
+	FRL_CAP_CHK_ERROR_AUDIO_BW   = -1,
+	FRL_CAP_CHK_ERROR_BORROW     = -2,
+	FRL_CAP_CHK_ERROR_MAX_BORROW = -3,
+	FRL_CAP_CHK_ERROR_MARGIN     = -4,
+
+	FRL_CAP_CHK_ERROR_UNSUPPORTED_AUDIO = -1000
+};
+
+enum frl_borrow_mode {
+	FRL_BORROW_MODE_NONE,
+	FRL_BORROW_MODE_FROM_ACTIVE,
+	FRL_BORROW_MODE_FROM_BLANK
+};
+
+enum frl_link_rate {
+	FRL_LINK_RATE_DISABLE = 0,
+	FRL_LINK_RATE_3GBPS,
+	FRL_LINK_RATE_6GBPS,
+	FRL_LINK_RATE_6GBPS_4LANE,
+	FRL_LINK_RATE_8GBPS,
+	FRL_LINK_RATE_10GBPS,
+	FRL_LINK_RATE_12GBPS,
+	FRL_LINK_RATE_16GBPS,
+	FRL_LINK_RATE_20GBPS,
+	FRL_LINK_RATE_24GBPS
+};
+
+struct frl_dml_borrow_params {
+	int audio_packets_line;
+	int hc_active_target;
+	int hc_blank_target;
+	enum frl_borrow_mode borrow_mode;
+};
+
+struct frl_primary_format {
+	uint32_t vic;
+	uint32_t frl_rate;
+	uint32_t frl_lanes;
+	uint32_t hc_active;
+	uint32_t hc_blank;
+};
+
+struct frl_cap_chk_intermediates {
+	int      c_frl_sb;
+	double   overhead_sb;
+	double   overhead_rs;
+	double   overhead_map;
+	double   overhead_min;
+	double   overhead_max;
+	double   f_pixel_clock_max;
+	double   t_line;
+	double   r_bit_min;
+	double   r_frl_char_min;
+	double   c_frl_line;
+	double   ap;
+	double   r_ap;
+	double   avg_audio_packets_line;
+	int      audio_packets_line;
+	int      blank_audio_min;
+};
+
+struct frl_cap_chk_params {
+	int      lanes;
+	double   f_pixel_clock_nominal;   /* Pixel Clock rate (Hz)  */
+	double   r_bit_nominal;           /* FRL bitrate (bps) */
+	int      audio_packet_type;
+	double   f_audio;                 /* Audio rate (Hz) */
+	int      h_active;                /* Active pixels per line */
+	int      h_blank;                 /* Blanking pixels per line */
+	int      bpc;                     /* Bits per component */
+	int      vic;                     /* Video Identification Code */
+
+	enum hdmi_frl_pixel_encoding    pixel_encoding;
+
+	bool     compressed;              /* set to true if DSC is enabled */
+	bool     bypass_hc_target_calc;   /* debug only */
+	bool     allow_all_bpp;           /* dsc_all_bpp */
+
+	/* DSC parameters */
+	int      slices;
+	int      slice_width;
+	double   bpp_target;
+	bool     is_ovt;
+	int      layout;
+	int      acat;    /* not supported */
+
+	/* outputs */
+	struct frl_dml_borrow_params borrow_params;
+	int      average_tribyte_rate;
+};
+
+enum frl_cap_chk_result dml1_frl_cap_chk(struct frl_cap_chk_params *params);
+
+enum frl_cap_chk_result dml1_frl_cap_chk_inter(struct frl_cap_chk_params *params,
+					       struct frl_cap_chk_intermediates *inter);
+
+enum frl_cap_chk_result dml1_frl_cap_chk_common(struct frl_cap_chk_intermediates *inter,
+						struct frl_cap_chk_params *params);
+
+enum frl_cap_chk_result dml1_frl_cap_chk_uncompressed(struct frl_cap_chk_params *params,
+						      struct frl_cap_chk_intermediates *inter);
+
+enum frl_cap_chk_result dml1_frl_cap_chk_compressed(struct frl_cap_chk_params *params,
+						    struct frl_cap_chk_intermediates *inter);
+#endif
+
+void frl_modified_pix_clock_for_dsc_padding(const int hc_active_target,
+	const int hc_blank_target,
+	const uint8_t frl_num_lanes,
+	const uint32_t pix_clk_100hz,
+	const int frl_link_rate,
+	const uint32_t h_addressable,
+	const uint32_t h_border_left,
+	const uint32_t h_border_right,
+	const uint32_t h_total,
+	const uint32_t h_addressable_otg,
+	uint32_t *pix_clk_100hz_otg,
+	uint32_t *h_total_otg);
+
+int frl_modify_borrow_mode_for_dsc_padding(const uint32_t pix_clk_100hz,
+	const uint32_t h_active,
+	const uint32_t h_active_padded,
+	const uint32_t h_blank,
+	const uint32_t h_blank_padded,
+	const int hc_active,
+	const int hc_blank,
+	const uint8_t frl_num_lanes,
+	const int frl_link_rate);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h
index 82085d9c3f40..388f801f4582 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h
@@ -48,6 +48,8 @@ enum dc_status {
 	DC_FAIL_DSC_VALIDATE = 16,
 	DC_NO_DSC_RESOURCE = 17,
 	DC_FAIL_UNSUPPORTED_1 = 18,
+	DC_FAIL_HDMI_FRL_LINK_TRAINING = 19,
+	DC_NO_HDMI_FRL_LINK_BANDWIDTH = 20,
 	DC_FAIL_CLK_EXCEED_MAX = 21,
 	DC_FAIL_CLK_BELOW_MIN = 22, /*THIS IS MIN PER IP*/
 	DC_FAIL_CLK_BELOW_CFG_REQUIRED = 23, /*THIS IS hard_min in PPLIB*/
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index a99e1937f8ce..cbbc1fb4b3dd 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -82,6 +82,9 @@ struct resource_funcs {
 	/* Create a minimal link encoder object with no dc_link object
 	 * associated with it. */
 	struct link_encoder *(*link_enc_create_minimal)(struct dc_context *ctx, enum engine_id eng_id);
+	struct hpo_frl_link_encoder *(*hpo_frl_link_enc_create)(
+			enum engine_id eng_id,
+			struct dc_context *ctx);
 	enum dc_status (*validate_bandwidth)(
 					struct dc *dc,
 					struct dc_state *context,
@@ -285,6 +288,10 @@ struct resource_pool {
 	/* Number of USB4 DPIA (DisplayPort Input Adapter) link objects created.*/
 	unsigned int usb4_dpia_count;
 
+	unsigned int hpo_frl_stream_enc_count;
+	struct hpo_frl_stream_encoder *hpo_frl_stream_enc[MAX_HDMI_FRL_ENCODERS];
+	unsigned int hpo_frl_link_enc_count;
+	struct hpo_frl_link_encoder *hpo_frl_link_enc[MAX_HDMI_FRL_ENCODERS];
 	unsigned int hpo_dp_stream_enc_count;
 	struct hpo_dp_stream_encoder *hpo_dp_stream_enc[MAX_HPO_DP2_ENCODERS];
 	unsigned int hpo_dp_link_enc_count;
@@ -351,6 +358,7 @@ struct stream_resource {
 	struct display_stream_compressor *dsc;
 	struct timing_generator *tg;
 	struct stream_encoder *stream_enc;
+	struct hpo_frl_stream_encoder *hpo_frl_stream_enc;
 	struct hpo_dp_stream_encoder *hpo_dp_stream_enc;
 	struct audio *audio;
 
@@ -394,6 +402,7 @@ struct plane_resource {
 struct link_resource {
 	struct link_encoder *dio_link_enc;
 	struct hpo_dp_link_encoder *hpo_dp_link_enc;
+	struct hpo_frl_link_encoder *hpo_frl_link_enc;
 };
 
 struct link_config {
@@ -531,6 +540,9 @@ struct resource_context {
 	struct link_enc_cfg_context link_enc_cfg_ctx;
 	unsigned int dio_link_enc_to_link_idx[MAX_LINK_ENCODERS];
 	int dio_link_enc_ref_cnts[MAX_LINK_ENCODERS];
+	bool is_hpo_frl_stream_enc_acquired[MAX_HDMI_FRL_ENCODERS];
+	unsigned int hpo_frl_link_enc_to_link_idx[MAX_HDMI_FRL_ENCODERS];
+	int hpo_frl_link_enc_ref_cnts[MAX_HDMI_FRL_ENCODERS];
 	bool is_hpo_dp_stream_enc_acquired[MAX_HPO_DP2_ENCODERS];
 	unsigned int hpo_dp_link_enc_to_link_idx[MAX_HPO_DP2_LINK_ENCODERS];
 	int hpo_dp_link_enc_ref_cnts[MAX_HPO_DP2_LINK_ENCODERS];
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
index d6f5e01a0b66..6db7c8753081 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
@@ -228,6 +228,16 @@ struct dccg_funcs {
 	void (*allow_clock_gating)(struct dccg *dccg, bool allow);
 	void (*enable_memory_low_power)(struct dccg *dccg, bool enable);
 	bool (*is_s0i3_golden_init_wa_done)(struct dccg *dccg);
+	void (*enable_hdmicharclk)(struct dccg *dccg, int hpo_inst, int phypll_inst);
+	void (*disable_hdmicharclk)(struct dccg *dccg, int hpo_inst);
+	void (*set_hdmistreamclk)(
+			struct dccg *dccg,
+			enum streamclk_source src,
+			uint32_t otg_inst);
+
+	void (*set_hdmistreamclk_root_clock_gating)(
+			struct dccg *dccg,
+			bool enable);
 	void (*set_dpstreamclk_root_clock_gating)(
 			struct dccg *dccg,
 			int dp_hpo_inst,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
index 51581c10fd6b..176d048a64e7 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
@@ -76,6 +76,7 @@
 #define MAX_LINK_ENCODERS (MAX_DIG_LINK_ENCODERS + MAX_DAC_LINK_ENCODERS)
 
 #define MAX_DWB_PIPES	1
+#define MAX_HDMI_FRL_ENCODERS	2
 #define MAX_HPO_DP2_ENCODERS	4
 #define MAX_HPO_DP2_LINK_ENCODERS	4
 
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
index 5abbf485d273..e7727ed3300c 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
@@ -67,6 +67,13 @@ struct encoder_feature_support {
 			uint32_t IS_UHBR13_5_CAPABLE:1;
 			uint32_t IS_UHBR20_CAPABLE:1;
 			uint32_t DP_IS_USB_C:1;
+			uint32_t IS_HDMI_FRL_CAPABLE:1;
+			uint32_t IS_FRL_8G_CAPABLE:1;
+			uint32_t IS_FRL_10G_CAPABLE:1;
+			uint32_t IS_FRL_12G_CAPABLE:1;
+			uint32_t IS_FRL_16G_CAPABLE:1;
+			uint32_t IS_FRL_20G_CAPABLE:1;
+			uint32_t IS_FRL_24G_CAPABLE:1;
 		} bits;
 		uint32_t raw;
 	} flags;
@@ -78,6 +85,11 @@ struct encoder_feature_support {
 	bool fec_supported;
 };
 
+enum phy_source_select {
+	PHY_SOURCE_DIG,
+	PHY_SOURCE_HPO
+};
+
 struct link_encoder {
 	const struct link_encoder_funcs *funcs;
 	int32_t aux_channel_offset;
@@ -93,6 +105,7 @@ struct link_encoder {
 	struct gpio *hpd_gpio;
 	enum hpd_source_id hpd_source;
 	bool usbc_combo_phy;
+	uint8_t txffe_state;
 };
 
 struct link_enc_state {
@@ -104,6 +117,12 @@ struct link_enc_state {
 
 };
 
+struct frl_txffe {
+	uint32_t   amplitude[4];
+	uint32_t   pre_emphasis[4];
+	uint32_t   post_emphasis[4];
+};
+
 enum encoder_type_select {
 	ENCODER_TYPE_DIG = 0,
 	ENCODER_TYPE_HDMI_FRL = 1,
@@ -172,6 +191,43 @@ struct link_encoder_funcs {
 	enum signal_type (*get_dig_mode)(
 		struct link_encoder *enc);
 
+	void (*dpcstx_set_order_invert_18_bit)(
+		struct link_encoder *enc,
+		bool invert);
+
+	void (*set_phy_source)(
+		struct link_encoder *enc,
+		enum phy_source_select src_sel,
+		uint32_t hpo_inst);
+
+	void (*dpcs_initialize_phy)(
+		struct link_encoder *enc,
+		uint32_t hpo_inst,
+		enum hdmi_frl_link_rate frl_link_rate);
+
+	void (*dpcs_configure_phypll)(
+		struct link_encoder *enc,
+		uint32_t hpo_inst,
+		enum hdmi_frl_link_rate frl_link_rate);
+
+	void (*dpcs_configure_dpcs)(
+		struct link_encoder *enc);
+
+	void (*dpcs_enable_dpcs)(
+		struct link_encoder *enc);
+	void (*prog_eq_setting)(
+		struct link_encoder *enc,
+		uint8_t FFE_Level,
+		bool de_emphasis_only,
+		bool pre_shoot_only,
+		bool no_ffe,
+		const struct dc_hdmi_frl_link_settings *link_settings);
+	void (*get_txffe)(
+		struct link_encoder *enc,
+		struct frl_txffe *lane_settings);
+	void (*set_txffe)(
+		struct link_encoder *enc,
+		struct frl_txffe *lane_settings);
 	void (*set_dio_phy_mux)(
 		struct link_encoder *enc,
 		enum encoder_type_select sel,
@@ -207,6 +263,126 @@ enum link_enc_cfg_mode {
 	LINK_ENC_CFG_TRANSIENT /* During commit state - use state to be committed. */
 };
 
+struct hpo_frl_link_encoder {
+	const struct hpo_frl_link_encoder_funcs *funcs;
+	struct dc_context *ctx;
+	int inst;
+};
+
+/**
+ * @hpo_frl_link_enc_state - FRL data from the device
+ *
+ * This struct is used to store FRL information retrieved from the hardware.
+ * This is used as a parameter for the read_state function.
+ */
+struct hpo_frl_link_enc_state {
+	/**
+	 * @link_enc_enabled: 0 means disable and 1 enabled.
+	 */
+	uint32_t link_enc_enabled;
+
+	/**
+	 * @link_active:
+	 *
+	 * If link training is enable this field should be set to 1.
+	 */
+	uint32_t link_active;
+
+	/**
+	 * @lane_count: FRL lane count.
+	 */
+	uint32_t lane_count;
+};
+
+/***
+ * @hpo_frl_link_encoder_funcs - FRL encoder functions
+ *
+ * DC handles FRL as an encoder; each ASIC may have some peculiarities in
+ * setting FRL. Thus, this struct, adds all the necessary callbacks that each
+ * DCN version must implement.
+ */
+struct hpo_frl_link_encoder_funcs {
+	/**
+	 * @setup_link_encoder:
+	 *
+	 * This function is responsible for setup the ASIC to use FRL, i.e., it
+	 * contains a register configuration. This function implementation
+	 * expects the enablement of the link clock, lane count configuration,
+	 * any reset/cleanup, and, finally, the enablement of the link.
+	 */
+	void (*setup_link_encoder)(struct hpo_frl_link_encoder *enc,
+				   int lane_count);
+
+	/**
+	 * @disable_link_encoder:
+	 *
+	 * Disable the FRL link. Note that this function must do the reverse of
+	 * the setup_link_encoder.
+	 */
+	void (*disable_link_encoder)(struct hpo_frl_link_encoder *enc);
+
+	/**
+	 * @set_hdmi_training_pattern:
+	 *
+	 * Register level configuration for each lane.
+	 */
+	void (*set_hdmi_training_pattern)(struct hpo_frl_link_encoder *enc,
+					  uint32_t lane0_pattern,
+					  uint32_t lane1_pattern,
+					  uint32_t lane2_pattern,
+					  uint32_t lane3_pattern);
+
+	/**
+	 * @get_hdmi_training_pattern:
+	 *
+	 * Retrieve from the registers each of the lane pattern configurations.
+	 */
+	void (*get_hdmi_training_pattern)(struct hpo_frl_link_encoder *enc,
+					  uint32_t *lane0_pattern,
+					  uint32_t *lane1_pattern,
+					  uint32_t *lane2_pattern,
+					  uint32_t *lane3_pattern);
+
+	/**
+	 * @enable_frl_phy_output:
+	 *
+	 * Based on the parameters, this function should fill out the
+	 * bp_transmitter_control struct and use it to enable the FRL PHY link
+	 * via VBIOS.
+	 */
+	void (*enable_frl_phy_output)(struct hpo_frl_link_encoder *hpo_enc,
+				      struct link_encoder *enc,
+				      enum clock_source_id clock_source,
+				      enum hdmi_frl_link_rate frl_link_rate);
+
+	/**
+	 * @enable_output:
+	 *
+	 * Enable FRL by sending the enable packet training.
+	 */
+	void (*enable_output)(struct hpo_frl_link_encoder *enc);
+
+	/**
+	 * @read_state:
+	 *
+	 * Get the FRL information from registers and fill it out in the
+	 * hpo_frl_link_enc_state struct.
+	 */
+	void (*read_state)(struct hpo_frl_link_encoder *enc,
+			   struct hpo_frl_link_enc_state *state);
+
+	/**
+	 * @destroy:
+	 *
+	 * Destroy encoder object.
+	 */
+	void (*destroy)(struct hpo_frl_link_encoder **enc);
+
+	void (*apply_vsdb_rcc_wa)(
+		struct hpo_frl_link_encoder *enc);
+
+};
+
 enum dp2_link_mode {
 	DP2_LINK_TRAINING_TPS1,
 	DP2_LINK_TRAINING_TPS2,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
index a9bf960dacbc..22d5f291c7db 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
@@ -71,6 +71,16 @@ enum dynamic_metadata_mode {
 	dmdata_dolby_vision
 };
 
+struct frl_audio_clock_info {
+	uint32_t frl_character_clock_kHz;
+	uint32_t n_32khz;
+	uint32_t cts_32khz;
+	uint32_t n_44khz;
+	uint32_t cts_44khz;
+	uint32_t n_48khz;
+	uint32_t cts_48khz;
+};
+
 struct enc_sdp_line_num {
 	/* Adaptive Sync SDP */
 	bool adaptive_sync_line_num_valid;
@@ -278,6 +288,223 @@ struct stream_encoder_funcs {
 	uint32_t (*get_pixels_per_cycle)(struct stream_encoder *enc);
 };
 
+/**
+ * @hpo_frl_stream_encoder_state - Stream encoder parameters
+ */
+struct hpo_frl_stream_encoder_state {
+	uint32_t stream_enc_enabled;
+	uint32_t otg_inst;
+	uint32_t color_depth;
+	uint32_t num_odm_segments;
+	uint32_t h_active;
+	uint32_t h_blank;
+	uint32_t borrow_mode;
+	enum dc_pixel_encoding pixel_format;
+};
+
+/**
+ * @hpo_frl_stream_encoder - Encoder stream instance
+ *
+ * This struct keeps the reference to the struct with the FRL stream encoder
+ * callbacks. Additionally, it has other references that simplify the stream
+ * configuration.
+ */
+struct hpo_frl_stream_encoder {
+	/**
+	 * @funcs: callback functions for using FRL stream encoder.
+	 */
+	const struct hpo_frl_stream_encoder_funcs *funcs;
+
+	/**
+	 * @stream_enc_inst: Instance ID reference.
+	 */
+	uint32_t stream_enc_inst;
+
+	/**
+	 * @ctx: DC context.
+	 */
+	struct dc_context *ctx;
+
+	/**
+	 * @bp: Bios parser reference.
+	 */
+	struct dc_bios *bp;
+
+	/**
+	 * @id: ID to the Engine object type.
+	 */
+	enum engine_id id;
+
+	/**
+	 * @afmt:
+	 *
+	 * Audio Formatter (AFMT) reference used for select the correct audio
+	 * reference.
+	 */
+	struct afmt *afmt;
+
+	/**
+	 * @vpg:
+	 *
+	 * The VBI Packet Generator (VPG) reference which is used for
+	 * generating the HDMI data island packet headers for ISRC1 and generic
+	 * packages.
+	 */
+	struct vpg *vpg;
+
+	/**
+	 * @afmt:
+	 *
+	 * Audio Pattern Generator (APG) reference used for select the correct audio
+	 * reference.
+	 */
+	struct apg *apg;
+};
+
+/**
+ * @hpo_frl_stream_encoder_funcs - FRL stream encoder functions callbacks
+ *
+ * DC must set up the FRL encoder and the stream encoder; however, each ASIC
+ * may have some quirks in setting FRL. Thus, this struct, adds all the encoder
+ * stream interfaces for setup the FRL stream encoder.
+ */
+struct hpo_frl_stream_encoder_funcs {
+	/**
+	 * @hdmi_frl_enable:
+	 *
+	 * This callback initializes a new FRL stream by enabling HDMI Dispclk,
+	 * SOCCLK, and HDMI stream clock. Additionally, this callback is also
+	 * used to initialize some debug options, such as the CRC validation.
+	 * Finally, it must setup the OTG instance.
+	 */
+	void (*hdmi_frl_enable)(struct hpo_frl_stream_encoder *enc,
+				int otg_inst);
+
+	/**
+	 * @hdmi_frl_unblank:
+	 *
+	 * Ensure that the FIFO video stream is active, reset the necessary
+	 * FIFO registers, enable HDMI tribyte encoder, and finally, adjust the
+	 * clock ramp registers for FIFO. Notice that all the configuration
+	 * made by this function it is at the register level.
+	 */
+	void (*hdmi_frl_unblank)(struct hpo_frl_stream_encoder *enc,
+				 int otg_inst);
+
+	/**
+	 * @hdmi_frl_blank:
+	 *
+	 * This callback is a register-level configuration that must disable
+	 * the clock ramp adjuster FIFO, disable the HDMI Tribyte encoder, and
+	 * disable the stream clocks (dispclk, socclk, and hdmistreamclk).
+	 */
+	void (*hdmi_frl_blank)(struct hpo_frl_stream_encoder *enc);
+
+	/**
+	 * @hdmi_frl_fifo_odm_enabled:
+	 *
+	 * This callback checks if the FIFO ODM Combine mode is enabled
+	 */
+	bool (*hdmi_frl_fifo_odm_enabled)(struct hpo_frl_stream_encoder *enc);
+
+	/**
+	 * @hdmi_frl_set_stream_attribute:
+	 *
+	 * This callback should be invoked only after the link is trained. The
+	 * implementation should configure the pixel encode, color depth, ODM
+	 * mode, configure horizontal blank/active size, configure borrow
+	 * parameters, enable general control packet, enable/setup audio, and
+	 * AVMute.
+	 */
+	void (*hdmi_frl_set_stream_attribute)(struct hpo_frl_stream_encoder *enc,
+					      struct dc_crtc_timing *crtc_timing,
+					      struct frl_borrow_params *borrow_params,
+					      int odm_combine_num_segments);
+
+	/**
+	 * @update_hdmi_info_packets:
+	 *
+	 * Update the HDMI packet control option.
+	 */
+	void (*update_hdmi_info_packets)(struct hpo_frl_stream_encoder *enc,
+					 const struct encoder_info_frame *info_frame);
+
+	/**
+	 * @stop_hdmi_info_packets:
+	 *
+	 * Update HDMI info packet (avi, vendoer, gamut, spd, hdrsmd, hfvsif,
+	 * vtem, etc).
+	 */
+	void (*stop_hdmi_info_packets)(struct hpo_frl_stream_encoder *enc);
+
+	/**
+	 * @audio_mute_control:
+	 *
+	 * Just mute the audio.
+	 */
+	void (*audio_mute_control)(struct hpo_frl_stream_encoder *enc,
+				   bool mute);
+
+	/**
+	 * @hdmi_audio_setup:
+	 *
+	 * Setup HDMI audio based on the Azila info.
+	 */
+	void (*hdmi_audio_setup)(struct hpo_frl_stream_encoder *enc,
+				 unsigned int az_inst,
+				 struct audio_info *info,
+				 struct audio_crtc_info *audio_crtc_info);
+
+	/**
+	 * @hdmi_audio_disable:
+	 *
+	 * Disable audio.
+	 */
+	void (*hdmi_audio_disable)(struct hpo_frl_stream_encoder *enc);
+
+	/**
+	 * @set_avmute:
+	 *
+	 * Disable AVmute at the register-level.
+	 */
+	void (*set_avmute)(struct hpo_frl_stream_encoder *enc, bool enable);
+
+	/**
+	 * @validate_hdmi_frl_output:
+	 *
+	 * Validate FRL inputs, DSC, audio parameters, FRL capacity, and borrow
+	 * parameters.
+	 */
+	bool (*validate_hdmi_frl_output)(struct hpo_frl_stream_encoder *enc,
+					 const struct dc_crtc_timing *timing,
+					 const struct audio_check *audio,
+					 struct dc_hdmi_frl_link_settings *frl_link_settings,
+					 unsigned int dsc_max_rate);
+
+	/**
+	 * @read_state:
+	 *
+	 * Fill out the hpo_frl_stream_encoder_state with the info retrieved
+	 * from ASIC registers.
+	 */
+	void (*read_state)(struct hpo_frl_stream_encoder *enc,
+			   struct hpo_frl_stream_encoder_state *state);
+
+	/**
+	 * @set_dynamic_metadata:
+	 *
+	 * Metadata configuration that sets:
+	 *  - Using Enfine or disable DME.
+	 *  - HUBP setup for the physical instance that has the DME enabled.
+	 *  - Metadata packet type.
+	 *  - Ensure OTG master update locks in the changing DME configuration.
+	 */
+	void (*set_dynamic_metadata)(struct hpo_frl_stream_encoder *enc,
+				     bool enable_dme,
+				     uint32_t hubp_requestor_id,
+				     enum dynamic_metadata_mode dmdata_mode);
+};
+
 struct hpo_dp_stream_encoder_state {
 	uint32_t stream_enc_enabled;
 	uint32_t vid_stream_enabled;
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
index 3a80369cde16..e4e17f630e97 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
@@ -106,6 +106,7 @@ enum crc_selection {
 
 enum otg_out_mux_dest {
 	OUT_MUX_DIO = 0,
+	OUT_MUX_HPO_FRL = 1,
 	OUT_MUX_HPO_DP = 2,
 };
 
@@ -493,6 +494,11 @@ struct timing_generator_funcs {
 	void (*set_out_mux)(struct timing_generator *tg, enum otg_out_mux_dest dest);
 	void (*set_drr_trigger_window)(struct timing_generator *optc,
 			uint32_t window_start, uint32_t window_end);
+	int (*set_fva_factor)(struct timing_generator *optc, struct fva_adj *fva_adj);
+	int (*get_max_hw_supported_fva_factor)(struct timing_generator *optc,
+		struct dc_crtc_timing *timing,
+		unsigned int max_pixclk_100hz);
+	void (*set_vstartup_dsc_frl)(struct timing_generator *optc);
 	void (*set_vtotal_change_limit)(struct timing_generator *optc,
 			uint32_t limit);
 	void (*align_vblanks)(struct timing_generator *master_optc,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_service.h b/drivers/gpu/drm/amd/display/dc/inc/link_service.h
index d0609443af49..23202c2114bb 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/link_service.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/link_service.h
@@ -144,6 +144,10 @@ struct link_service {
 	enum dc_status (*validate_dp_tunnel_bandwidth)(
 		const struct dc *dc,
 		const struct dc_state *new_ctx);
+	uint32_t (*frl_link_bandwidth_kbps)(enum hdmi_frl_link_rate link_rate);
+	bool (*frl_margin_check_uncompressed_video)(
+		struct frl_cap_chk_params_fixed31_32 *params,
+		struct frl_cap_chk_intermediates_fixed31_32 *inter);
 
 	uint32_t (*dp_required_hblank_size_bytes)(
 		const struct dc_link *link,
@@ -164,6 +168,7 @@ struct link_service {
 	void (*set_dsc_on_stream)(struct pipe_ctx *pipe_ctx, bool enable);
 	bool (*set_dsc_enable)(struct pipe_ctx *pipe_ctx, bool enable);
 	bool (*update_dsc_config)(struct pipe_ctx *pipe_ctx);
+	void (*wait_for_unlocked)(struct dc_link *link);
 
 
 	/*************************** DDC **************************************/
@@ -311,6 +316,16 @@ struct link_service {
 	void (*edp_set_panel_power)(struct dc_link *link, bool powerOn);
 
 
+	/*************************** HDMI FRL *********************************/
+	bool (*hdmi_frl_poll_status_flag)(struct dc_link *link);
+	struct dc_hdmi_frl_link_settings *(*hdmi_frl_get_verified_link_cap)(
+			struct dc_link *link);
+	void (*hdmi_frl_set_preferred_link_settings)(struct dc *dc,
+			struct dc_hdmi_frl_link_settings *link_setting,
+			struct dc_hdmi_frl_link_training_overrides *lt_overrides,
+			struct dc_link *link);
+
+
 	/*************************** DP CTS ************************************/
 	void (*dp_handle_automated_test)(struct dc_link *link);
 	bool (*dp_set_test_pattern)(
diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h
index cecd3282a29f..6352e078b132 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
@@ -57,6 +57,7 @@ struct resource_caps {
 	int num_dsc;
 	unsigned int num_dig_link_enc; // Total number of DIGs (digital encoders) in DIO (Display Input/Output).
 	unsigned int num_usb4_dpia; // Total number of USB4 DPIA (DisplayPort Input Adapters).
+	int num_hpo_frl;
 	int num_hpo_dp_stream_encoder;
 	int num_hpo_dp_link_encoder;
 	int num_mpc_3dlut;
@@ -86,6 +87,10 @@ struct resource_create_funcs {
 	struct stream_encoder *(*create_stream_encoder)(
 			enum engine_id eng_id, struct dc_context *ctx);
 
+	struct hpo_frl_stream_encoder *(*create_hpo_frl_stream_encoder)(
+			enum engine_id eng_id, struct dc_context *ctx);
+	struct hpo_frl_link_encoder *(*create_hpo_frl_link_encoder)(
+			enum engine_id eng_id, struct dc_context *ctx);
 	struct hpo_dp_stream_encoder *(*create_hpo_dp_stream_encoder)(
 			enum engine_id eng_id, struct dc_context *ctx);
 	struct hpo_dp_link_encoder *(*create_hpo_dp_link_encoder)(
@@ -604,6 +609,8 @@ unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format);
 bool get_temp_dp_link_res(struct dc_link *link,
 		struct link_resource *link_res,
 		struct dc_link_settings *link_settings);
+bool get_temp_frl_link_res(struct dc_link *link,
+		struct link_resource *link_res);
 
 void reset_syncd_pipes_from_disabled_pipes(struct dc *dc,
 	struct dc_state *context);
diff --git a/drivers/gpu/drm/amd/display/include/audio_types.h b/drivers/gpu/drm/amd/display/include/audio_types.h
index 6699ad4fa825..2a0f1a9c30a5 100644
--- a/drivers/gpu/drm/amd/display/include/audio_types.h
+++ b/drivers/gpu/drm/amd/display/include/audio_types.h
@@ -56,6 +56,7 @@ struct audio_crtc_info {
 	uint16_t refresh_rate;
 	uint8_t pixel_repetition;
 	bool interlaced;
+	uint32_t frl_character_clock_kHz; /* in KHz */
 };
 struct azalia_clock_info {
 	uint32_t pixel_clock_in_10khz;
diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h
index b5d97b394131..aeeac1f0c2c3 100644
--- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h
+++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h
@@ -329,7 +329,11 @@ struct bp_encoder_cap_info {
 	uint32_t DP_UHBR13_5_EN:1;
 	uint32_t DP_UHBR20_EN:1;
 	uint32_t DP_IS_USB_C:1;
-	uint32_t RESERVED:27;
+	uint32_t IS_HDMI_FRL_CAPABLE:1;
+	uint32_t FRL_8G_EN:1;
+	uint32_t FRL_10G_EN:1;
+	uint32_t FRL_12G_EN:1;
+	uint32_t RESERVED:19;
 };
 
 struct bp_soc_bb_info {
@@ -346,7 +350,13 @@ struct bp_connector_speed_cap_info {
 	uint32_t DP_UHBR13_5_EN:1;
 	uint32_t DP_UHBR20_EN:1;
 	uint32_t DP_IS_USB_C:1;
-	uint32_t RESERVED:28;
+	uint32_t FRL_8G_EN:1;
+	uint32_t FRL_10G_EN:1;
+	uint32_t FRL_12G_EN:1;
+	uint32_t FRL_16G_EN:1;
+	uint32_t FRL_20G_EN:1;
+	uint32_t FRL_24G_EN:1;
+	uint32_t RESERVED:19;
 };
 
 #endif /*__DAL_BIOS_PARSER_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h
index 177acb0574f1..a11bfb2e7cdd 100644
--- a/drivers/gpu/drm/amd/display/include/logger_types.h
+++ b/drivers/gpu/drm/amd/display/include/logger_types.h
@@ -62,6 +62,8 @@
 #define DC_LOG_ALL_TF_CHANNELS(...) pr_debug("[GAMMA]:"__VA_ARGS__)
 #define DC_LOG_DSC(...) drm_dbg_dp((DC_LOGGER)->dev, __VA_ARGS__)
 #define DC_LOG_SMU(...) pr_debug("[SMU_MSG]:"__VA_ARGS__)
+#define DC_LOG_HDMI_FRL(...) drm_dbg((DC_LOGGER)->dev, __VA_ARGS__)
+#define DC_LOG_HDMI_FRL_LTP(...) drm_dbg((DC_LOGGER)->dev, __VA_ARGS__)
 #define DC_LOG_DWB(...) drm_dbg((DC_LOGGER)->dev, __VA_ARGS__)
 #define DC_LOG_DP2(...) drm_dbg_dp((DC_LOGGER)->dev, __VA_ARGS__)
 #define DC_LOG_AUTO_DPM_TEST(...) pr_debug("[AutoDPMTest]: "__VA_ARGS__)
diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h
index 3a2c2d2fb629..9b134aa3e275 100644
--- a/drivers/gpu/drm/amd/display/include/signal_types.h
+++ b/drivers/gpu/drm/amd/display/include/signal_types.h
@@ -30,6 +30,8 @@
 #define TMDS_MIN_PIXEL_CLOCK 25000
 /* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */
 #define TMDS_MAX_PIXEL_CLOCK 165000
+/* Maximum pixel clock, in KHz. For HDMI2 TMDS signal is 600 MHz */
+#define HDMI2_TMDS_MAX_PIXEL_CLOCK 600000
 
 enum signal_type {
 	SIGNAL_TYPE_NONE		= 0L,		/* no signal */
@@ -41,6 +43,7 @@ enum signal_type {
 	SIGNAL_TYPE_DISPLAY_PORT	= (1 << 5),
 	SIGNAL_TYPE_DISPLAY_PORT_MST	= (1 << 6),
 	SIGNAL_TYPE_EDP			= (1 << 7),
+	SIGNAL_TYPE_HDMI_FRL		= (1 << 8),
 	SIGNAL_TYPE_VIRTUAL		= (1 << 9),	/* Virtual Display */
 };
 
@@ -65,6 +68,8 @@ static inline const char *signal_type_to_string(const int type)
 		return "Display Port: MST";
 	case SIGNAL_TYPE_EDP:
 		return "Embedded Display Port";
+	case SIGNAL_TYPE_HDMI_FRL:
+		return "HDMI: FRL";
 	case SIGNAL_TYPE_VIRTUAL:
 		return "Virtual";
 	default:
@@ -78,9 +83,14 @@ static inline bool dc_is_hdmi_tmds_signal(enum signal_type signal)
 	return (signal == SIGNAL_TYPE_HDMI_TYPE_A);
 }
 
+static inline bool dc_is_hdmi_frl_signal(enum signal_type signal)
+{
+	return ((signal == SIGNAL_TYPE_HDMI_FRL));
+}
+
 static inline bool dc_is_hdmi_signal(enum signal_type signal)
 {
-	return (signal == SIGNAL_TYPE_HDMI_TYPE_A);
+	return (dc_is_hdmi_tmds_signal(signal) || dc_is_hdmi_frl_signal(signal));
 }
 
 static inline bool dc_is_dp_sst_signal(enum signal_type signal)
-- 
2.54.0


  reply	other threads:[~2026-05-12 15:52 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-12 15:52 [PATCH v5 00/13] HDMI FRL and DSC Support for amdgpu Harry Wentland
2026-05-12 15:52 ` Harry Wentland [this message]
2026-05-12 15:52 ` [PATCH v5 02/13] drm/amd/display: Add DML changes to support HDMI FRL Harry Wentland
2026-05-12 15:52 ` [PATCH v5 03/13] drm/amd/display: add HDMI 2.1 FRL base support to DML 2.0 Harry Wentland
2026-05-12 15:52 ` [PATCH v5 04/13] drm/amd/display: Add DCCG DIO, HPO, OPP, and OPTC support for FRL Harry Wentland
2026-05-12 15:52 ` [PATCH v5 05/13] drm/amd/display: Add FRL support to clk_mgr, dsc, hdcp Harry Wentland
2026-05-12 15:52 ` [PATCH v5 06/13] drm/amd/display: Tie FRL programming together in HWSS Harry Wentland
2026-05-12 15:52 ` [PATCH v5 07/13] drm/amd/display: Add DC resource support for FRL Harry Wentland
2026-05-12 15:52 ` [PATCH v5 08/13] drm/amd/display Add DC link " Harry Wentland
2026-05-12 15:52 ` [PATCH v5 09/13] drm/amd/display: Add support for FRL to DC core Harry Wentland
2026-05-12 15:52 ` [PATCH v5 10/13] drm/amd/display: Update HDCP and info_packet modules for FRL Harry Wentland
2026-05-12 15:52 ` [PATCH v5 11/13] drm/amd/display: Tie FRL support into amdgpu_dm Harry Wentland
2026-05-13  0:11   ` [PATCH] drm/amd/display: fix FRL link-status polling never running dyllan
2026-05-12 15:52 ` [PATCH v5 12/13] drm/amd/display: add HDMI 2.1 Compliance Support Harry Wentland
2026-05-12 15:52 ` [PATCH v5 13/13] drm/amd/display: add HDMI 2.1 DSC over FRL support Harry Wentland
2026-05-17 18:58 ` [PATCH v5 00/13] HDMI FRL and DSC Support for amdgpu Tomasz Pakuła

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260512155244.403854-2-harry.wentland@amd.com \
    --to=harry.wentland@amd.com \
    --cc=Jerry.Zuo@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox