Commit 98c4a3f4 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-fixes-2025-08-20' of...

Merge tag 'drm-intel-fixes-2025-08-20' of https://gitlab.freedesktop.org/drm/i915/kernel

 into drm-fixes

- TypeC DP display Fixes [lnl] (Imre Deak)
- Silence rpm wakeref asserts on GEN11_GU_MISC_IIR access (Jani Nikula)
- Relocate compression repacking WA for JSL/EHL [gt] (Sebastian Brzezinka)

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Tvrtko Ursulin <tursulin@igalia.com>
Link: https://lore.kernel.org/r/aKW2CAy37usxTrzn@linux
parents c17b750b 8236820f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1506,10 +1506,14 @@ u32 gen11_gu_misc_irq_ack(struct intel_display *display, const u32 master_ctl)
	if (!(master_ctl & GEN11_GU_MISC_IRQ))
		return 0;

	intel_display_rpm_assert_block(display);

	iir = intel_de_read(display, GEN11_GU_MISC_IIR);
	if (likely(iir))
		intel_de_write(display, GEN11_GU_MISC_IIR, iir);

	intel_display_rpm_assert_unblock(display);

	return iir;
}

+75 −18
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "intel_modeset_lock.h"
#include "intel_tc.h"

#define DP_PIN_ASSIGNMENT_NONE	0x0
#define DP_PIN_ASSIGNMENT_C	0x3
#define DP_PIN_ASSIGNMENT_D	0x4
#define DP_PIN_ASSIGNMENT_E	0x5
@@ -66,6 +67,7 @@ struct intel_tc_port {
	enum tc_port_mode init_mode;
	enum phy_fia phy_fia;
	u8 phy_fia_idx;
	u8 max_lane_count;
};

static enum intel_display_power_domain
@@ -307,6 +309,8 @@ static int lnl_tc_port_get_max_lane_count(struct intel_digital_port *dig_port)
		REG_FIELD_GET(TCSS_DDI_STATUS_PIN_ASSIGNMENT_MASK, val);

	switch (pin_assignment) {
	case DP_PIN_ASSIGNMENT_NONE:
		return 0;
	default:
		MISSING_CASE(pin_assignment);
		fallthrough;
@@ -365,12 +369,12 @@ static int intel_tc_port_get_max_lane_count(struct intel_digital_port *dig_port)
	}
}

int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port)
static int get_max_lane_count(struct intel_tc_port *tc)
{
	struct intel_display *display = to_intel_display(dig_port);
	struct intel_tc_port *tc = to_tc_port(dig_port);
	struct intel_display *display = to_intel_display(tc->dig_port);
	struct intel_digital_port *dig_port = tc->dig_port;

	if (!intel_encoder_is_tc(&dig_port->base) || tc->mode != TC_PORT_DP_ALT)
	if (tc->mode != TC_PORT_DP_ALT)
		return 4;

	assert_tc_cold_blocked(tc);
@@ -384,6 +388,25 @@ int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port)
	return intel_tc_port_get_max_lane_count(dig_port);
}

static void read_pin_configuration(struct intel_tc_port *tc)
{
	tc->max_lane_count = get_max_lane_count(tc);
}

int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port)
{
	struct intel_display *display = to_intel_display(dig_port);
	struct intel_tc_port *tc = to_tc_port(dig_port);

	if (!intel_encoder_is_tc(&dig_port->base))
		return 4;

	if (DISPLAY_VER(display) < 20)
		return get_max_lane_count(tc);

	return tc->max_lane_count;
}

void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
				      int required_lanes)
{
@@ -596,9 +619,12 @@ static void icl_tc_phy_get_hw_state(struct intel_tc_port *tc)
	tc_cold_wref = __tc_cold_block(tc, &domain);

	tc->mode = tc_phy_get_current_mode(tc);
	if (tc->mode != TC_PORT_DISCONNECTED)
	if (tc->mode != TC_PORT_DISCONNECTED) {
		tc->lock_wakeref = tc_cold_block(tc);

		read_pin_configuration(tc);
	}

	__tc_cold_unblock(tc, domain, tc_cold_wref);
}

@@ -656,8 +682,11 @@ static bool icl_tc_phy_connect(struct intel_tc_port *tc,

	tc->lock_wakeref = tc_cold_block(tc);

	if (tc->mode == TC_PORT_TBT_ALT)
	if (tc->mode == TC_PORT_TBT_ALT) {
		read_pin_configuration(tc);

		return true;
	}

	if ((!tc_phy_is_ready(tc) ||
	     !icl_tc_phy_take_ownership(tc, true)) &&
@@ -668,6 +697,7 @@ static bool icl_tc_phy_connect(struct intel_tc_port *tc,
		goto out_unblock_tc_cold;
	}

	read_pin_configuration(tc);

	if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes))
		goto out_release_phy;
@@ -858,9 +888,12 @@ static void adlp_tc_phy_get_hw_state(struct intel_tc_port *tc)
	port_wakeref = intel_display_power_get(display, port_power_domain);

	tc->mode = tc_phy_get_current_mode(tc);
	if (tc->mode != TC_PORT_DISCONNECTED)
	if (tc->mode != TC_PORT_DISCONNECTED) {
		tc->lock_wakeref = tc_cold_block(tc);

		read_pin_configuration(tc);
	}

	intel_display_power_put(display, port_power_domain, port_wakeref);
}

@@ -873,6 +906,9 @@ static bool adlp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)

	if (tc->mode == TC_PORT_TBT_ALT) {
		tc->lock_wakeref = tc_cold_block(tc);

		read_pin_configuration(tc);

		return true;
	}

@@ -894,6 +930,8 @@ static bool adlp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)

	tc->lock_wakeref = tc_cold_block(tc);

	read_pin_configuration(tc);

	if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes))
		goto out_unblock_tc_cold;

@@ -1124,9 +1162,18 @@ static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
	tc_cold_wref = __tc_cold_block(tc, &domain);

	tc->mode = tc_phy_get_current_mode(tc);
	if (tc->mode != TC_PORT_DISCONNECTED)
	if (tc->mode != TC_PORT_DISCONNECTED) {
		tc->lock_wakeref = tc_cold_block(tc);

		read_pin_configuration(tc);
		/*
		 * Set a valid lane count value for a DP-alt sink which got
		 * disconnected. The driver can only disable the output on this PHY.
		 */
		if (tc->max_lane_count == 0)
			tc->max_lane_count = 4;
	}

	drm_WARN_ON(display->drm,
		    (tc->mode == TC_PORT_DP_ALT || tc->mode == TC_PORT_LEGACY) &&
		    !xelpdp_tc_phy_tcss_power_is_enabled(tc));
@@ -1138,14 +1185,19 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
{
	tc->lock_wakeref = tc_cold_block(tc);

	if (tc->mode == TC_PORT_TBT_ALT)
	if (tc->mode == TC_PORT_TBT_ALT) {
		read_pin_configuration(tc);

		return true;
	}

	if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
		goto out_unblock_tccold;

	xelpdp_tc_phy_take_ownership(tc, true);

	read_pin_configuration(tc);

	if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes))
		goto out_release_phy;

@@ -1226,14 +1278,19 @@ static void tc_phy_get_hw_state(struct intel_tc_port *tc)
	tc->phy_ops->get_hw_state(tc);
}

static bool tc_phy_is_ready_and_owned(struct intel_tc_port *tc,
/* Is the PHY owned by display i.e. is it in legacy or DP-alt mode? */
static bool tc_phy_owned_by_display(struct intel_tc_port *tc,
				    bool phy_is_ready, bool phy_is_owned)
{
	struct intel_display *display = to_intel_display(tc->dig_port);

	if (DISPLAY_VER(display) < 20) {
		drm_WARN_ON(display->drm, phy_is_owned && !phy_is_ready);

		return phy_is_ready && phy_is_owned;
	} else {
		return phy_is_owned;
	}
}

static bool tc_phy_is_connected(struct intel_tc_port *tc,
@@ -1244,7 +1301,7 @@ static bool tc_phy_is_connected(struct intel_tc_port *tc,
	bool phy_is_owned = tc_phy_is_owned(tc);
	bool is_connected;

	if (tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned))
	if (tc_phy_owned_by_display(tc, phy_is_ready, phy_is_owned))
		is_connected = port_pll_type == ICL_PORT_DPLL_MG_PHY;
	else
		is_connected = port_pll_type == ICL_PORT_DPLL_DEFAULT;
@@ -1352,7 +1409,7 @@ tc_phy_get_current_mode(struct intel_tc_port *tc)
	phy_is_ready = tc_phy_is_ready(tc);
	phy_is_owned = tc_phy_is_owned(tc);

	if (!tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned)) {
	if (!tc_phy_owned_by_display(tc, phy_is_ready, phy_is_owned)) {
		mode = get_tc_mode_in_phy_not_owned_state(tc, live_mode);
	} else {
		drm_WARN_ON(display->drm, live_mode == TC_PORT_TBT_ALT);
@@ -1441,11 +1498,11 @@ static void intel_tc_port_reset_mode(struct intel_tc_port *tc,
	intel_display_power_flush_work(display);
	if (!intel_tc_cold_requires_aux_pw(dig_port)) {
		enum intel_display_power_domain aux_domain;
		bool aux_powered;

		aux_domain = intel_aux_power_domain(dig_port);
		aux_powered = intel_display_power_is_enabled(display, aux_domain);
		drm_WARN_ON(display->drm, aux_powered);
		if (intel_display_power_is_enabled(display, aux_domain))
			drm_dbg_kms(display->drm, "Port %s: AUX unexpectedly powered\n",
				    tc->port_name);
	}

	tc_phy_disconnect(tc);
+11 −9
Original line number Diff line number Diff line
@@ -634,6 +634,8 @@ static void cfl_ctx_workarounds_init(struct intel_engine_cs *engine,
static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,
				     struct i915_wa_list *wal)
{
	struct drm_i915_private *i915 = engine->i915;

	/* Wa_1406697149 (WaDisableBankHangMode:icl) */
	wa_write(wal, GEN8_L3CNTLREG, GEN8_ERRDETBCTRL);

@@ -669,6 +671,15 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,

	/* Wa_1406306137:icl,ehl */
	wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN4, GEN11_DIS_PICK_2ND_EU);

	if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) {
		/*
		 * Disable Repacking for Compression (masked R/W access)
		 * before rendering compressed surfaces for display.
		 */
		wa_masked_en(wal, CACHE_MODE_0_GEN7,
			     DISABLE_REPACKING_FOR_COMPRESSION);
	}
}

/*
@@ -2306,15 +2317,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
			     GEN8_RC_SEMA_IDLE_MSG_DISABLE);
	}

	if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) {
		/*
		 * "Disable Repacking for Compression (masked R/W access)
		 *  before rendering compressed surfaces for display."
		 */
		wa_masked_en(wal, CACHE_MODE_0_GEN7,
			     DISABLE_REPACKING_FOR_COMPRESSION);
	}

	if (GRAPHICS_VER(i915) == 11) {
		/* This is not an Wa. Enable for better image quality */
		wa_masked_en(wal,