Skip to content

Commit 8c835a1

Browse files
committed
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: Dave Airlie <airlied@redhat.com> From: Tvrtko Ursulin <tursulin@igalia.com> Link: https://patch.msgid.link/abJ_MQ7o-5ghyaNW@linux
2 parents 3c9eced + 335b237 commit 8c835a1

9 files changed

Lines changed: 116 additions & 22 deletions

File tree

drivers/gpu/drm/i915/display/intel_alpm.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@ bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp,
4343

4444
void intel_alpm_init(struct intel_dp *intel_dp)
4545
{
46-
u8 dpcd;
47-
48-
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_RECEIVER_ALPM_CAP, &dpcd) < 0)
49-
return;
50-
51-
intel_dp->alpm_dpcd = dpcd;
5246
mutex_init(&intel_dp->alpm.lock);
5347
}
5448

drivers/gpu/drm/i915/display/intel_display.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1614,7 +1614,6 @@ static void hsw_configure_cpu_transcoder(const struct intel_crtc_state *crtc_sta
16141614
}
16151615

16161616
intel_set_transcoder_timings(crtc_state);
1617-
intel_vrr_set_transcoder_timings(crtc_state);
16181617

16191618
if (cpu_transcoder != TRANSCODER_EDP)
16201619
intel_de_write(display, TRANS_MULT(display, cpu_transcoder),

drivers/gpu/drm/i915/display/intel_dp.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4577,6 +4577,7 @@ static bool
45774577
intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector)
45784578
{
45794579
struct intel_display *display = to_intel_display(intel_dp);
4580+
int ret;
45804581

45814582
/* this function is meant to be called only once */
45824583
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
46164617
*/
46174618
intel_dp_init_source_oui(intel_dp);
46184619

4620+
/* Read the ALPM DPCD caps */
4621+
ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_RECEIVER_ALPM_CAP,
4622+
&intel_dp->alpm_dpcd);
4623+
if (ret < 0)
4624+
return false;
4625+
46194626
/*
46204627
* This has to be called after intel_dp->edp_dpcd is filled, PSR checks
46214628
* for SET_POWER_CAPABLE bit in intel_dp->edp_dpcd[1]

drivers/gpu/drm/i915/display/intel_psr.c

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2619,6 +2619,12 @@ void intel_psr2_program_trans_man_trk_ctl(struct intel_dsb *dsb,
26192619

26202620
intel_de_write_dsb(display, dsb, PIPE_SRCSZ_ERLY_TPT(crtc->pipe),
26212621
crtc_state->pipe_srcsz_early_tpt);
2622+
2623+
if (!crtc_state->dsc.compression_enable)
2624+
return;
2625+
2626+
intel_dsc_su_et_parameters_configure(dsb, encoder, crtc_state,
2627+
drm_rect_height(&crtc_state->psr2_su_area));
26222628
}
26232629

26242630
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,
26892695
overlap_damage_area->y2 = damage_area->y2;
26902696
}
26912697

2692-
static void intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_state)
2698+
static bool intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_state)
26932699
{
26942700
struct intel_display *display = to_intel_display(crtc_state);
26952701
const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
26962702
u16 y_alignment;
2703+
bool su_area_changed = false;
26972704

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

2705-
crtc_state->psr2_su_area.y1 -= crtc_state->psr2_su_area.y1 % y_alignment;
2706-
if (crtc_state->psr2_su_area.y2 % y_alignment)
2712+
if (crtc_state->psr2_su_area.y1 % y_alignment) {
2713+
crtc_state->psr2_su_area.y1 -= crtc_state->psr2_su_area.y1 % y_alignment;
2714+
su_area_changed = true;
2715+
}
2716+
2717+
if (crtc_state->psr2_su_area.y2 % y_alignment) {
27072718
crtc_state->psr2_su_area.y2 = ((crtc_state->psr2_su_area.y2 /
27082719
y_alignment) + 1) * y_alignment;
2720+
su_area_changed = true;
2721+
}
2722+
2723+
return su_area_changed;
27092724
}
27102725

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

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

2949-
/*
2950-
* Adjust su area to cover cursor fully as necessary (early
2951-
* transport). This needs to be done after
2952-
* drm_atomic_add_affected_planes to ensure visible cursor is added into
2953-
* affected planes even when cursor is not updated by itself.
2954-
*/
2955-
intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area);
2964+
do {
2965+
bool cursor_in_su_area;
29562966

2957-
intel_psr2_sel_fetch_pipe_alignment(crtc_state);
2967+
/*
2968+
* Adjust su area to cover cursor fully as necessary
2969+
* (early transport). This needs to be done after
2970+
* drm_atomic_add_affected_planes to ensure visible
2971+
* cursor is added into affected planes even when
2972+
* cursor is not updated by itself.
2973+
*/
2974+
intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area);
2975+
2976+
su_area_changed = intel_psr2_sel_fetch_pipe_alignment(crtc_state);
2977+
2978+
/*
2979+
* If the cursor was outside the SU area before
2980+
* alignment, the alignment step (which only expands
2981+
* SU) may pull the cursor partially inside, so we
2982+
* must run ET alignment again to fully cover it. But
2983+
* if the cursor was already fully inside before
2984+
* alignment, expanding the SU area won't change that,
2985+
* so no further work is needed.
2986+
*/
2987+
if (cursor_in_su_area)
2988+
break;
2989+
} while (su_area_changed);
29582990

29592991
/*
29602992
* 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,
30143046
}
30153047

30163048
skip_sel_fetch_set_loop:
3049+
if (full_update)
3050+
clip_area_update(&crtc_state->psr2_su_area, &crtc_state->pipe_src,
3051+
&crtc_state->pipe_src);
3052+
30173053
psr2_man_trk_ctl_calc(crtc_state, full_update);
30183054
crtc_state->pipe_srcsz_early_tpt =
30193055
psr2_pipe_srcsz_early_tpt_calc(crtc_state, full_update);

drivers/gpu/drm/i915/display/intel_vdsc.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,29 @@ void intel_dsc_dp_pps_write(struct intel_encoder *encoder,
767767
sizeof(dp_dsc_pps_sdp));
768768
}
769769

770+
void intel_dsc_su_et_parameters_configure(struct intel_dsb *dsb, struct intel_encoder *encoder,
771+
const struct intel_crtc_state *crtc_state, int su_lines)
772+
{
773+
struct intel_display *display = to_intel_display(crtc_state);
774+
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
775+
const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
776+
enum pipe pipe = crtc->pipe;
777+
int vdsc_instances_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
778+
int slice_row_per_frame = su_lines / vdsc_cfg->slice_height;
779+
u32 val;
780+
781+
drm_WARN_ON_ONCE(display->drm, su_lines % vdsc_cfg->slice_height);
782+
drm_WARN_ON_ONCE(display->drm, vdsc_instances_per_pipe > 2);
783+
784+
val = DSC_SUPS0_SU_SLICE_ROW_PER_FRAME(slice_row_per_frame);
785+
val |= DSC_SUPS0_SU_PIC_HEIGHT(su_lines);
786+
787+
intel_de_write_dsb(display, dsb, LNL_DSC0_SU_PARAMETER_SET_0(pipe), val);
788+
789+
if (vdsc_instances_per_pipe == 2)
790+
intel_de_write_dsb(display, dsb, LNL_DSC1_SU_PARAMETER_SET_0(pipe), val);
791+
}
792+
770793
static i915_reg_t dss_ctl1_reg(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
771794
{
772795
return is_pipe_dsc(crtc, cpu_transcoder) ?

drivers/gpu/drm/i915/display/intel_vdsc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ struct drm_printer;
1313
enum transcoder;
1414
struct intel_crtc;
1515
struct intel_crtc_state;
16+
struct intel_dsb;
1617
struct intel_encoder;
1718

1819
bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state);
@@ -31,6 +32,8 @@ void intel_dsc_dsi_pps_write(struct intel_encoder *encoder,
3132
const struct intel_crtc_state *crtc_state);
3233
void intel_dsc_dp_pps_write(struct intel_encoder *encoder,
3334
const struct intel_crtc_state *crtc_state);
35+
void intel_dsc_su_et_parameters_configure(struct intel_dsb *dsb, struct intel_encoder *encoder,
36+
const struct intel_crtc_state *crtc_state, int su_lines);
3437
void intel_vdsc_state_dump(struct drm_printer *p, int indent,
3538
const struct intel_crtc_state *crtc_state);
3639
int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state);

drivers/gpu/drm/i915/display/intel_vdsc_regs.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,18 @@
196196
#define DSC_PPS18_NSL_BPG_OFFSET(offset) REG_FIELD_PREP(DSC_PPS18_NSL_BPG_OFFSET_MASK, offset)
197197
#define DSC_PPS18_SL_OFFSET_ADJ(offset) REG_FIELD_PREP(DSC_PPS18_SL_OFFSET_ADJ_MASK, offset)
198198

199+
#define _LNL_DSC0_SU_PARAMETER_SET_0_PA 0x78064
200+
#define _LNL_DSC1_SU_PARAMETER_SET_0_PA 0x78164
201+
#define _LNL_DSC0_SU_PARAMETER_SET_0_PB 0x78264
202+
#define _LNL_DSC1_SU_PARAMETER_SET_0_PB 0x78364
203+
#define LNL_DSC0_SU_PARAMETER_SET_0(pipe) _MMIO_PIPE((pipe), _LNL_DSC0_SU_PARAMETER_SET_0_PA, _LNL_DSC0_SU_PARAMETER_SET_0_PB)
204+
#define LNL_DSC1_SU_PARAMETER_SET_0(pipe) _MMIO_PIPE((pipe), _LNL_DSC1_SU_PARAMETER_SET_0_PA, _LNL_DSC1_SU_PARAMETER_SET_0_PB)
205+
206+
#define DSC_SUPS0_SU_SLICE_ROW_PER_FRAME_MASK REG_GENMASK(31, 20)
207+
#define DSC_SUPS0_SU_SLICE_ROW_PER_FRAME(rows) REG_FIELD_PREP(DSC_SUPS0_SU_SLICE_ROW_PER_FRAME_MASK, (rows))
208+
#define DSC_SUPS0_SU_PIC_HEIGHT_MASK REG_GENMASK(15, 0)
209+
#define DSC_SUPS0_SU_PIC_HEIGHT(h) REG_FIELD_PREP(DSC_SUPS0_SU_PIC_HEIGHT_MASK, (h))
210+
199211
/* Icelake Rate Control Buffer Threshold Registers */
200212
#define DSCA_RC_BUF_THRESH_0 _MMIO(0x6B230)
201213
#define DSCA_RC_BUF_THRESH_0_UDW _MMIO(0x6B230 + 4)

drivers/gpu/drm/i915/display/intel_vrr.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,18 @@ void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state)
597597
if (!HAS_VRR(display))
598598
return;
599599

600+
/*
601+
* Bspec says:
602+
* "(note: VRR needs to be programmed after
603+
* TRANS_DDI_FUNC_CTL and before TRANS_CONF)."
604+
*
605+
* In practice it turns out that ICL can hang if
606+
* TRANS_VRR_VMAX/FLIPLINE are written before
607+
* enabling TRANS_DDI_FUNC_CTL.
608+
*/
609+
drm_WARN_ON(display->drm,
610+
!(intel_de_read(display, TRANS_DDI_FUNC_CTL(display, cpu_transcoder)) & TRANS_DDI_FUNC_ENABLE));
611+
600612
/*
601613
* This bit seems to have two meanings depending on the platform:
602614
* TGL: generate VRR "safe window" for DSB vblank waits
@@ -939,6 +951,8 @@ void intel_vrr_transcoder_enable(const struct intel_crtc_state *crtc_state)
939951
{
940952
struct intel_display *display = to_intel_display(crtc_state);
941953

954+
intel_vrr_set_transcoder_timings(crtc_state);
955+
942956
if (!intel_vrr_possible(crtc_state))
943957
return;
944958

drivers/gpu/drm/i915/gem/i915_gem_shmem.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,12 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
153153
}
154154
} while (1);
155155

156-
nr_pages = min_t(unsigned long,
157-
folio_nr_pages(folio), page_count - i);
156+
nr_pages = min_array(((unsigned long[]) {
157+
folio_nr_pages(folio),
158+
page_count - i,
159+
max_segment / PAGE_SIZE,
160+
}), 3);
161+
158162
if (!i ||
159163
sg->length >= max_segment ||
160164
folio_pfn(folio) != next_pfn) {
@@ -164,7 +168,9 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
164168
st->nents++;
165169
sg_set_folio(sg, folio, nr_pages * PAGE_SIZE, 0);
166170
} else {
167-
/* XXX: could overflow? */
171+
nr_pages = min_t(unsigned long, nr_pages,
172+
(max_segment - sg->length) / PAGE_SIZE);
173+
168174
sg->length += nr_pages * PAGE_SIZE;
169175
}
170176
next_pfn = folio_pfn(folio) + nr_pages;

0 commit comments

Comments
 (0)