diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
index ba6932f48e90..4060b8c8c6f3 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -9,6 +9,12 @@
 #include "intel_display.h"
 #include "intel_dp_mst.h"
 
+enum phy_fia {
+	FIA1,
+	FIA2,
+	FIA3,
+};
+
 static const char *tc_port_mode_name(enum tc_port_mode mode)
 {
 	static const char * const names[] = {
@@ -23,6 +29,23 @@ static const char *tc_port_mode_name(enum tc_port_mode mode)
 	return names[mode];
 }
 
+static bool has_modular_fia(struct drm_i915_private *i915)
+{
+	if (!INTEL_INFO(i915)->display.has_modular_fia)
+		return false;
+
+	return intel_uncore_read(&i915->uncore,
+				 PORT_TX_DFLEXDPSP(FIA1)) & MODULAR_FIA_MASK;
+}
+
+enum phy_fia tc_port_to_fia(struct drm_i915_private *i915, enum tc_port tc_port)
+{
+	if (!has_modular_fia(i915))
+		return FIA1;
+
+	return tc_port / 2;
+}
+
 u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
 {
 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
@@ -30,7 +53,8 @@ u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
 	struct intel_uncore *uncore = &i915->uncore;
 	u32 lane_mask;
 
-	lane_mask = intel_uncore_read(uncore, PORT_TX_DFLEXDPSP);
+	lane_mask = intel_uncore_read(uncore,
+				      PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia));
 
 	WARN_ON(lane_mask == 0xffffffff);
 
@@ -75,7 +99,8 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
 	enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
 	bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
 	struct intel_uncore *uncore = &i915->uncore;
-	u32 val = intel_uncore_read(uncore, PORT_TX_DFLEXDPMLE1);
+	u32 val = intel_uncore_read(uncore,
+				    PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia));
 
 	WARN_ON(lane_reversal && dig_port->tc_mode != TC_PORT_LEGACY);
 
@@ -96,7 +121,8 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
 		MISSING_CASE(required_lanes);
 	}
 
-	intel_uncore_write(uncore, PORT_TX_DFLEXDPMLE1, val);
+	intel_uncore_write(uncore,
+			   PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia), val);
 }
 
 static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port,
@@ -128,7 +154,8 @@ static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
 	u32 mask = 0;
 	u32 val;
 
-	val = intel_uncore_read(uncore, PORT_TX_DFLEXDPSP);
+	val = intel_uncore_read(uncore,
+				PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia));
 
 	if (val == 0xffffffff) {
 		DRM_DEBUG_KMS("Port %s: PHY in TCCOLD, nothing connected\n",
@@ -158,7 +185,8 @@ static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port)
 	struct intel_uncore *uncore = &i915->uncore;
 	u32 val;
 
-	val = intel_uncore_read(uncore, PORT_TX_DFLEXDPPMS);
+	val = intel_uncore_read(uncore,
+				PORT_TX_DFLEXDPPMS(dig_port->tc_phy_fia));
 	if (val == 0xffffffff) {
 		DRM_DEBUG_KMS("Port %s: PHY in TCCOLD, assuming not complete\n",
 			      dig_port->tc_port_name);
@@ -176,7 +204,8 @@ static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
 	struct intel_uncore *uncore = &i915->uncore;
 	u32 val;
 
-	val = intel_uncore_read(uncore, PORT_TX_DFLEXDPCSSS);
+	val = intel_uncore_read(uncore,
+				PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
 	if (val == 0xffffffff) {
 		DRM_DEBUG_KMS("Port %s: PHY in TCCOLD, can't set safe-mode to %s\n",
 			      dig_port->tc_port_name,
@@ -189,7 +218,8 @@ static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
 	if (!enable)
 		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
 
-	intel_uncore_write(uncore, PORT_TX_DFLEXDPCSSS, val);
+	intel_uncore_write(uncore,
+			   PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val);
 
 	if (enable && wait_for(!icl_tc_phy_status_complete(dig_port), 10))
 		DRM_DEBUG_KMS("Port %s: PHY complete clear timed out\n",
@@ -205,7 +235,8 @@ static bool icl_tc_phy_is_in_safe_mode(struct intel_digital_port *dig_port)
 	struct intel_uncore *uncore = &i915->uncore;
 	u32 val;
 
-	val = intel_uncore_read(uncore, PORT_TX_DFLEXDPCSSS);
+	val = intel_uncore_read(uncore,
+				PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
 	if (val == 0xffffffff) {
 		DRM_DEBUG_KMS("Port %s: PHY in TCCOLD, assume safe mode\n",
 			      dig_port->tc_port_name);
@@ -502,4 +533,5 @@ void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
 	mutex_init(&dig_port->tc_lock);
 	dig_port->tc_legacy_port = is_legacy;
 	dig_port->tc_link_refcount = 0;
+	dig_port->tc_phy_fia = tc_port_to_fia(i915, tc_port);
 }
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index c814cc1b3ae5..186e31e0291c 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2203,9 +2203,13 @@ enum i915_power_well_id {
 #define   DW6_OLDO_DYN_PWR_DOWN_EN	(1 << 28)
 
 #define FIA1_BASE			0x163000
+#define FIA2_BASE			0x16E000
+#define FIA3_BASE			0x16F000
+#define _FIA(fia)			_PICK((fia), FIA1_BASE, FIA2_BASE, FIA3_BASE)
+#define _MMIO_FIA(fia, off)		_MMIO(_FIA(fia) + (off))
 
 /* ICL PHY DFLEX registers */
-#define PORT_TX_DFLEXDPMLE1		_MMIO(FIA1_BASE + 0x008C0)
+#define PORT_TX_DFLEXDPMLE1(fia)	_MMIO_FIA((fia),  0x008C0)
 #define   DFLEXDPMLE1_DPMLETC_MASK(tc_port)	(0xf << (4 * (tc_port)))
 #define   DFLEXDPMLE1_DPMLETC_ML0(tc_port)	(1 << (4 * (tc_port)))
 #define   DFLEXDPMLE1_DPMLETC_ML1_0(tc_port)	(3 << (4 * (tc_port)))
@@ -11463,17 +11467,18 @@ enum skl_power_gate {
 						_ICL_DSC1_RC_BUF_THRESH_1_UDW_PB, \
 						_ICL_DSC1_RC_BUF_THRESH_1_UDW_PC)
 
-#define PORT_TX_DFLEXDPSP			_MMIO(FIA1_BASE + 0x008A0)
+#define PORT_TX_DFLEXDPSP(fia)			_MMIO_FIA((fia), 0x008A0)
+#define   MODULAR_FIA_MASK			(1 << 4)
 #define   TC_LIVE_STATE_TBT(tc_port)		(1 << ((tc_port) * 8 + 6))
 #define   TC_LIVE_STATE_TC(tc_port)		(1 << ((tc_port) * 8 + 5))
 #define   DP_LANE_ASSIGNMENT_SHIFT(tc_port)	((tc_port) * 8)
 #define   DP_LANE_ASSIGNMENT_MASK(tc_port)	(0xf << ((tc_port) * 8))
 #define   DP_LANE_ASSIGNMENT(tc_port, x)	((x) << ((tc_port) * 8))
 
-#define PORT_TX_DFLEXDPPMS				_MMIO(FIA1_BASE + 0x00890)
+#define PORT_TX_DFLEXDPPMS(fia)			_MMIO_FIA((fia), 0x00890)
 #define   DP_PHY_MODE_STATUS_COMPLETED(tc_port)		(1 << (tc_port))
 
-#define PORT_TX_DFLEXDPCSSS			_MMIO(FIA1_BASE + 0x00894)
+#define PORT_TX_DFLEXDPCSSS(fia)		_MMIO_FIA((fia), 0x00894)
 #define   DP_PHY_MODE_STATUS_NOT_SAFE(tc_port)		(1 << (tc_port))
 
 #endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h
index ddafc819bf30..e9dc86ed517b 100644
--- a/drivers/gpu/drm/i915/intel_device_info.h
+++ b/drivers/gpu/drm/i915/intel_device_info.h
@@ -136,6 +136,7 @@ enum intel_ppgtt_type {
 	func(has_gmch); \
 	func(has_hotplug); \
 	func(has_ipc); \
+	func(has_modular_fia); \
 	func(has_overlay); \
 	func(has_psr); \
 	func(overlay_needs_physical); \
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 24c63ed45c6f..7ea979c8c5f7 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1245,6 +1245,7 @@ struct intel_digital_port {
 	bool tc_legacy_port:1;
 	char tc_port_name[8];
 	enum tc_port_mode tc_mode;
+	u8 tc_phy_fia;
 
 	void (*write_infoframe)(struct intel_encoder *encoder,
 				const struct intel_crtc_state *crtc_state,
