dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [RFC 00/15] Add support for HDMI2.1 FRL
@ 2022-11-07  7:20 Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 01/15] drm/edid: Add helper to get max FRL rate for an HDMI sink Ankit Nautiyal
                   ` (14 more replies)
  0 siblings, 15 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

This set is RFC for adding support for HDMI2.1 FRL Link training.
FRL or Fixed Rate Link is defined by HDMI2.1 spec for supporting higher
bit-rate. As per HDMI2.1 specification, a new data-channel or lane is
added in FRL mode, by repurposing the TMDS clock Channel. This enables
HDMI to support 48 Gbps bandwidth (i.e. bit rate of 12 Gbps/lane for 4
lanes).

This series is a step for Native HDMI2.1 support for MTL and to begin
discussion on the Fixed Rate Link Training part. It adds new structures,
registers and functions for facilitating FRL training for HDMI2.1.
Basically it provides the support for starting the Link training for a
given bit rate and lane count.

The appropriate bit rate and lanes need to be computed in the compute
config phase for HDMI, for a given video-mode, which is not part of this
series, but can be built on the basic structures and new members added
in this series. The FRL Training will take place only when we take a
decision to go for FRL mode and set the crtc_state parameters
appropriately during compute config phase.

The first 2 patches are prep work to have helper for getting MAX
FRL rate for existing DP-to HDMI2.1 PCON and Native HDMI2.1 from an
older series: https://patchwork.freedesktop.org/series/99311/

As HDMI2.1 needs C20 PHY, there is dependency on patch series from
Mika: https://patchwork.freedesktop.org/series/109714/
Therefore Patch 3 which adds the C10/C20 registers, is taken from the
above series for completeness, and FRL bits are added on top of that.

Ankit Nautiyal (13):
  drm/edid: Add helper to get max FRL rate for an HDMI sink
  drm/i915/dp: Use the drm helpers for getting max FRL rate
  drm/i915/hdmi21/mtl: Add new data members for FRL configuration
  drm/drm_scdc_helper: Add SCDC helper funcs for HDMI2.1
  drm/i915/mtl: Add registers for FRL Link Training
  drm/i915/mtl: Add HDMI2.1 bits in PORT_BUF_CTL_1
  drm/i915/mtl: Add port_data/data width for TRANS_DDI_FUNC and
    DDI_BUF_CTL
  drm/i915/display/mtl: Add new members in crtc_state for FRL
    configuration
  drm/i915/display/mtl: Update Transcoder/DDI registers with the frl
    bits
  drm/i915/display/mtl: Reset FRL Transcoder config while disabling HDMI
  drm/i915/hdmi21/mtl: Enable Scrambling only for FRL mode
  drm/i915/hdmi21/mtl: Add support for sending uevent to user for FRL
    training failure
  drm/i915/display/mtl: Add functions for FRL trainining state machine

Mika Kahola (1):
  drm/i915/mtl: Create separate reg file for PICA registers

Vandita Kulkarni (1):
  drm/i915/hdmi21/mtl: Parse frl max link rate from vbt

 drivers/gpu/drm/display/drm_scdc_helper.c     | 196 ++++++++
 drivers/gpu/drm/drm_edid.c                    |  38 ++
 drivers/gpu/drm/i915/display/intel_bios.c     |  51 ++
 drivers/gpu/drm/i915/display/intel_bios.h     |   1 +
 .../gpu/drm/i915/display/intel_cx0_reg_defs.h | 144 ++++++
 drivers/gpu/drm/i915/display/intel_ddi.c      |  63 ++-
 .../drm/i915/display/intel_display_types.h    |  32 ++
 drivers/gpu/drm/i915/display/intel_dp.c       |  17 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c     | 443 +++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_hdmi.h     |   2 +
 drivers/gpu/drm/i915/display/intel_vbt_defs.h |   7 +
 drivers/gpu/drm/i915/i915_reg.h               |  33 +-
 include/drm/display/drm_scdc.h                |  23 +
 include/drm/display/drm_scdc_helper.h         |  21 +
 include/drm/drm_edid.h                        |   2 +
 15 files changed, 1052 insertions(+), 21 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h

-- 
2.25.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [RFC 01/15] drm/edid: Add helper to get max FRL rate for an HDMI sink
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 02/15] drm/i915/dp: Use the drm helpers for getting max FRL rate Ankit Nautiyal
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

Add the helpers for getting the max FRL rate with and without DSC
for an HDMI sink.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/drm_edid.c | 38 ++++++++++++++++++++++++++++++++++++++
 include/drm/drm_edid.h     |  2 ++
 2 files changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index b2d61c05f559..5961399c31ba 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -7182,3 +7182,41 @@ static void _drm_update_tile_info(struct drm_connector *connector,
 		connector->tile_group = NULL;
 	}
 }
+
+/**
+ * drm_hdmi_sink_max_frl_rate - get the max frl rate, if supported
+ * @connector - connector with HDMI sink
+ *
+ * RETURNS:
+ * max frl rate supported by the HDMI sink, 0 if FRL not supported
+ */
+int drm_hdmi_sink_max_frl_rate(struct drm_connector *connector)
+{
+	int max_lanes = connector->display_info.hdmi.max_lanes;
+	int rate_per_lane = connector->display_info.hdmi.max_frl_rate_per_lane;
+
+	return max_lanes * rate_per_lane;
+}
+EXPORT_SYMBOL(drm_hdmi_sink_max_frl_rate);
+
+/**
+ * drm_hdmi_sink_dsc_max_frl_rate - get the max frl rate from HDMI sink with
+ * DSC1.2 compression.
+ * @connector - connector with HDMI sink
+ *
+ * RETURNS:
+ * max frl rate supported by the HDMI sink with DSC1.2, 0 if FRL not supported
+ */
+int drm_hdmi_sink_dsc_max_frl_rate(struct drm_connector *connector)
+{
+	int max_dsc_lanes, dsc_rate_per_lane;
+
+	if (!connector->display_info.hdmi.dsc_cap.v_1p2)
+		return 0;
+
+	max_dsc_lanes = connector->display_info.hdmi.dsc_cap.max_lanes;
+	dsc_rate_per_lane = connector->display_info.hdmi.dsc_cap.max_frl_rate_per_lane;
+
+	return max_dsc_lanes * dsc_rate_per_lane;
+}
+EXPORT_SYMBOL(drm_hdmi_sink_dsc_max_frl_rate);
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 372963600f1d..c567826eee58 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -611,5 +611,7 @@ int drm_edid_connector_update(struct drm_connector *connector,
 			      const struct drm_edid *edid);
 const u8 *drm_find_edid_extension(const struct drm_edid *drm_edid,
 				  int ext_id, int *ext_index);
+int drm_hdmi_sink_max_frl_rate(struct drm_connector *connector);
+int drm_hdmi_sink_dsc_max_frl_rate(struct drm_connector *connector);
 
 #endif /* __DRM_EDID_H__ */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 02/15] drm/i915/dp: Use the drm helpers for getting max FRL rate
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 01/15] drm/edid: Add helper to get max FRL rate for an HDMI sink Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 03/15] drm/i915/mtl: Create separate reg file for PICA registers Ankit Nautiyal
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

Re-use the drm helpers for getting max FRL rate for an HDMI sink.
This patch removes the duplicate code and calls the already defined
drm helpers for the task.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 17 ++++-------------
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 7400d6b4c587..ef2383ca8d7d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2398,20 +2398,11 @@ static int intel_dp_hdmi_sink_max_frl(struct intel_dp *intel_dp)
 {
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
 	struct drm_connector *connector = &intel_connector->base;
-	int max_frl_rate;
-	int max_lanes, rate_per_lane;
-	int max_dsc_lanes, dsc_rate_per_lane;
+	int max_frl_rate = drm_hdmi_sink_max_frl_rate(connector);
+	int dsc_max_frl_rate = drm_hdmi_sink_dsc_max_frl_rate(connector);
 
-	max_lanes = connector->display_info.hdmi.max_lanes;
-	rate_per_lane = connector->display_info.hdmi.max_frl_rate_per_lane;
-	max_frl_rate = max_lanes * rate_per_lane;
-
-	if (connector->display_info.hdmi.dsc_cap.v_1p2) {
-		max_dsc_lanes = connector->display_info.hdmi.dsc_cap.max_lanes;
-		dsc_rate_per_lane = connector->display_info.hdmi.dsc_cap.max_frl_rate_per_lane;
-		if (max_dsc_lanes && dsc_rate_per_lane)
-			max_frl_rate = min(max_frl_rate, max_dsc_lanes * dsc_rate_per_lane);
-	}
+	if (dsc_max_frl_rate)
+		return min(max_frl_rate, dsc_max_frl_rate);
 
 	return max_frl_rate;
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 03/15] drm/i915/mtl: Create separate reg file for PICA registers
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 01/15] drm/edid: Add helper to get max FRL rate for an HDMI sink Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 02/15] drm/i915/dp: Use the drm helpers for getting max FRL rate Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 04/15] drm/i915/hdmi21/mtl: Parse frl max link rate from vbt Ankit Nautiyal
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

From: Mika Kahola <mika.kahola@intel.com>

(Patch is part of the series to add C10/C20 PHY support, which is in
review : https://patchwork.freedesktop.org/series/109714/)

Create a separate file to store registers for PICA chips
C10 and C20.

Signed-off-by: Radhakrishna Sripada <radhakrishna.sripada@intel.com>
Signed-off-by: Mika Kahola <mika.kahola@intel.com>
---
 .../gpu/drm/i915/display/intel_cx0_reg_defs.h | 136 ++++++++++++++++++
 1 file changed, 136 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h b/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h
new file mode 100644
index 000000000000..dfe156141d73
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef __INTEL_CX0_REG_DEFS_H__
+#define __INTEL_CX0_REG_DEFS_H__
+
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A		0x64040
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B		0x64140
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1		0x16F240
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2		0x16F440
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC3		0x16F640
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC4		0x16F840
+#define _XELPDP_PORT_M2P_MSGBUS_CTL(port, lane)		(_PICK(port, \
+							 [PORT_A] = _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A, \
+							 [PORT_B] = _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B, \
+							 [PORT_TC1] = _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1, \
+							 [PORT_TC2] = _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2, \
+							 [PORT_TC3] = _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC3, \
+							 [PORT_TC4] = _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC4) + ((lane) * 4))
+
+#define XELPDP_PORT_M2P_MSGBUS_CTL(port, lane)		_MMIO(_XELPDP_PORT_M2P_MSGBUS_CTL(port, lane))
+#define  XELPDP_PORT_M2P_TRANSACTION_PENDING		REG_BIT(31)
+#define  XELPDP_PORT_M2P_COMMAND_TYPE_MASK		REG_GENMASK(30, 27)
+#define  XELPDP_PORT_M2P_COMMAND_WRITE_UNCOMMITTED	REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x1)
+#define  XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED	REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x2)
+#define  XELPDP_PORT_M2P_COMMAND_READ			REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x3)
+#define  XELPDP_PORT_M2P_DATA_MASK			REG_GENMASK(23, 16)
+#define  XELPDP_PORT_M2P_DATA(val)			REG_FIELD_PREP(XELPDP_PORT_M2P_DATA_MASK, val)
+#define  XELPDP_PORT_M2P_TRANSACTION_RESET		REG_BIT(15)
+#define  XELPDP_PORT_M2P_ADDRESS_MASK			REG_GENMASK(11, 0)
+#define  XELPDP_PORT_M2P_ADDRESS(val)			REG_FIELD_PREP(XELPDP_PORT_M2P_ADDRESS_MASK, val)
+
+#define XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane)	_MMIO(_XELPDP_PORT_M2P_MSGBUS_CTL(port, lane) + 8)
+#define  XELPDP_PORT_P2M_RESPONSE_READY			REG_BIT(31)
+#define  XELPDP_PORT_P2M_COMMAND_TYPE_MASK		REG_GENMASK(30, 27)
+#define  XELPDP_PORT_P2M_COMMAND_READ_ACK		0x4
+#define  XELPDP_PORT_P2M_COMMAND_WRITE_ACK		0x5
+#define  XELPDP_PORT_P2M_DATA_MASK			REG_GENMASK(23, 16)
+#define  XELPDP_PORT_P2M_DATA(val)			REG_FIELD_PREP(XELPDP_PORT_P2M_DATA_MASK, val)
+#define  XELPDP_PORT_P2M_ERROR_SET			REG_BIT(15)
+
+#define  XELPDP_MSGBUS_TIMEOUT_SLOW			1
+#define  XELPDP_MSGBUS_TIMEOUT_FAST_US			2
+#define XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US		3200
+#define XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US		20
+#define XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US		100
+#define XELPDP_PORT_RESET_START_TIMEOUT_US		5
+#define XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US		100
+#define XELPDP_PORT_RESET_END_TIMEOUT			15
+#define XELPDP_REFCLK_ENABLE_TIMEOUT_US			1
+
+#define _XELPDP_PORT_BUF_CTL1_LN0_A			0x64004
+#define _XELPDP_PORT_BUF_CTL1_LN0_B			0x64104
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC1			0x16F200
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC2			0x16F400
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC3			0x16F600
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC4			0x16F800
+#define _XELPDP_PORT_BUF_CTL1(port)			(_PICK(port, \
+							 [PORT_A] = _XELPDP_PORT_BUF_CTL1_LN0_A, \
+							 [PORT_B] = _XELPDP_PORT_BUF_CTL1_LN0_B, \
+							 [PORT_TC1] = _XELPDP_PORT_BUF_CTL1_LN0_USBC1, \
+							 [PORT_TC2] = _XELPDP_PORT_BUF_CTL1_LN0_USBC2, \
+							 [PORT_TC3] = _XELPDP_PORT_BUF_CTL1_LN0_USBC3, \
+							 [PORT_TC4] = _XELPDP_PORT_BUF_CTL1_LN0_USBC4))
+
+#define XELPDP_PORT_BUF_CTL1(port)			_MMIO(_XELPDP_PORT_BUF_CTL1(port))
+#define  XELPDP_PORT_BUF_SOC_PHY_READY			REG_BIT(24)
+#define  XELPDP_PORT_REVERSAL				REG_BIT(16)
+
+#define  XELPDP_TC_PHY_OWNERSHIP			REG_BIT(6)
+#define  XELPDP_TCSS_POWER_REQUEST			REG_BIT(5)
+#define  XELPDP_TCSS_POWER_STATE			REG_BIT(4)
+#define  XELPDP_PORT_WIDTH_MASK				REG_GENMASK(3, 1)
+#define  XELPDP_PORT_WIDTH(val)				REG_FIELD_PREP(XELPDP_PORT_WIDTH_MASK, val)
+
+#define XELPDP_PORT_BUF_CTL2(port)			_MMIO(_XELPDP_PORT_BUF_CTL1(port) + 4)
+#define  XELPDP_LANE0_PIPE_RESET			REG_BIT(31)
+#define  XELPDP_LANE1_PIPE_RESET			REG_BIT(30)
+#define  XELPDP_LANE0_PHY_CURRENT_STATUS		REG_BIT(29)
+#define  XELPDP_LANE1_PHY_CURRENT_STATUS		REG_BIT(28)
+#define  XELPDP_LANE0_POWERDOWN_UPDATE			REG_BIT(25)
+#define  XELPDP_LANE1_POWERDOWN_UPDATE			REG_BIT(24)
+#define  XELPDP_LANE0_POWERDOWN_NEW_STATE_MASK		REG_GENMASK(23, 20)
+#define  XELPDP_LANE0_POWERDOWN_NEW_STATE(val)		REG_FIELD_PREP(XELPDP_LANE0_POWERDOWN_NEW_STATE_MASK, val)
+#define  XELPDP_LANE1_POWERDOWN_NEW_STATE_MASK		REG_GENMASK(19, 16)
+#define  XELPDP_LANE1_POWERDOWN_NEW_STATE(val)		REG_FIELD_PREP(XELPDP_LANE1_POWERDOWN_NEW_STATE_MASK, val)
+#define  XELPDP_POWER_STATE_READY_MASK			REG_GENMASK(7, 4)
+#define  XELPDP_POWER_STATE_READY(val)			REG_FIELD_PREP(XELPDP_POWER_STATE_READY_MASK, val)
+
+#define XELPDP_PORT_BUF_CTL3(port)			_MMIO(_XELPDP_PORT_BUF_CTL1(port) + 8)
+#define  XELPDP_PLL_LANE_STAGGERING_DELAY_MASK		REG_GENMASK(15, 8)
+#define  XELPDP_PLL_LANE_STAGGERING_DELAY(val)		REG_FIELD_PREP(XELPDP_PLL_LANE_STAGGERING_DELAY_MASK, val)
+#define  XELPDP_POWER_STATE_ACTIVE_MASK			REG_GENMASK(3, 0)
+#define  XELPDP_POWER_STATE_ACTIVE(val)			REG_FIELD_PREP(XELPDP_POWER_STATE_ACTIVE_MASK, val)
+
+#define _XELPDP_PORT_CLOCK_CTL_A			0x640E0
+#define _XELPDP_PORT_CLOCK_CTL_B			0x641E0
+#define _XELPDP_PORT_CLOCK_CTL_USBC1			0x16F260
+#define _XELPDP_PORT_CLOCK_CTL_USBC2			0x16F460
+#define _XELPDP_PORT_CLOCK_CTL_USBC3			0x16F660
+#define _XELPDP_PORT_CLOCK_CTL_USBC4			0x16F860
+#define XELPDP_PORT_CLOCK_CTL(port)			_MMIO(_PICK(port, \
+							[PORT_A] = _XELPDP_PORT_CLOCK_CTL_A, \
+							[PORT_B] = _XELPDP_PORT_CLOCK_CTL_B, \
+							[PORT_TC1] = _XELPDP_PORT_CLOCK_CTL_USBC1, \
+							[PORT_TC2] = _XELPDP_PORT_CLOCK_CTL_USBC2, \
+							[PORT_TC3] = _XELPDP_PORT_CLOCK_CTL_USBC3, \
+							[PORT_TC4] = _XELPDP_PORT_CLOCK_CTL_USBC4))
+
+#define XELPDP_LANE0_PCLK_PLL_REQUEST			REG_BIT(31)
+#define XELPDP_LANE0_PCLK_PLL_ACK			REG_BIT(30)
+#define XELPDP_LANE0_PCLK_REFCLK_REQUEST		REG_BIT(29)
+#define XELPDP_LANE0_PCLK_REFCLK_ACK			REG_BIT(28)
+#define XELPDP_LANE1_PCLK_PLL_REQUEST			REG_BIT(27)
+#define XELPDP_LANE1_PCLK_PLL_ACK			REG_BIT(26)
+#define XELPDP_LANE1_PCLK_REFCLK_REQUEST		REG_BIT(25)
+#define XELPDP_LANE1_PCLK_REFCLK_ACK			REG_BIT(24)
+#define XELPDP_TBT_CLOCK_REQUEST			REG_BIT(19)
+#define XELPDP_TBT_CLOCK_ACK				REG_BIT(18)
+#define XELPDP_DDI_CLOCK_SELECT_MASK			REG_GENMASK(15, 12)
+#define XELPDP_DDI_CLOCK_SELECT(val)			REG_FIELD_PREP(XELPDP_DDI_CLOCK_SELECT_MASK, val)
+#define XELPDP_DDI_CLOCK_SELECT_NONE			0x0
+#define XELPDP_DDI_CLOCK_SELECT_MAXPCLK			0x8
+#define XELPDP_DDI_CLOCK_SELECT_DIV18CLK		0x9
+#define XELPDP_DDI_CLOCK_SELECT_TBT_162			0xc
+#define XELPDP_DDI_CLOCK_SELECT_TBT_270			0xd
+#define XELPDP_DDI_CLOCK_SELECT_TBT_540			0xe
+#define XELPDP_DDI_CLOCK_SELECT_TBT_810			0xf
+#define XELPDP_FORWARD_CLOCK_UNGATE			REG_BIT(10)
+#define XELPDP_LANE1_PHY_CLOCK_SELECT			REG_BIT(8)
+#define XELPDP_SSC_ENABLE_PLLA				REG_BIT(1)
+#define XELPDP_SSC_ENABLE_PLLB				REG_BIT(0)
+
+#endif /* __INTEL_CX0_REG_DEFS_H__ */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 04/15] drm/i915/hdmi21/mtl: Parse frl max link rate from vbt
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
                   ` (2 preceding siblings ...)
  2022-11-07  7:20 ` [RFC 03/15] drm/i915/mtl: Create separate reg file for PICA registers Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 05/15] drm/i915/hdmi21/mtl: Add new data members for FRL configuration Ankit Nautiyal
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

From: Vandita Kulkarni <vandita.kulkarni@intel.com>

From the max_frl_rate field of vbt parse the maxfrl_rate.

Signed-off-by: Vandita Kulkarni <vandita.kulkarni@intel.com>
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c     | 51 +++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_bios.h     |  1 +
 drivers/gpu/drm/i915/display/intel_vbt_defs.h |  7 +++
 3 files changed, 59 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index c2987f2c2b2e..14008fc4c9bf 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -2621,6 +2621,42 @@ static bool is_port_valid(struct drm_i915_private *i915, enum port port)
 	return true;
 }
 
+static int _intel_bios_hdmi_max_frl_rate(const struct intel_bios_encoder_data *devdata)
+{
+	struct drm_i915_private *i915 = devdata->i915;
+
+	if (i915->display.vbt.version >= 237 &&
+	    devdata->child.hdmi_max_frl_rate_valid) {
+		switch (devdata->child.hdmi_max_frl_rate) {
+		default:
+		case HDMI_MAX_FRL_RATE_PLATFORM:
+			drm_dbg_kms(&i915->drm, "HDMI2.1 is limited to support only TMDS modes\n");
+			return 0;
+		case HDMI_MAX_FRL_RATE_3G:
+			return 3000000;
+		case HDMI_MAX_FRL_RATE_6G:
+			return 6000000;
+		case HDMI_MAX_FRL_RATE_8G:
+			return 8000000;
+		case HDMI_MAX_FRL_RATE_10G:
+			return 10000000;
+		case HDMI_MAX_FRL_RATE_12G:
+			return 12000000;
+		}
+	}
+
+	/*
+	 * When hdmi_max_frl_rate_valid is 0
+	 * Don't consider the hdmi_max_frl_rate for
+	 * limiting the FrlRates on HDMI2.1 displays
+	 */
+	if (i915->display.vbt.version >= 237 &&
+	    IS_METEORLAKE(i915))
+		return 12000000;
+
+	return 0;
+}
+
 static void print_ddi_port(const struct intel_bios_encoder_data *devdata,
 			   enum port port)
 {
@@ -2628,6 +2664,7 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata,
 	const struct child_device_config *child = &devdata->child;
 	bool is_dvi, is_hdmi, is_dp, is_edp, is_crt, supports_typec_usb, supports_tbt;
 	int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock;
+	int hdmi_max_frl_rate;
 
 	is_dvi = intel_bios_encoder_supports_dvi(devdata);
 	is_dp = intel_bios_encoder_supports_dp(devdata);
@@ -2677,6 +2714,12 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata,
 			    "Port %c VBT DP max link rate: %d\n",
 			    port_name(port), dp_max_link_rate);
 
+	hdmi_max_frl_rate = _intel_bios_hdmi_max_frl_rate(devdata);
+	if (hdmi_max_frl_rate)
+		drm_dbg_kms(&i915->drm,
+			    "VBT HDMI max frl rate for port %c: %d\n",
+			    port_name(port), hdmi_max_frl_rate);
+
 	/*
 	 * FIXME need to implement support for VBT
 	 * vswing/preemph tables should this ever trigger.
@@ -3679,6 +3722,14 @@ int intel_bios_max_tmds_clock(struct intel_encoder *encoder)
 	return _intel_bios_max_tmds_clock(devdata);
 }
 
+int intel_bios_hdmi_max_frl_rate(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	const struct intel_bios_encoder_data *devdata = i915->display.vbt.ports[encoder->port];
+
+	return _intel_bios_hdmi_max_frl_rate(devdata);
+}
+
 /* This is an index in the HDMI/DVI DDI buffer translation table, or -1 */
 int intel_bios_hdmi_level_shift(struct intel_encoder *encoder)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
index e375405a7828..e3a8e8198881 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.h
+++ b/drivers/gpu/drm/i915/display/intel_bios.h
@@ -273,5 +273,6 @@ bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data
 bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devdata);
 int intel_bios_encoder_dp_boost_level(const struct intel_bios_encoder_data *devdata);
 int intel_bios_encoder_hdmi_boost_level(const struct intel_bios_encoder_data *devdata);
+int intel_bios_hdmi_max_frl_rate(struct intel_encoder *encoder);
 
 #endif /* _INTEL_BIOS_H_ */
diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
index a9f44abfc9fc..f7ecb82b0b3f 100644
--- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
@@ -320,6 +320,13 @@ struct bdb_general_features {
 #define HDMI_MAX_DATA_RATE_340		4			/* 249+ */
 #define HDMI_MAX_DATA_RATE_300		5			/* 249+ */
 
+#define HDMI_MAX_FRL_RATE_PLATFORM	0			/* 237 */
+#define HDMI_MAX_FRL_RATE_3G		1			/* 237 */
+#define HDMI_MAX_FRL_RATE_6G		2			/* 237 */
+#define HDMI_MAX_FRL_RATE_8G		3			/* 237 */
+#define HDMI_MAX_FRL_RATE_10G		4			/* 237 */
+#define HDMI_MAX_FRL_RATE_12G		5			/* 237 */
+
 #define LEGACY_CHILD_DEVICE_CONFIG_SIZE		33
 
 /* DDC Bus DDI Type 155+ */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 05/15] drm/i915/hdmi21/mtl: Add new data members for FRL configuration
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
                   ` (3 preceding siblings ...)
  2022-11-07  7:20 ` [RFC 04/15] drm/i915/hdmi21/mtl: Parse frl max link rate from vbt Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 06/15] drm/drm_scdc_helper: Add SCDC helper funcs for HDMI2.1 Ankit Nautiyal
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

HDMI2.1 supports higher resolutions using Fixed Rate Link.
Source need to do FRL link training on the 4 lanes before video
stream transmission.

This patch adds the members to crtc_state and intel_hdmi for
identifying the FRL supporting HDMI sink and to maintain the frl
training information, after successful training.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 .../drm/i915/display/intel_display_types.h    |  9 ++++++++
 drivers/gpu/drm/i915/display/intel_hdmi.c     | 22 +++++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index c6abaaa46e17..e57fac00e945 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1517,8 +1517,17 @@ struct intel_hdmi {
 	} dp_dual_mode;
 	bool has_hdmi_sink;
 	bool has_audio;
+	bool has_sink_hdmi_21;
+	int max_frl_rate;
+	int max_dsc_frl_rate;
 	struct intel_connector *attached_connector;
 	struct cec_notifier *cec_notifier;
+	struct {
+		bool trained;
+		int lanes;
+		int rate_gbps;
+		int ffe_level;
+	} frl;
 };
 
 struct intel_dp_mst_encoder;
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 02f8374ea51f..1dd0b0f2e2f1 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2346,6 +2346,7 @@ intel_hdmi_unset_edid(struct drm_connector *connector)
 
 	intel_hdmi->has_hdmi_sink = false;
 	intel_hdmi->has_audio = false;
+	intel_hdmi->has_sink_hdmi_21 = false;
 
 	intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE;
 	intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
@@ -2405,11 +2406,21 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector)
 	}
 }
 
+static void
+intel_hdmi_reset_frl_config(struct intel_hdmi *intel_hdmi)
+{
+	intel_hdmi->frl.trained = false;
+	intel_hdmi->frl.lanes = 0;
+	intel_hdmi->frl.rate_gbps = 0;
+	intel_hdmi->frl.ffe_level = 0;
+}
+
 static bool
 intel_hdmi_set_edid(struct drm_connector *connector)
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector));
+	struct intel_encoder *encoder = &hdmi_to_dig_port(intel_hdmi)->base;
 	intel_wakeref_t wakeref;
 	struct edid *edid;
 	bool connected = false;
@@ -2431,10 +2442,21 @@ intel_hdmi_set_edid(struct drm_connector *connector)
 
 	to_intel_connector(connector)->detect_edid = edid;
 	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
+		int src_rate_lane_gbps = DIV_ROUND_UP(intel_bios_hdmi_max_frl_rate(encoder),
+						      1000000);
+		int max_src_rate = src_rate_lane_gbps * 4;
+
 		intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
 		intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
 
 		intel_hdmi_dp_dual_mode_detect(connector);
+		intel_hdmi->has_sink_hdmi_21 =
+			drm_hdmi_sink_max_frl_rate(connector) > 0 ? true : false;
+		intel_hdmi->max_frl_rate = min(drm_hdmi_sink_max_frl_rate(connector),
+					       max_src_rate);
+		intel_hdmi->max_dsc_frl_rate = min(drm_hdmi_sink_dsc_max_frl_rate(connector),
+						   max_src_rate);
+		intel_hdmi_reset_frl_config(intel_hdmi);
 
 		connected = true;
 	}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 06/15] drm/drm_scdc_helper: Add SCDC helper funcs for HDMI2.1
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
                   ` (4 preceding siblings ...)
  2022-11-07  7:20 ` [RFC 05/15] drm/i915/hdmi21/mtl: Add new data members for FRL configuration Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 07/15] drm/i915/mtl: Add registers for FRL Link Training Ankit Nautiyal
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

HDMI2.1 specifies new SCDC registers to configure FRL Training
between source and sink and get the FRL Training updated from
and HDMI2.1 sink.

This patch adds new SCDC registers and helper functions to
read and configure these registers.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/display/drm_scdc_helper.c | 196 ++++++++++++++++++++++
 include/drm/display/drm_scdc.h            |  23 +++
 include/drm/display/drm_scdc_helper.h     |  21 +++
 3 files changed, 240 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_scdc_helper.c b/drivers/gpu/drm/display/drm_scdc_helper.c
index c3ad4ab2b456..dcf05167473d 100644
--- a/drivers/gpu/drm/display/drm_scdc_helper.c
+++ b/drivers/gpu/drm/display/drm_scdc_helper.c
@@ -261,3 +261,199 @@ bool drm_scdc_set_high_tmds_clock_ratio(struct i2c_adapter *adapter, bool set)
 	return true;
 }
 EXPORT_SYMBOL(drm_scdc_set_high_tmds_clock_ratio);
+
+/**
+ * drm_scdc_read_update_flags - read the SCDC update flags
+ * @adapter: I2C adapter for DDC channel
+ *
+ * Returns:
+ * 8bit SCDC update
+ */
+u8 drm_scdc_read_update_flags(struct i2c_adapter *adapter)
+{
+	u8 update = 0;
+	int ret;
+
+	ret = drm_scdc_readb(adapter, SCDC_UPDATE_0, &update);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Failed to read scdc update: %d\n", ret);
+
+	return update;
+}
+EXPORT_SYMBOL(drm_scdc_read_update_flags);
+
+/**
+ * drm_scdc_clear_update_flags - Clears the given update flag bits
+ * @adapter: I2C adapter for DDC channel
+ * @status: update flag bits to be cleared
+ *
+ * Returns:
+ * 0 on success, negative error code otherwise.
+ */
+int drm_scdc_clear_update_flags(struct i2c_adapter *adapter, u8 update_flags)
+{
+	u8 buf;
+	int ret;
+
+	/* Not all flags can be cleared by source */
+	if (update_flags & ~(SCDC_STATUS_UPDATE | SCDC_CED_UPDATE |
+			     SCDC_SOURCE_TEST_UPDATE | SCDC_FLT_UPDATE |
+			     SCDC_RSED_UPDATE)) {
+		DRM_DEBUG_KMS("SCDC Update flag/s %u cannot be cleared\n",
+			      update_flags);
+
+		return false;
+	}
+
+	ret = drm_scdc_readb(adapter, SCDC_UPDATE_0, &buf);
+	if (ret < 0) {
+		DRM_DEBUG_KMS("Failed to read SCDC_UPDATE_0\n");
+
+		return ret;
+	}
+
+	buf = buf | update_flags;
+
+	ret = drm_scdc_writeb(adapter, SCDC_UPDATE_0, buf);
+	if (ret < 0) {
+		DRM_DEBUG_KMS("Failed to clear SCDC Update flag/s\n");
+
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_scdc_clear_update_flags);
+
+/**
+ * drm_scdc_read_status_flags - Read the status flags from offset 0x40
+ * @adapter: I2C adapter for DDC channel
+ *
+ * Returns:
+ * 8 bit value read from the 0ffset 0x40
+ */
+u8 drm_scdc_read_status_flags(struct i2c_adapter *adapter)
+{
+	u8 update = 0;
+	int ret;
+
+	ret = drm_scdc_readb(adapter, SCDC_STATUS_FLAGS_0, &update);
+	if (ret < 0)
+		DRM_DEBUG_KMS("Failed to read scdc status flag: %d\n", ret);
+
+	return update;
+}
+EXPORT_SYMBOL(drm_scdc_read_status_flags);
+
+/**
+ * drm_scdc_config_frl - configure the sink for starting FRL training
+ * @adapter: I2C adapter for DDC channel
+ * @frl_rate: FRL rate per lane required.
+ * @num_lanes: no. of lanes required, can be either 3 or 4.
+ * @ffe_levelw: max FFE Levelw supported for current rate for the given FRL rate.
+ *
+ * Returns:
+ * 0 if the SCDC offsets for FRL training are successfully configure,
+ * negative error code otherwise.
+ */
+int drm_scdc_config_frl(struct i2c_adapter *adapter, int frl_rate,
+			int num_lanes, int ffe_levels)
+{
+	u8 write_buf = 0;
+	int ret;
+
+	if (num_lanes > 4 || num_lanes < 3) {
+		DRM_DEBUG_KMS("No. of lanes can be 3 or 4 only\n");
+
+		return -EINVAL;
+	}
+	if (ffe_levels > 3) {
+		DRM_DEBUG_KMS("Max FFE levels can be 3 or less\n");
+
+		return -EINVAL;
+	}
+	switch (frl_rate) {
+	case 3:
+		write_buf |= (num_lanes == 3) ? SCDC_FRL_RATE_3GBPS_3LANES : 0;
+		break;
+	case 6:
+		write_buf |= (num_lanes == 3) ? SCDC_FRL_RATE_6GBPS_3LANES :
+			     SCDC_FRL_RATE_6GBPS_4LANES;
+		break;
+	case 8:
+		write_buf |= (num_lanes == 4) ? SCDC_FRL_RATE_8GBPS_4LANES : 0;
+		break;
+	case 10:
+		write_buf |= (num_lanes == 4) ? SCDC_FRL_RATE_10GBPS_4LANES : 0;
+		break;
+	case 12:
+		write_buf |= (num_lanes == 4) ? SCDC_FRL_RATE_12GBPS_4LANES : 0;
+		break;
+	default:
+		write_buf |= SCDC_FRL_DISABLE;
+	}
+
+	write_buf |= (ffe_levels << SCDC_FFE_LEVELS_SHIFT);
+
+	ret = drm_scdc_writeb(adapter, SCDC_CONFIG_1, write_buf);
+	if (ret < 0) {
+		DRM_DEBUG_KMS("Failed to write SCDC config: %d\n", ret);
+
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_scdc_config_frl);
+
+/**
+ * drm_scdc_get_ltp - get the Link training patterns for the 4 lanes
+ * @adapter: I2C adapter for DDC channel
+ * @ltp: pointer array for reading Link training patterns for the 4 lanes.
+ *
+ * Returns:
+ * 0 on success also filling ltp out argument, negetive error code otherwise.
+ */
+int drm_scdc_get_ltp(struct i2c_adapter *adapter,
+		     enum drm_scdc_frl_ltp ltp[4])
+{
+	u8 buf;
+	u8 ltp_reg;
+	u8 ltp_mask;
+	int ret;
+	int lane;
+
+	for (lane = 0; lane < 4; lane++) {
+		switch (lane) {
+		case 0:
+			ltp_reg = SCDC_STATUS_FLAGS_1;
+			ltp_mask = SCDC_LN0_LTP_REQ;
+			break;
+		case 1:
+			ltp_reg = SCDC_STATUS_FLAGS_1;
+			ltp_mask = SCDC_LN1_LTP_REQ;
+			break;
+		case 2:
+			ltp_reg = SCDC_STATUS_FLAGS_2;
+			ltp_mask = SCDC_LN2_LTP_REQ;
+			break;
+		case 3:
+		default:
+			ltp_reg = SCDC_STATUS_FLAGS_2;
+			ltp_mask = SCDC_LN3_LTP_REQ;
+			break;
+		}
+		ret = drm_scdc_readb(adapter, ltp_reg, &buf);
+		if (ret < 0) {
+			DRM_DEBUG_KMS("Failed to read link training pattern for Lane%d: %d\n",
+				      lane, ret);
+
+			return ret;
+		}
+
+		ltp[lane] = (buf & ltp_mask) >> lane % 2;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_scdc_get_ltp);
diff --git a/include/drm/display/drm_scdc.h b/include/drm/display/drm_scdc.h
index 3d58f37e8ed8..c7e621f4cc31 100644
--- a/include/drm/display/drm_scdc.h
+++ b/include/drm/display/drm_scdc.h
@@ -29,6 +29,10 @@
 #define SCDC_SOURCE_VERSION 0x02
 
 #define SCDC_UPDATE_0 0x10
+#define  SCDC_RSED_UPDATE (1 << 6)
+#define  SCDC_FLT_UPDATE (1 << 5)
+#define  SCDC_FRL_START (1 << 4)
+#define  SCDC_SOURCE_TEST_UPDATE (1 << 3)
 #define  SCDC_READ_REQUEST_TEST (1 << 2)
 #define  SCDC_CED_UPDATE (1 << 1)
 #define  SCDC_STATUS_UPDATE (1 << 0)
@@ -46,7 +50,20 @@
 #define SCDC_CONFIG_0 0x30
 #define  SCDC_READ_REQUEST_ENABLE (1 << 0)
 
+#define SCDC_CONFIG_1 0x31
+#define  SCDC_FRL_DISABLE		0
+#define  SCDC_FRL_RATE_3GBPS_3LANES	1
+#define  SCDC_FRL_RATE_6GBPS_3LANES	2
+#define  SCDC_FRL_RATE_6GBPS_4LANES	3
+#define  SCDC_FRL_RATE_8GBPS_4LANES	4
+#define  SCDC_FRL_RATE_10GBPS_4LANES	5
+#define  SCDC_FRL_RATE_12GBPS_4LANES	6
+#define  SCDC_FFE_LEVELS_SHIFT		4
+
 #define SCDC_STATUS_FLAGS_0 0x40
+#define  SCDC_DSC_DECODE_FAIL (1 << 7)
+#define  SCDC_FLT_READY (1 << 6)
+#define  SCDC_LANE3_LOCKED (1 << 4)
 #define  SCDC_CH2_LOCK (1 << 3)
 #define  SCDC_CH1_LOCK (1 << 2)
 #define  SCDC_CH0_LOCK (1 << 1)
@@ -54,6 +71,12 @@
 #define  SCDC_CLOCK_DETECT (1 << 0)
 
 #define SCDC_STATUS_FLAGS_1 0x41
+#define  SCDC_LN0_LTP_REQ (0xF << 0)
+#define  SCDC_LN1_LTP_REQ (0xF << 4)
+
+#define SCDC_STATUS_FLAGS_2 0x42
+#define  SCDC_LN2_LTP_REQ (0xF << 0)
+#define  SCDC_LN3_LTP_REQ (0xF << 4)
 
 #define SCDC_ERR_DET_0_L 0x50
 #define SCDC_ERR_DET_0_H 0x51
diff --git a/include/drm/display/drm_scdc_helper.h b/include/drm/display/drm_scdc_helper.h
index ded01fd948b4..405386335f20 100644
--- a/include/drm/display/drm_scdc_helper.h
+++ b/include/drm/display/drm_scdc_helper.h
@@ -35,6 +35,20 @@ ssize_t drm_scdc_read(struct i2c_adapter *adapter, u8 offset, void *buffer,
 ssize_t drm_scdc_write(struct i2c_adapter *adapter, u8 offset,
 		       const void *buffer, size_t size);
 
+enum drm_scdc_frl_ltp {
+	SCDC_FRL_NO_LTP = 0,
+	SCDC_FRL_LTP1,
+	SCDC_FRL_LTP2,
+	SCDC_FRL_LTP3,
+	SCDC_FRL_LTP4,
+	SCDC_FRL_LTP5,
+	SCDC_FRL_LTP6,
+	SCDC_FRL_LTP7,
+	SCDC_FRL_LTP8,
+	SCDC_FRL_CHNG_FFE = 0xE,
+	SCDC_FRL_CHNG_RATE = 0xF,
+};
+
 /**
  * drm_scdc_readb - read a single byte from SCDC
  * @adapter: I2C adapter
@@ -75,5 +89,12 @@ bool drm_scdc_get_scrambling_status(struct i2c_adapter *adapter);
 
 bool drm_scdc_set_scrambling(struct i2c_adapter *adapter, bool enable);
 bool drm_scdc_set_high_tmds_clock_ratio(struct i2c_adapter *adapter, bool set);
+u8 drm_scdc_read_update_flags(struct i2c_adapter *adapter);
+int drm_scdc_clear_update_flags(struct i2c_adapter *adapter, u8 update_flags);
+u8 drm_scdc_read_status_flags(struct i2c_adapter *adapter);
+int drm_scdc_config_frl(struct i2c_adapter *adapter, int frl_rate,
+			int num_lanes, int ffe_levels);
+int drm_scdc_get_ltp(struct i2c_adapter *adapter,
+		     enum drm_scdc_frl_ltp ltp[4]);
 
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 07/15] drm/i915/mtl: Add registers for FRL Link Training
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
                   ` (5 preceding siblings ...)
  2022-11-07  7:20 ` [RFC 06/15] drm/drm_scdc_helper: Add SCDC helper funcs for HDMI2.1 Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 08/15] drm/i915/mtl: Add HDMI2.1 bits in PORT_BUF_CTL_1 Ankit Nautiyal
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

Add registers for FRL configuration.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 765a10e0de88..b50e1349d22c 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2121,6 +2121,28 @@
 #define   TRANS_PUSH_EN			REG_BIT(31)
 #define   TRANS_PUSH_SEND		REG_BIT(30)
 
+/* HDMI 2.1 FRL Configuration */
+#define _TRANS_HDMI_FRL_CFG_A		0x600B0
+#define TRANS_HDMI_FRL_CFG(trans)	_MMIO_TRANS2(trans, _TRANS_HDMI_FRL_CFG_A)
+#define TRANS_HDMI_FRL_ENABLE			REG_BIT(31)
+#define TRANS_HDMI_TMDS_ENABLE			0
+#define TRANS_HDMI_FRL_TRAINING_COMPLETE	REG_BIT(28)
+#define TRANS_HDMI_DISABLE_DFM_MASKING		REG_BIT(20)
+#define TRANS_HDMI_R_B_SCHED_ENABLE_MASK	REG_BIT(19)
+#define TRANS_HDMI_R_B_SCHED_ENABLE(val)	REG_FIELD_PREP(TRANS_HDMI_R_B_SCHED_ENABLE_MASK, val)
+#define TRANS_HDMI_ACTIVE_CHAR_BUF_THRESH_MASK	REG_GENMASK(18, 16)
+#define TRANS_HDMI_ACTIVE_CHAR_BUF_THRESH(val)	REG_FIELD_PREP(TRANS_HDMI_ACTIVE_CHAR_BUF_THRESH_MASK, val)
+#define TRANS_HDMI_MIN_BLANK_CHAR_MASK		REG_GENMASK(15, 12)
+#define TRANS_HDMI_MIN_BLANK_CHAR(val)		REG_FIELD_PREP(TRANS_HDMI_MIN_BLANK_CHAR_MASK, val)
+#define TRANS_HDMI_MIN_BLANK_CHAR_VAL           0xA
+#define TRANS_HDMI_FRL_PKT_PAYLOAD_MAX_MASK	REG_GENMASK(9, 0)
+#define TRANS_HDMI_FRL_PKT_PAYLOAD_MAX(val)	REG_FIELD_PREP(TRANS_HDMI_FRL_PKT_PAYLOAD_MAX_MASK, val)
+#define TRANS_HDMI_PAYLOAD_UPPER_BOUND		0x3FE
+
+#define _TRANS_HDMI_FRL_TRAIN_A			0x600B4
+#define TRANS_HDMI_FRL_TRAIN(trans)		_MMIO_TRANS2(trans, _TRANS_HDMI_FRL_TRAIN_A)
+#define  TRANS_HDMI_FRL_LTP(pattern, lane)	((pattern) << (lane) * 8)
+
 /*
  * HSW+ eDP PSR registers
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 08/15] drm/i915/mtl: Add HDMI2.1 bits in PORT_BUF_CTL_1
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
                   ` (6 preceding siblings ...)
  2022-11-07  7:20 ` [RFC 07/15] drm/i915/mtl: Add registers for FRL Link Training Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 09/15] drm/i915/mtl: Add port_data/data width for TRANS_DDI_FUNC and DDI_BUF_CTL Ankit Nautiyal
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

This patch adds bits related to HDMI2.1 in PORT_BUF_CTL_1 that
is needed to be programmed for D2D Interface for Ports in
IO expansion Die.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h b/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h
index dfe156141d73..efba0ce90229 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h
@@ -66,14 +66,22 @@
 							 [PORT_TC4] = _XELPDP_PORT_BUF_CTL1_LN0_USBC4))
 
 #define XELPDP_PORT_BUF_CTL1(port)			_MMIO(_XELPDP_PORT_BUF_CTL1(port))
+#define  XELPDP_PORT_BUF_D2D_LINK_ENABLE		REG_BIT(29)
+#define  XELPDP_PORT_BUF_D2D_LINK_STATE			REG_BIT(28)
 #define  XELPDP_PORT_BUF_SOC_PHY_READY			REG_BIT(24)
 #define  XELPDP_PORT_REVERSAL				REG_BIT(16)
+#define  XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK		REG_GENMASK(19, 18)
+#define  XELPDP_PORT_BUF_PORT_DATA_10BIT		REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 0)
+#define  XELPDP_PORT_BUF_PORT_DATA_20BIT		REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 1)
+#define  XELPDP_PORT_BUF_PORT_DATA_40BIT		REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 2)
 
+#define  XELPDP_PORT_BUF_PHY_IDLE			REG_BIT(7)
 #define  XELPDP_TC_PHY_OWNERSHIP			REG_BIT(6)
 #define  XELPDP_TCSS_POWER_REQUEST			REG_BIT(5)
 #define  XELPDP_TCSS_POWER_STATE			REG_BIT(4)
 #define  XELPDP_PORT_WIDTH_MASK				REG_GENMASK(3, 1)
 #define  XELPDP_PORT_WIDTH(val)				REG_FIELD_PREP(XELPDP_PORT_WIDTH_MASK, val)
+#define  XELPDP_PORT_HDMI_FRL_SHFTR_EN			REG_BIT(0)
 
 #define XELPDP_PORT_BUF_CTL2(port)			_MMIO(_XELPDP_PORT_BUF_CTL1(port) + 4)
 #define  XELPDP_LANE0_PIPE_RESET			REG_BIT(31)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 09/15] drm/i915/mtl: Add port_data/data width for TRANS_DDI_FUNC and DDI_BUF_CTL
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
                   ` (7 preceding siblings ...)
  2022-11-07  7:20 ` [RFC 08/15] drm/i915/mtl: Add HDMI2.1 bits in PORT_BUF_CTL_1 Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 10/15] drm/i915/display/mtl: Add new members in crtc_state for FRL configuration Ankit Nautiyal
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

This patch adds the bits for port width for TRANS_DDI_FUNC_CTL and
port data width for DDI_BUF_CTL.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index b50e1349d22c..8afe4b965463 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -6914,6 +6914,9 @@ enum skl_power_gate {
 #define  TRANS_DDI_HDCP_SELECT		REG_BIT(5)
 #define  TRANS_DDI_BFI_ENABLE		(1 << 4)
 #define  TRANS_DDI_HIGH_TMDS_CHAR_RATE	(1 << 4)
+#define  TRANS_DDI_PORT_WIDTH_MASK	REG_GENMASK(3, 1)
+#define  TRANS_DDI_PORT_WIDTH(width)	REG_FIELD_PREP(TRANS_DDI_PORT_WIDTH_MASK, (width) - 1)
+#define  TRANS_DDI_PORT_WIDTH_SHIFT	1
 #define  TRANS_DDI_HDMI_SCRAMBLING	(1 << 0)
 #define  TRANS_DDI_HDMI_SCRAMBLING_MASK (TRANS_DDI_HDMI_SCRAMBLER_CTS_ENABLE \
 					| TRANS_DDI_HDMI_SCRAMBLER_RESET_FREQ \
@@ -6979,11 +6982,15 @@ enum skl_power_gate {
 #define  DDI_BUF_EMP_MASK			(0xf << 24)
 #define  DDI_BUF_PHY_LINK_RATE(r)		((r) << 20)
 #define  DDI_BUF_PORT_REVERSAL			(1 << 16)
+#define  DDI_BUF_PORT_DATA_WIDTH_MASK		REG_GENMASK(19, 18)
+#define  DDI_BUF_PORT_DATA_10BIT		REG_FIELD_PREP(DDI_BUF_PORT_DATA_WIDTH_MASK, 0)
+#define  DDI_BUF_PORT_DATA_20BIT		REG_FIELD_PREP(DDI_BUF_PORT_DATA_WIDTH_MASK, 1)
+#define  DDI_BUF_PORT_DATA_40BIT		REG_FIELD_PREP(DDI_BUF_PORT_DATA_WIDTH_MASK, 2)
 #define  DDI_BUF_IS_IDLE			(1 << 7)
 #define  DDI_BUF_CTL_TC_PHY_OWNERSHIP		REG_BIT(6)
 #define  DDI_A_4_LANES				(1 << 4)
-#define  DDI_PORT_WIDTH(width)			(((width) - 1) << 1)
-#define  DDI_PORT_WIDTH_MASK			(7 << 1)
+#define  DDI_PORT_WIDTH_MASK			REG_GENMASK(3, 1)
+#define  DDI_PORT_WIDTH(width)			REG_FIELD_PREP(DDI_PORT_WIDTH_MASK, (width) - 1)
 #define  DDI_PORT_WIDTH_SHIFT			1
 #define  DDI_INIT_DISPLAY_DETECTED		(1 << 0)
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 10/15] drm/i915/display/mtl: Add new members in crtc_state for FRL configuration
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
                   ` (8 preceding siblings ...)
  2022-11-07  7:20 ` [RFC 09/15] drm/i915/mtl: Add port_data/data width for TRANS_DDI_FUNC and DDI_BUF_CTL Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 11/15] drm/i915/display/mtl: Update Transcoder/DDI registers with the frl bits Ankit Nautiyal
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

Add new struture to store FRL related configurations for a pipe.
These members to be calculated during compute config phase, when FRL
mode is to be used.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 .../drm/i915/display/intel_display_types.h    | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index e57fac00e945..8cab50d5d565 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1307,6 +1307,29 @@ struct intel_crtc_state {
 		u16 flipline, vmin, vmax, guardband;
 	} vrr;
 
+	struct {
+		/* Go for FRL training */
+		bool enable;
+
+		/* Enable resource based scheduling */
+		bool rsrc_sched_en;
+
+		/* can be either 3 or 4 lanes */
+		u8 required_lanes;
+
+		/* required rate - can be 3, 6, 8, 10, 12 Gbps */
+		u8 required_rate;
+
+		/* FRL DFM Parameters */
+		u32 tb_borrowed, tb_actual, tb_threshold_min, active_char_buf_threshold;
+
+		/* FRL DFM DSC Tribytes */
+		u32 hcactive_tb, hctotal_tb;
+
+		/* Clock parameters in KHz */
+		u32 div18, link_m_ext, link_n_ext;
+	} frl;
+
 	/* Stream Splitter for eDP MSO */
 	struct {
 		bool enable;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 11/15] drm/i915/display/mtl: Update Transcoder/DDI registers with the frl bits
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
                   ` (9 preceding siblings ...)
  2022-11-07  7:20 ` [RFC 10/15] drm/i915/display/mtl: Add new members in crtc_state for FRL configuration Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 12/15] drm/i915/display/mtl: Reset FRL Transcoder config while disabling HDMI Ankit Nautiyal
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

For platforms supporting HDMI2.1 we need to fill the lane count
in Transcoder and DDI/PORT registers for FRL mode.
Similarly, FRL SHIFTER ENABLE, and DATA_WIDTH bits are to be set
in FRL mode. These bits are written in both the DDI_BUF_CTL and
PORT_BUF_CTL registers.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 49 +++++++++++++++++++++---
 1 file changed, 44 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index e95bde5cf060..5e2e4c78c564 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -38,6 +38,7 @@
 #include "intel_combo_phy_regs.h"
 #include "intel_connector.h"
 #include "intel_crtc.h"
+#include "intel_cx0_reg_defs.h"
 #include "intel_ddi.h"
 #include "intel_ddi_buf_trans.h"
 #include "intel_de.h"
@@ -499,6 +500,8 @@ intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder,
 			temp |= TRANS_DDI_HDMI_SCRAMBLING;
 		if (crtc_state->hdmi_high_tmds_clock_ratio)
 			temp |= TRANS_DDI_HIGH_TMDS_CHAR_RATE;
+		if (crtc_state->frl.enable)
+			temp |= TRANS_DDI_PORT_WIDTH(crtc_state->lane_count);
 	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
 		temp |= TRANS_DDI_MODE_SELECT_FDI_OR_128B132B;
 		temp |= (crtc_state->fdi_lanes - 1) << 1;
@@ -2587,6 +2590,13 @@ static void intel_disable_ddi_buf(struct intel_encoder *encoder,
 
 	if (wait)
 		intel_wait_ddi_buf_idle(dev_priv, port);
+
+	/* Clear PORT_BUF_CTL */
+	if (crtc_state->frl.enable) {
+		val = intel_de_read(dev_priv, XELPDP_PORT_BUF_CTL1(port));
+		intel_de_write(dev_priv, XELPDP_PORT_BUF_CTL1(port),
+			       val & ~(XELPDP_PORT_HDMI_FRL_SHFTR_EN));
+	}
 }
 
 static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
@@ -2837,7 +2847,6 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
 	struct drm_connector *connector = conn_state->connector;
 	enum port port = encoder->port;
 	enum phy phy = intel_port_to_phy(dev_priv, port);
-	u32 buf_ctl;
 
 	if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
 					       crtc_state->hdmi_high_tmds_clock_ratio,
@@ -2894,13 +2903,43 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
 	 *
 	 * On ADL_P the PHY link rate and lane count must be programmed but
 	 * these are both 0 for HDMI.
+	 *
+	 * But MTL onwards HDMI2.1 is supported and in FRL mode, port width
+	 * needs to be filled with either 3 or 4 lanes. For TMDS mode this
+	 * is always filled with 4 lanes, already set in the crtc_state.
 	 */
-	buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE;
-	if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) {
+	if (DISPLAY_VER(dev_priv) > 13) {
+		u32 ddi_buf = 0;
+		u32 port_buf = intel_de_read(dev_priv, XELPDP_PORT_BUF_CTL1(port));
+
+		port_buf |= XELPDP_PORT_WIDTH(crtc_state->lane_count);
+		ddi_buf |= DDI_BUF_CTL_ENABLE |
+			   DDI_PORT_WIDTH(crtc_state->lane_count);
+
+		if (intel_bios_is_lane_reversal_needed(dev_priv, port))
+			port_buf |= XELPDP_PORT_REVERSAL;
+
+		if (crtc_state->frl.enable) {
+			port_buf |= XELPDP_PORT_HDMI_FRL_SHFTR_EN;
+			port_buf |= XELPDP_PORT_BUF_PORT_DATA_20BIT;
+			ddi_buf |= DDI_BUF_PORT_DATA_20BIT;
+		} else {
+			port_buf &= ~XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK;
+			ddi_buf &= ~DDI_BUF_PORT_DATA_WIDTH_MASK;
+		}
+
+		intel_de_write(dev_priv, XELPDP_PORT_BUF_CTL1(port), port_buf);
+		intel_de_write(dev_priv, DDI_BUF_CTL(port),
+			       dig_port->saved_port_bits | ddi_buf);
+	} else if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) {
 		drm_WARN_ON(&dev_priv->drm, !intel_tc_port_in_legacy_mode(dig_port));
-		buf_ctl |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
+		intel_de_write(dev_priv, DDI_BUF_CTL(port),
+			       dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE |
+			       DDI_BUF_CTL_TC_PHY_OWNERSHIP);
+	} else {
+		intel_de_write(dev_priv, DDI_BUF_CTL(port),
+			       dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE);
 	}
-	intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl);
 
 	intel_audio_codec_enable(encoder, crtc_state, conn_state);
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 12/15] drm/i915/display/mtl: Reset FRL Transcoder config while disabling HDMI
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
                   ` (10 preceding siblings ...)
  2022-11-07  7:20 ` [RFC 11/15] drm/i915/display/mtl: Update Transcoder/DDI registers with the frl bits Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 13/15] drm/i915/hdmi21/mtl: Enable Scrambling only for FRL mode Ankit Nautiyal
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

While disabling HDMI, reset the FRL transcoder config if FRL mode was
used.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 5e2e4c78c564..cb0d19b6ee56 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2667,6 +2667,8 @@ static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state,
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
 	struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
+	enum transcoder hdmi_transcoder;
+	u8 buf;
 
 	dig_port->set_infoframes(encoder, false,
 				 old_crtc_state, old_conn_state);
@@ -2679,6 +2681,16 @@ static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state,
 	if (DISPLAY_VER(dev_priv) >= 12)
 		intel_ddi_disable_pipe_clock(old_crtc_state);
 
+	if (old_crtc_state->frl.enable) {
+		hdmi_transcoder = old_crtc_state->cpu_transcoder;
+		buf = intel_de_read(dev_priv,
+				    TRANS_HDMI_FRL_CFG(hdmi_transcoder));
+		buf &= ~(TRANS_HDMI_FRL_ENABLE | TRANS_HDMI_FRL_TRAINING_COMPLETE);
+
+		intel_de_write(dev_priv,
+			       TRANS_HDMI_FRL_CFG(hdmi_transcoder), buf);
+	}
+
 	intel_display_power_put(dev_priv,
 				dig_port->ddi_io_power_domain,
 				fetch_and_zero(&dig_port->ddi_io_wakeref));
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 13/15] drm/i915/hdmi21/mtl: Enable Scrambling only for FRL mode
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
                   ` (11 preceding siblings ...)
  2022-11-07  7:20 ` [RFC 12/15] drm/i915/display/mtl: Reset FRL Transcoder config while disabling HDMI Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 14/15] drm/i915/hdmi21/mtl: Add support for sending uevent to user for FRL training failure Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 15/15] drm/i915/display/mtl: Add functions for FRL trainining state machine Ankit Nautiyal
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

In FRL mode, the Scrambling is always enabled by the HW.
The High TMDS Char Rate and Scrambing Enable bit of
reg TRANS_DDI_FUNC_CTRL are only set in TMDS mode and not
in FRL mode.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 1dd0b0f2e2f1..1eadf77dc819 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2292,7 +2292,13 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
 
 	pipe_config->lane_count = 4;
 
-	if (scdc->scrambling.supported && DISPLAY_VER(dev_priv) >= 10) {
+	/*
+	 * Enable scrambing for only for TMDS mode.
+	 * For FRL mode, scrambling is always enabled by HW, and
+	 * scrambling enable and high tmds clock bits are not used.
+	 */
+	if (scdc->scrambling.supported && DISPLAY_VER(dev_priv) >= 10 &&
+	    !pipe_config->frl.enable) {
 		if (scdc->scrambling.low_rates)
 			pipe_config->hdmi_scrambling = true;
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 14/15] drm/i915/hdmi21/mtl: Add support for sending uevent to user for FRL training failure
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
                   ` (12 preceding siblings ...)
  2022-11-07  7:20 ` [RFC 13/15] drm/i915/hdmi21/mtl: Enable Scrambling only for FRL mode Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  2022-11-07  7:20 ` [RFC 15/15] drm/i915/display/mtl: Add functions for FRL trainining state machine Ankit Nautiyal
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

In case of HDMI2.1 FRL training failure for a given mode, the user
should be sent a uevent signalling Link failure.

This patch adds support for sending uevent to userspace in case of link
training failure.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 30 +++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 1eadf77dc819..9e8ee6d5bc5d 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2944,6 +2944,31 @@ void intel_infoframe_init(struct intel_digital_port *dig_port)
 	}
 }
 
+/* Common code with DP, need to put in a common place */
+static void intel_hdmi_modeset_retry_work_fn(struct work_struct *work)
+{
+	struct intel_connector *intel_connector;
+	struct drm_connector *connector;
+
+	intel_connector = container_of(work, typeof(*intel_connector),
+				       modeset_retry_work);
+	connector = &intel_connector->base;
+	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
+		      connector->name);
+
+	/* Grab the locks before changing connector property*/
+	mutex_lock(&connector->dev->mode_config.mutex);
+	/*
+	 * Set connector link status to BAD and send a Uevent to notify
+	 * userspace to do a modeset.
+	 */
+	drm_connector_set_link_status_property(connector,
+					       DRM_MODE_LINK_STATUS_BAD);
+	mutex_unlock(&connector->dev->mode_config.mutex);
+	/* Send Hotplug uevent so userspace can reprobe */
+	drm_kms_helper_hotplug_event(connector->dev);
+}
+
 void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
 			       struct intel_connector *intel_connector)
 {
@@ -3021,6 +3046,11 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
 					   &conn_info);
 	if (!intel_hdmi->cec_notifier)
 		drm_dbg_kms(&dev_priv->drm, "CEC notifier get failed\n");
+
+	/* Initialize the work for modeset in case of link train failure */
+	if (DISPLAY_VER(dev_priv) >= 14)
+		INIT_WORK(&intel_connector->modeset_retry_work,
+			  intel_hdmi_modeset_retry_work_fn);
 }
 
 /*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC 15/15] drm/i915/display/mtl: Add functions for FRL trainining state machine
  2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
                   ` (13 preceding siblings ...)
  2022-11-07  7:20 ` [RFC 14/15] drm/i915/hdmi21/mtl: Add support for sending uevent to user for FRL training failure Ankit Nautiyal
@ 2022-11-07  7:20 ` Ankit Nautiyal
  14 siblings, 0 replies; 16+ messages in thread
From: Ankit Nautiyal @ 2022-11-07  7:20 UTC (permalink / raw)
  To: dri-devel, intel-gfx
  Cc: vandita.kulkarni, uma.shankar, mika.kahola, radhakrishna.sripada

Add support for FRL Link training state and transition
to different states during FRL Link training.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c  |   2 +
 drivers/gpu/drm/i915/display/intel_hdmi.c | 383 ++++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_hdmi.h |   2 +
 3 files changed, 387 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index cb0d19b6ee56..4b1b8a18863e 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2514,6 +2514,8 @@ static void intel_ddi_pre_enable_hdmi(struct intel_atomic_state *state,
 
 	intel_ddi_enable_pipe_clock(encoder, crtc_state);
 
+	intel_hdmi_start_frl(encoder, crtc_state);
+
 	dig_port->set_infoframes(encoder,
 				 crtc_state->has_infoframe,
 				 crtc_state, conn_state);
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 9e8ee6d5bc5d..6553763306ff 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -3285,3 +3285,386 @@ intel_hdmi_dsc_get_bpp(int src_fractional_bpp, int slice_width, int num_slices,
 
 	return 0;
 }
+
+static
+bool is_flt_ready(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct i2c_adapter *adapter =
+		intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
+
+	return drm_scdc_read_status_flags(adapter) & SCDC_FLT_READY;
+}
+
+static
+bool intel_hdmi_frl_prepare_lts2(struct intel_encoder *encoder,
+				 const struct intel_crtc_state *crtc_state,
+				 int ffe_level)
+{
+#define TIMEOUT_FLT_READY_MS  250
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct i2c_adapter *adapter =
+		intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
+	bool flt_ready = false;
+	int frl_rate;
+	int frl_lanes;
+
+	frl_rate = crtc_state->frl.required_rate;
+	frl_lanes = crtc_state->frl.required_lanes;
+
+	if (!frl_rate || !frl_lanes)
+		return false;
+
+	/*
+	 * POLL for FRL ready : READ SCDC 0x40 Bit 6 FLT ready
+	 * #TODO Check if 250 msec is required
+	 */
+	wait_for(flt_ready = is_flt_ready(encoder) == true,
+		 TIMEOUT_FLT_READY_MS);
+
+	if (!flt_ready) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "HDMI sink not ready for FRL in %d\n",
+			    TIMEOUT_FLT_READY_MS);
+
+		return false;
+	}
+
+	/*
+	 * #TODO As per spec, during prepare phase LTS2, the TXFFE to be
+	 * programmed to be 0 for each lane in the PHY registers.
+	 */
+
+	if (drm_scdc_config_frl(adapter, frl_rate, frl_lanes, ffe_level) < 0) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "Failed to write SCDC config regs for FRL\n");
+
+		return false;
+	}
+
+	return flt_ready;
+}
+
+enum frl_lt_status {
+	FRL_TRAINING_PASSED,
+	FRL_CHANGE_RATE,
+	FRL_TRAIN_CONTINUE,
+	FRL_TRAIN_RETRAIN,
+	FRL_TRAIN_STOP,
+};
+
+static
+u8 get_frl_update_flag(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct i2c_adapter *adapter =
+		intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
+
+	return drm_scdc_read_update_flags(adapter);
+}
+
+static
+int get_link_training_patterns(struct intel_encoder *encoder,
+			       enum drm_scdc_frl_ltp ltp[4])
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct i2c_adapter *adapter =
+		intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
+
+	return drm_scdc_get_ltp(adapter, ltp);
+}
+
+static enum frl_lt_status
+intel_hdmi_train_lanes(struct intel_encoder *encoder,
+		       const struct intel_crtc_state *crtc_state,
+		       int ffe_level)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum transcoder trans = crtc_state->cpu_transcoder;
+	enum drm_scdc_frl_ltp ltp[4];
+	int num_lanes = crtc_state->frl.required_lanes;
+	int lane;
+
+	/*
+	 * LTS3 Link Training in Progress.
+	 * Section 6.4.2.3 Table 6-34.
+	 *
+	 * Transmit link training pattern as requested by the sink
+	 * for a specific rate.
+	 * Source keep on Polling on FLT update flag and keep
+	 * repeating patterns till timeout or request for new rate,
+	 * or training is successful.
+	 */
+	if (!(get_frl_update_flag(encoder) & SCDC_FLT_UPDATE))
+		return FRL_TRAIN_CONTINUE;
+
+	if (get_link_training_patterns(encoder, ltp) < 0)
+		return FRL_TRAIN_STOP;
+
+	if (ltp[0] == ltp[1] && ltp[1] == ltp[2]) {
+		if (num_lanes == 3 || (num_lanes == 4 && ltp[2] == ltp[3])) {
+			if (ltp[0] == SCDC_FRL_NO_LTP)
+				return FRL_TRAINING_PASSED;
+			if (ltp[0] == SCDC_FRL_CHNG_RATE)
+				return FRL_CHANGE_RATE;
+		}
+	}
+
+	for (lane = 0; lane < num_lanes; lane++) {
+		if (ltp[lane] >= SCDC_FRL_LTP1 && ltp[lane] <= SCDC_FRL_LTP8)
+			/* write the LTP for the lane*/
+			intel_de_write(dev_priv, TRANS_HDMI_FRL_TRAIN(trans),
+				       TRANS_HDMI_FRL_LTP(ltp[lane], lane));
+		else if (ltp[lane] == SCDC_FRL_CHNG_FFE) {
+			/*
+			 * #TODO Update TxFFE for the lane
+			 *
+			 * Read the existing TxFFE for the lane, from PHY regs.
+			 * If TxFFE is already at FFE_level (i.e. max level)
+			 * then Set TXFFE0 for the lane.
+			 * Otherwise increment TxFFE for the lane.
+			 */
+		}
+	}
+
+	return FRL_TRAIN_CONTINUE;
+}
+
+static int
+clear_scdc_update_flags(struct intel_encoder *encoder, u8 flags)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct i2c_adapter *adapter =
+		intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
+
+	return drm_scdc_clear_update_flags(adapter, flags);
+}
+
+static enum frl_lt_status
+frl_train_complete_ltsp(struct intel_encoder *encoder,
+			const struct intel_crtc_state *crtc_state)
+{
+#define FLT_UPDATE_TIMEOUT_MS 200
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum transcoder trans = crtc_state->cpu_transcoder;
+	u32 buf;
+	u8 update_flag = 0;
+
+	/*
+	 * Start FRL transmission with only Gap Characters, with Scrambing,
+	 * Reed Solomon FEC, and Super block structure.
+	 */
+	buf = intel_de_read(dev_priv, TRANS_HDMI_FRL_CFG(trans));
+	intel_de_write(dev_priv, TRANS_HDMI_FRL_CFG(trans),
+		       buf | TRANS_HDMI_FRL_TRAINING_COMPLETE);
+
+	/* Clear SCDC FLT_UPDATE by writing 1 */
+	if (clear_scdc_update_flags(encoder, SCDC_FLT_UPDATE) < 0)
+		return FRL_TRAIN_STOP;
+
+	wait_for((update_flag = get_frl_update_flag(encoder)) &
+		 (SCDC_FRL_START | SCDC_FLT_UPDATE), FLT_UPDATE_TIMEOUT_MS);
+
+	if (update_flag & SCDC_FRL_START)
+		return FRL_TRAINING_PASSED;
+
+	if (update_flag & SCDC_FLT_UPDATE) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "FRL update received for retraining the lanes\n");
+		clear_scdc_update_flags(encoder, SCDC_FLT_UPDATE);
+
+		return FRL_TRAIN_RETRAIN;
+	}
+
+	drm_err(&dev_priv->drm, "FRL TRAINING: FRL update timedout\n");
+
+	return FRL_TRAIN_STOP;
+}
+
+static enum frl_lt_status
+intel_hdmi_frl_train_lts3(struct intel_encoder *encoder,
+			  const struct intel_crtc_state *crtc_state,
+			  int ffe_level)
+{
+/*
+ * Time interval specified for link training HDMI2.1 Spec:
+ * Sec 6.4.2.1 Table 6-31
+ */
+#define FLT_TIMEOUT_MS 200
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum frl_lt_status status;
+	enum transcoder trans = crtc_state->cpu_transcoder;
+	u32 buf;
+
+	buf = intel_de_read(dev_priv, TRANS_HDMI_FRL_CFG(trans));
+	intel_de_write(dev_priv, TRANS_HDMI_FRL_CFG(trans),
+		       buf | TRANS_HDMI_FRL_ENABLE);
+
+#define done ((status = intel_hdmi_train_lanes(encoder, crtc_state, ffe_level)) != FRL_TRAIN_CONTINUE)
+	wait_for(done, FLT_TIMEOUT_MS);
+
+	/* TIMEDOUT */
+	if (status == FRL_TRAIN_CONTINUE) {
+		drm_err(&dev_priv->drm, "FRL TRAINING: FLT TIMEDOUT\n");
+
+		return FRL_TRAIN_STOP;
+	}
+
+	if (status != FRL_TRAINING_PASSED)
+		return status;
+
+	return frl_train_complete_ltsp(encoder, crtc_state);
+}
+
+static void intel_hdmi_frl_ltsl(struct intel_encoder *encoder,
+				const struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct i2c_adapter *adapter =
+		intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
+	int lanes = crtc_state->frl.required_lanes;
+
+	/* Clear flags */
+	drm_scdc_config_frl(adapter, 0, lanes, 0);
+	drm_scdc_clear_update_flags(adapter, SCDC_FLT_UPDATE);
+}
+
+static bool get_next_frl_rate(int *curr_rate_gbps, int max_sink_rate)
+{
+	int valid_rate[] =  {48, 40, 32, 24, 18, 9};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(valid_rate); i++) {
+		if (max_sink_rate < valid_rate[i])
+			continue;
+
+		if (*curr_rate_gbps < valid_rate[i]) {
+			*curr_rate_gbps = valid_rate[i];
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static int get_ffe_level(int rate_gbps)
+{
+	/*
+	 * #TODO check for FFE_LEVEL to be programmed
+	 *
+	 * Should start with max ffe_levels supported by source. MAX can be 3.
+	 * Currently setting ffe_level = 0.
+	 */
+	return 0;
+}
+
+/*
+ * intel_hdmi_start_frl - Start FRL training for HDMI2.1 sink
+ *
+ */
+void intel_hdmi_start_frl(struct intel_encoder *encoder,
+			  const struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+	struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
+	struct intel_connector *intel_connector = intel_hdmi->attached_connector;
+	struct drm_connector *connector = &intel_connector->base;
+	int *rate;
+	int max_rate = crtc_state->dsc.compression_enable ? intel_hdmi->max_dsc_frl_rate :
+							intel_hdmi->max_frl_rate;
+	int req_rate = crtc_state->frl.required_lanes * crtc_state->frl.required_rate;
+	int ffe_level = get_ffe_level(req_rate);
+	enum transcoder trans = crtc_state->cpu_transcoder;
+	enum frl_lt_status status;
+	u32 buf = 0;
+
+	if (DISPLAY_VER(dev_priv) < 14)
+		return;
+
+	if (!crtc_state->frl.enable)
+		goto ltsl_tmds_mode;
+
+	if (intel_hdmi->frl.trained &&
+	    intel_hdmi->frl.rate_gbps >= req_rate &&
+	    intel_hdmi->frl.ffe_level == ffe_level) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "[CONNECTOR:%d:%s] FRL Already trained with rate=%d, ffe_level=%d\n",
+			    connector->base.id, connector->name,
+			    req_rate, ffe_level);
+
+		return;
+	}
+
+	intel_hdmi_reset_frl_config(intel_hdmi);
+
+	if (!intel_hdmi_frl_prepare_lts2(encoder, crtc_state, ffe_level))
+		status = FRL_TRAIN_STOP;
+	else
+		status = intel_hdmi_frl_train_lts3(encoder, crtc_state, ffe_level);
+
+	switch (status) {
+	case FRL_TRAINING_PASSED:
+		intel_hdmi->frl.trained = true;
+		intel_hdmi->frl.rate_gbps = req_rate;
+		intel_hdmi->frl.ffe_level = ffe_level;
+		drm_dbg_kms(&dev_priv->drm,
+			    "[CONNECTOR:%d:%s] FRL Training Passed with rate=%d, ffe_level=%d\n",
+			    connector->base.id, connector->name,
+			    req_rate, ffe_level);
+
+		return;
+	case FRL_TRAIN_STOP:
+		/*
+		 * Cannot go with FRL transmission.
+		 * Reset FRL rates so during next modeset TMDS mode will be
+		 * selected.
+		 */
+		if (crtc_state->dsc.compression_enable)
+			intel_hdmi->max_dsc_frl_rate = 0;
+		else
+			intel_hdmi->max_frl_rate = 0;
+		break;
+	case FRL_CHANGE_RATE:
+		/*
+		 * Sink request for change of FRL rate.
+		 * Set FRL rates for the connector with lower rate.
+		 */
+		if (crtc_state->dsc.compression_enable)
+			rate = &intel_hdmi->max_dsc_frl_rate;
+		else
+			rate = &intel_hdmi->max_frl_rate;
+		if (!get_next_frl_rate(rate, max_rate))
+			*rate = 0;
+		break;
+	case FRL_TRAIN_RETRAIN:
+		/*
+		 * For Retraining with same rate, we send a uevent to userspace.
+		 * TODO Need to check how many times we can retry.
+		 */
+		fallthrough;
+	default:
+		break;
+	}
+
+ltsl_tmds_mode:
+	intel_hdmi_frl_ltsl(encoder, crtc_state);
+	buf = intel_de_read(dev_priv, TRANS_HDMI_FRL_CFG(trans));
+	intel_de_write(dev_priv, TRANS_HDMI_FRL_CFG(trans),
+		       buf & ~(TRANS_HDMI_FRL_ENABLE | TRANS_HDMI_FRL_TRAINING_COMPLETE));
+
+	if (crtc_state->frl.enable && !intel_hdmi->frl.trained) {
+		drm_err(&dev_priv->drm,
+			"[CONNECTOR:%d:%s] FRL Training Failed with rate=%d, ffe_level=%d\n",
+			connector->base.id, connector->name,
+			req_rate, ffe_level);
+		/* Send event to user space, to try with next rate or fall back to TMDS */
+		schedule_work(&intel_connector->modeset_retry_work);
+	}
+}
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h
index 774dda2376ed..a0a5c3159079 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.h
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.h
@@ -54,5 +54,7 @@ int intel_hdmi_dsc_get_num_slices(const struct intel_crtc_state *crtc_state,
 				  int src_max_slices, int src_max_slice_width,
 				  int hdmi_max_slices, int hdmi_throughput);
 int intel_hdmi_dsc_get_slice_height(int vactive);
+void intel_hdmi_start_frl(struct intel_encoder *encoder,
+			  const struct intel_crtc_state *crtc_state);
 
 #endif /* __INTEL_HDMI_H__ */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2022-11-07  7:21 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-07  7:20 [RFC 00/15] Add support for HDMI2.1 FRL Ankit Nautiyal
2022-11-07  7:20 ` [RFC 01/15] drm/edid: Add helper to get max FRL rate for an HDMI sink Ankit Nautiyal
2022-11-07  7:20 ` [RFC 02/15] drm/i915/dp: Use the drm helpers for getting max FRL rate Ankit Nautiyal
2022-11-07  7:20 ` [RFC 03/15] drm/i915/mtl: Create separate reg file for PICA registers Ankit Nautiyal
2022-11-07  7:20 ` [RFC 04/15] drm/i915/hdmi21/mtl: Parse frl max link rate from vbt Ankit Nautiyal
2022-11-07  7:20 ` [RFC 05/15] drm/i915/hdmi21/mtl: Add new data members for FRL configuration Ankit Nautiyal
2022-11-07  7:20 ` [RFC 06/15] drm/drm_scdc_helper: Add SCDC helper funcs for HDMI2.1 Ankit Nautiyal
2022-11-07  7:20 ` [RFC 07/15] drm/i915/mtl: Add registers for FRL Link Training Ankit Nautiyal
2022-11-07  7:20 ` [RFC 08/15] drm/i915/mtl: Add HDMI2.1 bits in PORT_BUF_CTL_1 Ankit Nautiyal
2022-11-07  7:20 ` [RFC 09/15] drm/i915/mtl: Add port_data/data width for TRANS_DDI_FUNC and DDI_BUF_CTL Ankit Nautiyal
2022-11-07  7:20 ` [RFC 10/15] drm/i915/display/mtl: Add new members in crtc_state for FRL configuration Ankit Nautiyal
2022-11-07  7:20 ` [RFC 11/15] drm/i915/display/mtl: Update Transcoder/DDI registers with the frl bits Ankit Nautiyal
2022-11-07  7:20 ` [RFC 12/15] drm/i915/display/mtl: Reset FRL Transcoder config while disabling HDMI Ankit Nautiyal
2022-11-07  7:20 ` [RFC 13/15] drm/i915/hdmi21/mtl: Enable Scrambling only for FRL mode Ankit Nautiyal
2022-11-07  7:20 ` [RFC 14/15] drm/i915/hdmi21/mtl: Add support for sending uevent to user for FRL training failure Ankit Nautiyal
2022-11-07  7:20 ` [RFC 15/15] drm/i915/display/mtl: Add functions for FRL trainining state machine Ankit Nautiyal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).