Commit a47828f3 authored by Ville Syrjälä's avatar Ville Syrjälä
Browse files

drm/i915/flipq: Implement Wa_18034343758



Implement the driver side of Wa_18034343758, which is supposed to
prevent the DSB and DMC from accessing registers in parallel, and
thus potentially corrupting the registers due to a hardware issue
(which should be fixed in PTL-B0).

The w/a sequence goes as follows:
DMC starts the DSB
 |                 \
DMC halts itself    | DSB waits a while for DMC to have time to halt
 .                  | DSB executes normally
 .		    | DSB unhalts the DMC at the very end
 .             	   /
DMC resumes execution

v2: PTL-B0+ firmware no longer has the w/a since the hw got fixed
v3: Do the w/a on all PTL for now since we only have the A0 firmware
    binaries which issues the halt instructions unconditionally
v4: PTL DMC binaries do in fact have the A0 vs. B0 split, so skip
    the w/a on PTL-B0+

Reviewed-by: default avatarUma Shankar <uma.shankar@intel.com>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250624170049.27284-7-ville.syrjala@linux.intel.com
parent ec3a347b
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -7246,6 +7246,10 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
	}

	if (new_crtc_state->use_flipq || new_crtc_state->use_dsb) {
		/* Wa_18034343758 */
		if (new_crtc_state->use_flipq)
			intel_flipq_wait_dmc_halt(new_crtc_state->dsb_commit, crtc);

		if (intel_crtc_needs_color_update(new_crtc_state))
			intel_color_commit_noarm(new_crtc_state->dsb_commit,
						 new_crtc_state);
@@ -7276,6 +7280,10 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
		if (DISPLAY_VER(display) >= 9)
			skl_detach_scalers(new_crtc_state->dsb_commit,
					   new_crtc_state);

		/* Wa_18034343758 */
		if (new_crtc_state->use_flipq)
			intel_flipq_unhalt_dmc(new_crtc_state->dsb_commit, crtc);
	}

	if (intel_color_uses_chained_dsb(new_crtc_state))
+24 −0
Original line number Diff line number Diff line
@@ -400,3 +400,27 @@ void intel_flipq_add(struct intel_crtc *crtc,

	intel_flipq_sw_dmc_wake(crtc);
}

/* Wa_18034343758 */
static bool need_dmc_halt_wa(struct intel_display *display)
{
	return DISPLAY_VER(display) == 20 ||
		(display->platform.pantherlake &&
		 IS_DISPLAY_STEP(display, STEP_A0, STEP_B0));
}

void intel_flipq_wait_dmc_halt(struct intel_dsb *dsb, struct intel_crtc *crtc)
{
	struct intel_display *display = to_intel_display(crtc);

	if (need_dmc_halt_wa(display))
		intel_dsb_wait_usec(dsb, 2);
}

void intel_flipq_unhalt_dmc(struct intel_dsb *dsb, struct intel_crtc *crtc)
{
	struct intel_display *display = to_intel_display(crtc);

	if (need_dmc_halt_wa(display))
		intel_dsb_reg_write(dsb, PIPEDMC_CTL(crtc->pipe), 0);
}
+2 −0
Original line number Diff line number Diff line
@@ -29,5 +29,7 @@ void intel_flipq_add(struct intel_crtc *crtc,
		     enum intel_dsb_id dsb_id,
		     struct intel_dsb *dsb);
int intel_flipq_exec_time_us(struct intel_display *display);
void intel_flipq_wait_dmc_halt(struct intel_dsb *dsb, struct intel_crtc *crtc);
void intel_flipq_unhalt_dmc(struct intel_dsb *dsb, struct intel_crtc *crtc);

#endif /* __INTEL_FLIPQ_H__ */