Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+116 -22
-6
drivers/gpu/drm/i915/display/intel_alpm.c
··· 43 43 44 44 void intel_alpm_init(struct intel_dp *intel_dp) 45 45 { 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; 52 46 mutex_init(&intel_dp->alpm.lock); 53 47 } 54 48
-1
drivers/gpu/drm/i915/display/intel_display.c
··· 1614 1614 } 1615 1615 1616 1616 intel_set_transcoder_timings(crtc_state); 1617 - intel_vrr_set_transcoder_timings(crtc_state); 1618 1617 1619 1618 if (cpu_transcoder != TRANSCODER_EDP) 1620 1619 intel_de_write(display, TRANS_MULT(display, cpu_transcoder),
+7
drivers/gpu/drm/i915/display/intel_dp.c
··· 4577 4577 intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector) 4578 4578 { 4579 4579 struct intel_display *display = to_intel_display(intel_dp); 4580 + int ret; 4580 4581 4581 4582 /* this function is meant to be called only once */ 4582 4583 drm_WARN_ON(display->drm, intel_dp->dpcd[DP_DPCD_REV] != 0); ··· 4616 4615 * available (such as HDR backlight controls) 4617 4616 */ 4618 4617 intel_dp_init_source_oui(intel_dp); 4618 + 4619 + /* Read the ALPM DPCD caps */ 4620 + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_RECEIVER_ALPM_CAP, 4621 + &intel_dp->alpm_dpcd); 4622 + if (ret < 0) 4623 + return false; 4619 4624 4620 4625 /* 4621 4626 * This has to be called after intel_dp->edp_dpcd is filled, PSR checks
+48 -12
drivers/gpu/drm/i915/display/intel_psr.c
··· 2619 2619 2620 2620 intel_de_write_dsb(display, dsb, PIPE_SRCSZ_ERLY_TPT(crtc->pipe), 2621 2621 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)); 2622 2628 } 2623 2629 2624 2630 static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, ··· 2695 2689 overlap_damage_area->y2 = damage_area->y2; 2696 2690 } 2697 2691 2698 - static void intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_state) 2692 + static bool intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_state) 2699 2693 { 2700 2694 struct intel_display *display = to_intel_display(crtc_state); 2701 2695 const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; 2702 2696 u16 y_alignment; 2697 + bool su_area_changed = false; 2703 2698 2704 2699 /* ADLP aligns the SU region to vdsc slice height in case dsc is enabled */ 2705 2700 if (crtc_state->dsc.compression_enable && ··· 2709 2702 else 2710 2703 y_alignment = crtc_state->su_y_granularity; 2711 2704 2712 - crtc_state->psr2_su_area.y1 -= crtc_state->psr2_su_area.y1 % y_alignment; 2713 - if (crtc_state->psr2_su_area.y2 % y_alignment) 2705 + if (crtc_state->psr2_su_area.y1 % y_alignment) { 2706 + crtc_state->psr2_su_area.y1 -= crtc_state->psr2_su_area.y1 % y_alignment; 2707 + su_area_changed = true; 2708 + } 2709 + 2710 + if (crtc_state->psr2_su_area.y2 % y_alignment) { 2714 2711 crtc_state->psr2_su_area.y2 = ((crtc_state->psr2_su_area.y2 / 2715 2712 y_alignment) + 1) * y_alignment; 2713 + su_area_changed = true; 2714 + } 2715 + 2716 + return su_area_changed; 2716 2717 } 2717 2718 2718 2719 /* ··· 2854 2839 struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); 2855 2840 struct intel_plane_state *new_plane_state, *old_plane_state; 2856 2841 struct intel_plane *plane; 2857 - bool full_update = false, cursor_in_su_area = false; 2842 + bool full_update = false, su_area_changed; 2858 2843 int i, ret; 2859 2844 2860 2845 if (!crtc_state->enable_psr2_sel_fetch) ··· 2961 2946 if (ret) 2962 2947 return ret; 2963 2948 2964 - /* 2965 - * Adjust su area to cover cursor fully as necessary (early 2966 - * transport). This needs to be done after 2967 - * drm_atomic_add_affected_planes to ensure visible cursor is added into 2968 - * affected planes even when cursor is not updated by itself. 2969 - */ 2970 - intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area); 2949 + do { 2950 + bool cursor_in_su_area; 2971 2951 2972 - intel_psr2_sel_fetch_pipe_alignment(crtc_state); 2952 + /* 2953 + * Adjust su area to cover cursor fully as necessary 2954 + * (early transport). This needs to be done after 2955 + * drm_atomic_add_affected_planes to ensure visible 2956 + * cursor is added into affected planes even when 2957 + * cursor is not updated by itself. 2958 + */ 2959 + intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area); 2960 + 2961 + su_area_changed = intel_psr2_sel_fetch_pipe_alignment(crtc_state); 2962 + 2963 + /* 2964 + * If the cursor was outside the SU area before 2965 + * alignment, the alignment step (which only expands 2966 + * SU) may pull the cursor partially inside, so we 2967 + * must run ET alignment again to fully cover it. But 2968 + * if the cursor was already fully inside before 2969 + * alignment, expanding the SU area won't change that, 2970 + * so no further work is needed. 2971 + */ 2972 + if (cursor_in_su_area) 2973 + break; 2974 + } while (su_area_changed); 2973 2975 2974 2976 /* 2975 2977 * Now that we have the pipe damaged area check if it intersect with ··· 3046 3014 } 3047 3015 3048 3016 skip_sel_fetch_set_loop: 3017 + if (full_update) 3018 + clip_area_update(&crtc_state->psr2_su_area, &crtc_state->pipe_src, 3019 + &crtc_state->pipe_src); 3020 + 3049 3021 psr2_man_trk_ctl_calc(crtc_state, full_update); 3050 3022 crtc_state->pipe_srcsz_early_tpt = 3051 3023 psr2_pipe_srcsz_early_tpt_calc(crtc_state, full_update);
+23
drivers/gpu/drm/i915/display/intel_vdsc.c
··· 767 767 sizeof(dp_dsc_pps_sdp)); 768 768 } 769 769 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 + 770 793 static i915_reg_t dss_ctl1_reg(struct intel_crtc *crtc, enum transcoder cpu_transcoder) 771 794 { 772 795 return is_pipe_dsc(crtc, cpu_transcoder) ?
+3
drivers/gpu/drm/i915/display/intel_vdsc.h
··· 13 13 enum transcoder; 14 14 struct intel_crtc; 15 15 struct intel_crtc_state; 16 + struct intel_dsb; 16 17 struct intel_encoder; 17 18 18 19 bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state); ··· 32 31 const struct intel_crtc_state *crtc_state); 33 32 void intel_dsc_dp_pps_write(struct intel_encoder *encoder, 34 33 const struct intel_crtc_state *crtc_state); 34 + void intel_dsc_su_et_parameters_configure(struct intel_dsb *dsb, struct intel_encoder *encoder, 35 + const struct intel_crtc_state *crtc_state, int su_lines); 35 36 void intel_vdsc_state_dump(struct drm_printer *p, int indent, 36 37 const struct intel_crtc_state *crtc_state); 37 38 int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state);
+12
drivers/gpu/drm/i915/display/intel_vdsc_regs.h
··· 196 196 #define DSC_PPS18_NSL_BPG_OFFSET(offset) REG_FIELD_PREP(DSC_PPS18_NSL_BPG_OFFSET_MASK, offset) 197 197 #define DSC_PPS18_SL_OFFSET_ADJ(offset) REG_FIELD_PREP(DSC_PPS18_SL_OFFSET_ADJ_MASK, offset) 198 198 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 + 199 211 /* Icelake Rate Control Buffer Threshold Registers */ 200 212 #define DSCA_RC_BUF_THRESH_0 _MMIO(0x6B230) 201 213 #define DSCA_RC_BUF_THRESH_0_UDW _MMIO(0x6B230 + 4)
+14
drivers/gpu/drm/i915/display/intel_vrr.c
··· 598 598 return; 599 599 600 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 + 612 + /* 601 613 * This bit seems to have two meanings depending on the platform: 602 614 * TGL: generate VRR "safe window" for DSB vblank waits 603 615 * ADL/DG2: make TRANS_SET_CONTEXT_LATENCY effective with VRR ··· 950 938 void intel_vrr_transcoder_enable(const struct intel_crtc_state *crtc_state) 951 939 { 952 940 struct intel_display *display = to_intel_display(crtc_state); 941 + 942 + intel_vrr_set_transcoder_timings(crtc_state); 953 943 954 944 if (!intel_vrr_possible(crtc_state)) 955 945 return;
+9 -3
drivers/gpu/drm/i915/gem/i915_gem_shmem.c
··· 153 153 } 154 154 } while (1); 155 155 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 + 158 162 if (!i || 159 163 sg->length >= max_segment || 160 164 folio_pfn(folio) != next_pfn) { ··· 168 164 st->nents++; 169 165 sg_set_folio(sg, folio, nr_pages * PAGE_SIZE, 0); 170 166 } else { 171 - /* XXX: could overflow? */ 167 + nr_pages = min_t(unsigned long, nr_pages, 168 + (max_segment - sg->length) / PAGE_SIZE); 169 + 172 170 sg->length += nr_pages * PAGE_SIZE; 173 171 } 174 172 next_pfn = folio_pfn(folio) + nr_pages;