Commit ce7a3d2e authored by Daniel Vetter's avatar Daniel Vetter
Browse files

Merge tag 'drm-intel-fixes-2023-03-30' of...

Merge tag 'drm-intel-fixes-2023-03-30' of git://anongit.freedesktop.org/drm/drm-intel

 into drm-fixes

drm/i915 fixes for v6.3-rc5:
- Fix PMU support by reusing functions with sysfs
- Fix a number of issues related to color, PSR and arm/noarm
- Fix state check related to ICL PHY ownership check in TC-cold state
- Flush lmem contents after construction
- Fix hibernate oops related to DPT BO
- Fix perf stream error path wakeref balance

Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/87355m4gtm.fsf@intel.com
parents 197b6b60 5c95b2d5
Loading
Loading
Loading
Loading
+97 −4
Original line number Diff line number Diff line
@@ -46,6 +46,11 @@ struct intel_color_funcs {
	 * registers involved with the same commit.
	 */
	void (*color_commit_arm)(const struct intel_crtc_state *crtc_state);
	/*
	 * Perform any extra tasks needed after all the
	 * double buffered registers have been latched.
	 */
	void (*color_post_update)(const struct intel_crtc_state *crtc_state);
	/*
	 * Load LUTs (and other single buffered color management
	 * registers). Will (hopefully) be called during the vblank
@@ -614,9 +619,33 @@ static void ilk_lut_12p4_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)

static void icl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
{
	/*
	 * Despite Wa_1406463849, ICL no longer suffers from the SKL
	 * DC5/PSR CSC black screen issue (see skl_color_commit_noarm()).
	 * Possibly due to the extra sticky CSC arming
	 * (see icl_color_post_update()).
	 *
	 * On TGL+ all CSC arming issues have been properly fixed.
	 */
	icl_load_csc_matrix(crtc_state);
}

static void skl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
{
	/*
	 * Possibly related to display WA #1184, SKL CSC loses the latched
	 * CSC coeff/offset register values if the CSC registers are disarmed
	 * between DC5 exit and PSR exit. This will cause the plane(s) to
	 * output all black (until CSC_MODE is rearmed and properly latched).
	 * Once PSR exit (and proper register latching) has occurred the
	 * danger is over. Thus when PSR is enabled the CSC coeff/offset
	 * register programming will be peformed from skl_color_commit_arm()
	 * which is called after PSR exit.
	 */
	if (!crtc_state->has_psr)
		ilk_load_csc_matrix(crtc_state);
}

static void ilk_color_commit_noarm(const struct intel_crtc_state *crtc_state)
{
	ilk_load_csc_matrix(crtc_state);
@@ -659,6 +688,9 @@ static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)
	enum pipe pipe = crtc->pipe;
	u32 val = 0;

	if (crtc_state->has_psr)
		ilk_load_csc_matrix(crtc_state);

	/*
	 * We don't (yet) allow userspace to control the pipe background color,
	 * so force it to black, but apply pipe gamma and CSC appropriately
@@ -677,6 +709,47 @@ static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)
			  crtc_state->csc_mode);
}

static void icl_color_commit_arm(const struct intel_crtc_state *crtc_state)
{
	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
	enum pipe pipe = crtc->pipe;

	/*
	 * We don't (yet) allow userspace to control the pipe background color,
	 * so force it to black.
	 */
	intel_de_write(i915, SKL_BOTTOM_COLOR(pipe), 0);

	intel_de_write(i915, GAMMA_MODE(crtc->pipe),
		       crtc_state->gamma_mode);

	intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
			  crtc_state->csc_mode);
}

static void icl_color_post_update(const struct intel_crtc_state *crtc_state)
{
	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
	struct drm_i915_private *i915 = to_i915(crtc->base.dev);

	/*
	 * Despite Wa_1406463849, ICL CSC is no longer disarmed by
	 * coeff/offset register *writes*. Instead, once CSC_MODE
	 * is armed it stays armed, even after it has been latched.
	 * Afterwards the coeff/offset registers become effectively
	 * self-arming. That self-arming must be disabled before the
	 * next icl_color_commit_noarm() tries to write the next set
	 * of coeff/offset registers. Fortunately register *reads*
	 * do still disarm the CSC. Naturally this must not be done
	 * until the previously written CSC registers have actually
	 * been latched.
	 *
	 * TGL+ no longer need this workaround.
	 */
	intel_de_read_fw(i915, PIPE_CSC_PREOFF_HI(crtc->pipe));
}

static struct drm_property_blob *
create_linear_lut(struct drm_i915_private *i915, int lut_size)
{
@@ -1373,6 +1446,14 @@ void intel_color_commit_arm(const struct intel_crtc_state *crtc_state)
	i915->display.funcs.color->color_commit_arm(crtc_state);
}

void intel_color_post_update(const struct intel_crtc_state *crtc_state)
{
	struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);

	if (i915->display.funcs.color->color_post_update)
		i915->display.funcs.color->color_post_update(crtc_state);
}

void intel_color_prepare_commit(struct intel_crtc_state *crtc_state)
{
	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -3064,10 +3145,20 @@ static const struct intel_color_funcs i9xx_color_funcs = {
	.lut_equal = i9xx_lut_equal,
};

static const struct intel_color_funcs tgl_color_funcs = {
	.color_check = icl_color_check,
	.color_commit_noarm = icl_color_commit_noarm,
	.color_commit_arm = icl_color_commit_arm,
	.load_luts = icl_load_luts,
	.read_luts = icl_read_luts,
	.lut_equal = icl_lut_equal,
};

static const struct intel_color_funcs icl_color_funcs = {
	.color_check = icl_color_check,
	.color_commit_noarm = icl_color_commit_noarm,
	.color_commit_arm = skl_color_commit_arm,
	.color_commit_arm = icl_color_commit_arm,
	.color_post_update = icl_color_post_update,
	.load_luts = icl_load_luts,
	.read_luts = icl_read_luts,
	.lut_equal = icl_lut_equal,
@@ -3075,7 +3166,7 @@ static const struct intel_color_funcs icl_color_funcs = {

static const struct intel_color_funcs glk_color_funcs = {
	.color_check = glk_color_check,
	.color_commit_noarm = ilk_color_commit_noarm,
	.color_commit_noarm = skl_color_commit_noarm,
	.color_commit_arm = skl_color_commit_arm,
	.load_luts = glk_load_luts,
	.read_luts = glk_read_luts,
@@ -3084,7 +3175,7 @@ static const struct intel_color_funcs glk_color_funcs = {

static const struct intel_color_funcs skl_color_funcs = {
	.color_check = ivb_color_check,
	.color_commit_noarm = ilk_color_commit_noarm,
	.color_commit_noarm = skl_color_commit_noarm,
	.color_commit_arm = skl_color_commit_arm,
	.load_luts = bdw_load_luts,
	.read_luts = bdw_read_luts,
@@ -3180,7 +3271,9 @@ void intel_color_init_hooks(struct drm_i915_private *i915)
		else
			i915->display.funcs.color = &i9xx_color_funcs;
	} else {
		if (DISPLAY_VER(i915) >= 11)
		if (DISPLAY_VER(i915) >= 12)
			i915->display.funcs.color = &tgl_color_funcs;
		else if (DISPLAY_VER(i915) == 11)
			i915->display.funcs.color = &icl_color_funcs;
		else if (DISPLAY_VER(i915) == 10)
			i915->display.funcs.color = &glk_color_funcs;
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ void intel_color_prepare_commit(struct intel_crtc_state *crtc_state);
void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state);
void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state);
void intel_color_commit_arm(const struct intel_crtc_state *crtc_state);
void intel_color_post_update(const struct intel_crtc_state *crtc_state);
void intel_color_load_luts(const struct intel_crtc_state *crtc_state);
void intel_color_get_config(struct intel_crtc_state *crtc_state);
bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
+28 −3
Original line number Diff line number Diff line
@@ -1209,6 +1209,9 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
	if (needs_cursorclk_wa(old_crtc_state) &&
	    !needs_cursorclk_wa(new_crtc_state))
		icl_wa_cursorclkgating(dev_priv, pipe, false);

	if (intel_crtc_needs_color_update(new_crtc_state))
		intel_color_post_update(new_crtc_state);
}

static void intel_crtc_enable_flip_done(struct intel_atomic_state *state,
@@ -7091,6 +7094,8 @@ static void intel_update_crtc(struct intel_atomic_state *state,

	intel_fbc_update(state, crtc);

	drm_WARN_ON(&i915->drm, !intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF));

	if (!modeset &&
	    intel_crtc_needs_color_update(new_crtc_state))
		intel_color_commit_noarm(new_crtc_state);
@@ -7458,8 +7463,28 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
	drm_atomic_helper_wait_for_dependencies(&state->base);
	drm_dp_mst_atomic_wait_for_dependencies(&state->base);

	if (state->modeset)
		wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
	/*
	 * During full modesets we write a lot of registers, wait
	 * for PLLs, etc. Doing that while DC states are enabled
	 * is not a good idea.
	 *
	 * During fastsets and other updates we also need to
	 * disable DC states due to the following scenario:
	 * 1. DC5 exit and PSR exit happen
	 * 2. Some or all _noarm() registers are written
	 * 3. Due to some long delay PSR is re-entered
	 * 4. DC5 entry -> DMC saves the already written new
	 *    _noarm() registers and the old not yet written
	 *    _arm() registers
	 * 5. DC5 exit -> DMC restores a mixture of old and
	 *    new register values and arms the update
	 * 6. PSR exit -> hardware latches a mixture of old and
	 *    new register values -> corrupted frame, or worse
	 * 7. New _arm() registers are finally written
	 * 8. Hardware finally latches a complete set of new
	 *    register values, and subsequent frames will be OK again
	 */
	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DC_OFF);

	intel_atomic_prepare_plane_clear_colors(state);

@@ -7608,8 +7633,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
		 * the culprit.
		 */
		intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore);
		intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET, wakeref);
	}
	intel_display_power_put(dev_priv, POWER_DOMAIN_DC_OFF, wakeref);
	intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref);

	/*
+2 −0
Original line number Diff line number Diff line
@@ -301,6 +301,7 @@ intel_dpt_create(struct intel_framebuffer *fb)
	vm->pte_encode = gen8_ggtt_pte_encode;

	dpt->obj = dpt_obj;
	dpt->obj->is_dpt = true;

	return &dpt->vm;
}
@@ -309,5 +310,6 @@ void intel_dpt_destroy(struct i915_address_space *vm)
{
	struct i915_dpt *dpt = i915_vm_to_dpt(vm);

	dpt->obj->is_dpt = false;
	i915_vm_put(&dpt->vm);
}
+2 −2
Original line number Diff line number Diff line
@@ -418,9 +418,9 @@ static bool icl_tc_phy_is_owned(struct intel_digital_port *dig_port)
	val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
	if (val == 0xffffffff) {
		drm_dbg_kms(&i915->drm,
			    "Port %s: PHY in TCCOLD, assume safe mode\n",
			    "Port %s: PHY in TCCOLD, assume not owned\n",
			    dig_port->tc_port_name);
		return true;
		return false;
	}

	return val & DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx);
Loading