Commit 8c835a10 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-fixes-2026-03-12' of...

Merge tag 'drm-intel-fixes-2026-03-12' of https://gitlab.freedesktop.org/drm/i915/kernel

 into drm-fixes

- Avoid hang when configuring VRR [icl] (Ville Syrjälä)
- Fix sg_table overflow with >4GB folios (Janusz Krzysztofik)
- Fix PSR Selective Update handling [psr] (Jouni Högander)
- Fix eDP ALPM read-out sequence [dp] (Arun R Murthy)

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Tvrtko Ursulin <tursulin@igalia.com>
Link: https://patch.msgid.link/abJ_MQ7o-5ghyaNW@linux
parents 3c9eced5 335b237d
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -43,12 +43,6 @@ bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp,

void intel_alpm_init(struct intel_dp *intel_dp)
{
	u8 dpcd;

	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_RECEIVER_ALPM_CAP, &dpcd) < 0)
		return;

	intel_dp->alpm_dpcd = dpcd;
	mutex_init(&intel_dp->alpm.lock);
}

+0 −1
Original line number Diff line number Diff line
@@ -1614,7 +1614,6 @@ static void hsw_configure_cpu_transcoder(const struct intel_crtc_state *crtc_sta
	}

	intel_set_transcoder_timings(crtc_state);
	intel_vrr_set_transcoder_timings(crtc_state);

	if (cpu_transcoder != TRANSCODER_EDP)
		intel_de_write(display, TRANS_MULT(display, cpu_transcoder),
+7 −0
Original line number Diff line number Diff line
@@ -4577,6 +4577,7 @@ static bool
intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector)
{
	struct intel_display *display = to_intel_display(intel_dp);
	int ret;

	/* this function is meant to be called only once */
	drm_WARN_ON(display->drm, intel_dp->dpcd[DP_DPCD_REV] != 0);
@@ -4616,6 +4617,12 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector
	 */
	intel_dp_init_source_oui(intel_dp);

	/* Read the ALPM DPCD caps */
	ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_RECEIVER_ALPM_CAP,
				    &intel_dp->alpm_dpcd);
	if (ret < 0)
		return false;

	/*
	 * This has to be called after intel_dp->edp_dpcd is filled, PSR checks
	 * for SET_POWER_CAPABLE bit in intel_dp->edp_dpcd[1]
+48 −12
Original line number Diff line number Diff line
@@ -2619,6 +2619,12 @@ void intel_psr2_program_trans_man_trk_ctl(struct intel_dsb *dsb,

	intel_de_write_dsb(display, dsb, PIPE_SRCSZ_ERLY_TPT(crtc->pipe),
			   crtc_state->pipe_srcsz_early_tpt);

	if (!crtc_state->dsc.compression_enable)
		return;

	intel_dsc_su_et_parameters_configure(dsb, encoder, crtc_state,
					     drm_rect_height(&crtc_state->psr2_su_area));
}

static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state,
@@ -2689,11 +2695,12 @@ static void clip_area_update(struct drm_rect *overlap_damage_area,
		overlap_damage_area->y2 = damage_area->y2;
}

static void intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_state)
static bool intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_state)
{
	struct intel_display *display = to_intel_display(crtc_state);
	const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
	u16 y_alignment;
	bool su_area_changed = false;

	/* ADLP aligns the SU region to vdsc slice height in case dsc is enabled */
	if (crtc_state->dsc.compression_enable &&
@@ -2702,10 +2709,18 @@ static void intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_st
	else
		y_alignment = crtc_state->su_y_granularity;

	if (crtc_state->psr2_su_area.y1 % y_alignment) {
		crtc_state->psr2_su_area.y1 -= crtc_state->psr2_su_area.y1 % y_alignment;
	if (crtc_state->psr2_su_area.y2 % y_alignment)
		su_area_changed = true;
	}

	if (crtc_state->psr2_su_area.y2 % y_alignment) {
		crtc_state->psr2_su_area.y2 = ((crtc_state->psr2_su_area.y2 /
						y_alignment) + 1) * y_alignment;
		su_area_changed = true;
	}

	return su_area_changed;
}

/*
@@ -2839,7 +2854,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
	struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
	struct intel_plane_state *new_plane_state, *old_plane_state;
	struct intel_plane *plane;
	bool full_update = false, cursor_in_su_area = false;
	bool full_update = false, su_area_changed;
	int i, ret;

	if (!crtc_state->enable_psr2_sel_fetch)
@@ -2946,15 +2961,32 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
	if (ret)
		return ret;

	do {
		bool cursor_in_su_area;

		/*
	 * Adjust su area to cover cursor fully as necessary (early
	 * transport). This needs to be done after
	 * drm_atomic_add_affected_planes to ensure visible cursor is added into
	 * affected planes even when cursor is not updated by itself.
		 * Adjust su area to cover cursor fully as necessary
		 * (early transport). This needs to be done after
		 * drm_atomic_add_affected_planes to ensure visible
		 * cursor is added into affected planes even when
		 * cursor is not updated by itself.
		 */
		intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area);

	intel_psr2_sel_fetch_pipe_alignment(crtc_state);
		su_area_changed = intel_psr2_sel_fetch_pipe_alignment(crtc_state);

		/*
		 * If the cursor was outside the SU area before
		 * alignment, the alignment step (which only expands
		 * SU) may pull the cursor partially inside, so we
		 * must run ET alignment again to fully cover it. But
		 * if the cursor was already fully inside before
		 * alignment, expanding the SU area won't change that,
		 * so no further work is needed.
		 */
		if (cursor_in_su_area)
			break;
	} while (su_area_changed);

	/*
	 * Now that we have the pipe damaged area check if it intersect with
@@ -3014,6 +3046,10 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
	}

skip_sel_fetch_set_loop:
	if (full_update)
		clip_area_update(&crtc_state->psr2_su_area, &crtc_state->pipe_src,
				 &crtc_state->pipe_src);

	psr2_man_trk_ctl_calc(crtc_state, full_update);
	crtc_state->pipe_srcsz_early_tpt =
		psr2_pipe_srcsz_early_tpt_calc(crtc_state, full_update);
+23 −0
Original line number Diff line number Diff line
@@ -767,6 +767,29 @@ void intel_dsc_dp_pps_write(struct intel_encoder *encoder,
				  sizeof(dp_dsc_pps_sdp));
}

void intel_dsc_su_et_parameters_configure(struct intel_dsb *dsb, struct intel_encoder *encoder,
					  const struct intel_crtc_state *crtc_state, int su_lines)
{
	struct intel_display *display = to_intel_display(crtc_state);
	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
	const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
	enum pipe pipe = crtc->pipe;
	int vdsc_instances_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
	int slice_row_per_frame = su_lines / vdsc_cfg->slice_height;
	u32 val;

	drm_WARN_ON_ONCE(display->drm, su_lines % vdsc_cfg->slice_height);
	drm_WARN_ON_ONCE(display->drm, vdsc_instances_per_pipe > 2);

	val = DSC_SUPS0_SU_SLICE_ROW_PER_FRAME(slice_row_per_frame);
	val |= DSC_SUPS0_SU_PIC_HEIGHT(su_lines);

	intel_de_write_dsb(display, dsb, LNL_DSC0_SU_PARAMETER_SET_0(pipe), val);

	if (vdsc_instances_per_pipe == 2)
		intel_de_write_dsb(display, dsb, LNL_DSC1_SU_PARAMETER_SET_0(pipe), val);
}

static i915_reg_t dss_ctl1_reg(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
{
	return is_pipe_dsc(crtc, cpu_transcoder) ?
Loading