diff options
| author | Mark Brown <broonie@kernel.org> | 2026-05-29 22:42:13 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-05-29 22:42:13 +0100 |
| commit | 3c09a9267c25450885364263e8f90daffc65702f (patch) | |
| tree | c5120c110f9f2f8708bb7e087a24b9ed5b7378fe | |
| parent | c7c18ef008859bbe0017e164f8522aef5bac3e7b (diff) | |
| parent | 7185566c3db090aa5e17a17bca92dfcef9656b03 (diff) | |
| download | linux-next-history-3c09a9267c25450885364263e8f90daffc65702f.tar.gz | |
Merge branch 'for-linux-next' of https://gitlab.freedesktop.org/drm/i915/kernel.git
58 files changed, 1185 insertions, 834 deletions
diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 33d8f6b6afeaf..86d1c9f7f0ff0 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -640,7 +640,7 @@ static struct intel_crtc *single_enabled_crtc(struct intel_display *display) { struct intel_crtc *crtc, *enabled = NULL; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { if (intel_crtc_active(crtc)) { if (enabled) return NULL; @@ -1393,7 +1393,7 @@ static void g4x_merge_wm(struct intel_display *display, wm->hpll_en = true; wm->fbc_en = true; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { const struct g4x_wm_state *wm_state = &crtc->wm.active.g4x; if (!crtc->active) @@ -1415,7 +1415,7 @@ static void g4x_merge_wm(struct intel_display *display, wm->fbc_en = false; } - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { const struct g4x_wm_state *wm_state = &crtc->wm.active.g4x; enum pipe pipe = crtc->pipe; @@ -2034,7 +2034,7 @@ static void vlv_merge_wm(struct intel_display *display, wm->level = display->wm.num_levels - 1; wm->cxsr = true; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { const struct vlv_wm_state *wm_state = &crtc->wm.active.vlv; if (!crtc->active) @@ -2053,7 +2053,7 @@ static void vlv_merge_wm(struct intel_display *display, if (num_active_pipes > 1) wm->level = VLV_WM_LEVEL_PM2; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { const struct vlv_wm_state *wm_state = &crtc->wm.active.vlv; enum pipe pipe = crtc->pipe; @@ -3078,7 +3078,7 @@ static void ilk_merge_wm_level(struct intel_display *display, ret_wm->enable = true; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { const struct intel_pipe_wm *active = &crtc->wm.active.ilk; const struct intel_wm_level *wm = &active->wm[level]; @@ -3218,7 +3218,7 @@ static void ilk_compute_wm_results(struct intel_display *display, } /* LP0 register values */ - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { enum pipe pipe = crtc->pipe; const struct intel_pipe_wm *pipe_wm = &crtc->wm.active.ilk; const struct intel_wm_level *r = &pipe_wm->wm[0]; @@ -3416,7 +3416,7 @@ static void ilk_compute_wm_config(struct intel_display *display, struct intel_crtc *crtc; /* Compute the currently _active_ config */ - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { const struct intel_pipe_wm *wm = &crtc->wm.active.ilk; if (!wm->pipe_enabled) @@ -3533,10 +3533,11 @@ static void ilk_pipe_wm_get_hw_state(struct intel_crtc *crtc) static int ilk_sanitize_watermarks_add_affected(struct drm_atomic_commit *state) { + struct intel_display *display = to_intel_display(state->dev); struct drm_plane *plane; struct intel_crtc *crtc; - for_each_intel_crtc(state->dev, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state; crtc_state = intel_atomic_get_crtc_state(state, crtc); @@ -3581,7 +3582,6 @@ void ilk_wm_sanitize(struct intel_display *display) struct intel_crtc_state *crtc_state; struct drm_modeset_acquire_ctx ctx; int ret; - int i; /* Only supported on platforms that use atomic watermark design */ if (!display->wm.funcs->optimize_watermarks) @@ -3619,7 +3619,7 @@ retry: goto fail; /* Write calculated watermark values back */ - for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state) { crtc_state->wm.need_postvbl_update = true; intel_optimize_watermarks(intel_state, crtc); @@ -3769,7 +3769,7 @@ static void g4x_wm_get_hw_state(struct intel_display *display) wm->cxsr = intel_de_read(display, FW_BLC_SELF) & FW_BLC_SELF_EN; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); struct g4x_wm_state *active = &crtc->wm.active.g4x; @@ -3884,7 +3884,7 @@ static void g4x_wm_sanitize(struct intel_display *display) } } - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); int ret; @@ -3951,7 +3951,7 @@ static void vlv_wm_get_hw_state(struct intel_display *display) vlv_punit_put(display); } - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); struct vlv_wm_state *active = &crtc->wm.active.vlv; @@ -4033,7 +4033,7 @@ static void vlv_wm_sanitize(struct intel_display *display) } } - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); int ret; @@ -4074,7 +4074,7 @@ static void ilk_wm_get_hw_state(struct intel_display *display) ilk_init_lp_watermarks(display); - for_each_intel_crtc(display->drm, crtc) + for_each_intel_crtc(display, crtc) ilk_pipe_wm_get_hw_state(crtc); hw->wm_lp[0] = intel_de_read(display, WM1_LP_ILK); diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index a7350ce8e7163..c6963ea420cc9 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -11,6 +11,7 @@ #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_types.h" +#include "intel_display_utils.h" #include "intel_dp.h" #include "intel_dp_aux.h" #include "intel_psr.h" @@ -359,6 +360,23 @@ void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp, crtc_state->has_lobf = true; } +static u32 get_pr_alpm_as_sdp_transmission_time(const struct intel_crtc_state *crtc_state) +{ + u8 as_sdp_setup_time = intel_dp_as_sdp_transmission_time(); + + switch (as_sdp_setup_time) { + case DP_PR_AS_SDP_SETUP_TIME_T1: + return PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1; + case DP_PR_AS_SDP_SETUP_TIME_DYNAMIC: + return PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1_OR_T2; + case DP_PR_AS_SDP_SETUP_TIME_T2: + return PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T2; + default: + MISSING_CASE(as_sdp_setup_time); + return PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1; + } +} + static void lnl_alpm_configure(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { @@ -382,7 +400,7 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp, ALPM_CTL_AUX_LESS_WAKE_TIME(crtc_state->alpm_state.aux_less_wake_lines); if (intel_dp->as_sdp_supported) { - u32 pr_alpm_ctl = PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1; + u32 pr_alpm_ctl = get_pr_alpm_as_sdp_transmission_time(crtc_state); if (crtc_state->link_off_after_as_sdp_when_pr_active) pr_alpm_ctl |= PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU; diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 38bbd6964d8ee..0e4f0678c53cd 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -200,9 +200,8 @@ bool intel_any_crtc_needs_modeset(struct intel_atomic_state *state) { struct intel_crtc *crtc; struct intel_crtc_state *crtc_state; - int i; - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { if (intel_crtc_needs_modeset(crtc_state)) return true; } diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 9c3a9bbb49f66..dc5a5b639d872 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -67,25 +67,31 @@ struct intel_qgv_info { u8 deinterleave; }; +static int dclk_freq_mhz(int ratio) +{ + /* multiple of 16.666 MHz (100/6) */ + return DIV_ROUND_CLOSEST(ratio * 100, 6); +} + static int dg1_mchbar_read_qgv_point_info(struct intel_display *display, struct intel_qgv_point *sp, int point) { - u32 dclk_ratio, dclk_reference; + u32 dclk_ratio; u32 val; val = intel_mchbar_read(display, SA_PERF_STATUS_0_0_0_MCHBAR_PC); dclk_ratio = REG_FIELD_GET(DG1_QCLK_RATIO_MASK, val); if (val & DG1_QCLK_REFERENCE) - dclk_reference = 6; /* 6 * 16.666 MHz = 100 MHz */ + dclk_ratio *= 6; /* 6 * 16.666 MHz = 100 MHz */ else - dclk_reference = 8; /* 8 * 16.666 MHz = 133 MHz */ - sp->dclk = DIV_ROUND_UP((16667 * dclk_ratio * dclk_reference) + 500, 1000); + dclk_ratio *= 8; /* 8 * 16.666 MHz = 133 MHz */ val = intel_mchbar_read(display, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU); if (val & DG1_GEAR_TYPE) - sp->dclk *= 2; + dclk_ratio *= 2; + sp->dclk = dclk_freq_mhz(dclk_ratio); if (sp->dclk == 0) return -EINVAL; @@ -107,7 +113,6 @@ static int icl_pcode_read_qgv_point_info(struct intel_display *display, int point) { u32 val = 0, val2 = 0; - u16 dclk; int ret; ret = intel_parent_pcode_read(display, ICL_PCODE_MEM_SUBSYSYSTEM_INFO | @@ -116,9 +121,7 @@ static int icl_pcode_read_qgv_point_info(struct intel_display *display, if (ret) return ret; - dclk = val & 0xffff; - sp->dclk = DIV_ROUND_UP((16667 * dclk) + (DISPLAY_VER(display) >= 12 ? 500 : 0), - 1000); + sp->dclk = dclk_freq_mhz(val & 0xffff); sp->t_rp = (val & 0xff0000) >> 16; sp->t_rcd = (val & 0xff000000) >> 24; @@ -208,12 +211,11 @@ static int mtl_read_qgv_point_info(struct intel_display *display, struct intel_qgv_point *sp, int point) { u32 val, val2; - u16 dclk; val = intel_de_read(display, MTL_MEM_SS_INFO_QGV_POINT_LOW(point)); val2 = intel_de_read(display, MTL_MEM_SS_INFO_QGV_POINT_HIGH(point)); - dclk = REG_FIELD_GET(MTL_DCLK_MASK, val); - sp->dclk = DIV_ROUND_CLOSEST(16667 * dclk, 1000); + + sp->dclk = dclk_freq_mhz(REG_FIELD_GET(MTL_DCLK_MASK, val)); sp->t_rp = REG_FIELD_GET(MTL_TRP_MASK, val); sp->t_rcd = REG_FIELD_GET(MTL_TRCD_MASK, val); @@ -238,10 +240,15 @@ intel_read_qgv_point_info(struct intel_display *display, return icl_pcode_read_qgv_point_info(display, sp, point); } +static bool is_y_tile(struct intel_display *display) +{ + /* assume Y tile may be used if supported */ + return !HAS_4TILE(display); +} + static int icl_get_qgv_points(struct intel_display *display, const struct dram_info *dram_info, - struct intel_qgv_info *qi, - bool is_y_tile) + struct intel_qgv_info *qi) { int i, ret; @@ -280,16 +287,16 @@ static int icl_get_qgv_points(struct intel_display *display, } else if (DISPLAY_VER(display) >= 12) { switch (dram_info->type) { case INTEL_DRAM_DDR4: - qi->t_bl = is_y_tile ? 8 : 4; + qi->t_bl = is_y_tile(display) ? 8 : 4; qi->max_numchannels = 2; qi->channel_width = 64; - qi->deinterleave = is_y_tile ? 1 : 2; + qi->deinterleave = is_y_tile(display) ? 1 : 2; break; case INTEL_DRAM_DDR5: - qi->t_bl = is_y_tile ? 16 : 8; + qi->t_bl = is_y_tile(display) ? 16 : 8; qi->max_numchannels = 4; qi->channel_width = 32; - qi->deinterleave = is_y_tile ? 1 : 2; + qi->deinterleave = is_y_tile(display) ? 1 : 2; break; case INTEL_DRAM_LPDDR4: if (display->platform.rocketlake) { @@ -304,7 +311,7 @@ static int icl_get_qgv_points(struct intel_display *display, qi->t_bl = 16; qi->max_numchannels = 8; qi->channel_width = 16; - qi->deinterleave = is_y_tile ? 2 : 4; + qi->deinterleave = is_y_tile(display) ? 2 : 4; break; default: qi->t_bl = 16; @@ -372,85 +379,144 @@ static int icl_sagv_max_dclk(const struct intel_qgv_info *qi) return dclk; } -struct intel_sa_info { - u16 displayrtids; - u8 deburst, deprogbwlimit, derating; +/* + * Bandwidth parameters that are tied to the SoC (as opposed to struct + * intel_display_bw_params). + */ +struct intel_soc_bw_params { + u8 deprogbwlimit; + u8 derating; }; -static const struct intel_sa_info icl_sa_info = { - .deburst = 8, - .deprogbwlimit = 25, /* GB/s */ - .displayrtids = 128, +static const struct intel_soc_bw_params icl_bw_params = { + .deprogbwlimit = 25, .derating = 10, }; -static const struct intel_sa_info tgl_sa_info = { - .deburst = 16, - .deprogbwlimit = 34, /* GB/s */ - .displayrtids = 256, +static const struct intel_soc_bw_params tgl_bw_params = { + .deprogbwlimit = 34, .derating = 10, }; -static const struct intel_sa_info rkl_sa_info = { - .deburst = 8, - .deprogbwlimit = 20, /* GB/s */ - .displayrtids = 128, +static const struct intel_soc_bw_params rkl_bw_params = { + .deprogbwlimit = 20, .derating = 10, }; -static const struct intel_sa_info adls_sa_info = { - .deburst = 16, - .deprogbwlimit = 38, /* GB/s */ - .displayrtids = 256, +static const struct intel_soc_bw_params adl_s_bw_params = { + .deprogbwlimit = 38, .derating = 10, }; -static const struct intel_sa_info adlp_sa_info = { - .deburst = 16, - .deprogbwlimit = 38, /* GB/s */ - .displayrtids = 256, +static const struct intel_soc_bw_params adl_p_bw_params = { + .deprogbwlimit = 38, .derating = 20, }; -static const struct intel_sa_info mtl_sa_info = { - .deburst = 32, - .deprogbwlimit = 38, /* GB/s */ - .displayrtids = 256, - .derating = 10, +static const struct intel_soc_bw_params bmg_bw_params = { + .deprogbwlimit = 53, + .derating = 30, }; -static const struct intel_sa_info xe2_hpd_sa_info = { - .derating = 30, +static const struct intel_soc_bw_params bmg_ecc_bw_params = { .deprogbwlimit = 53, - /* Other values not used by simplified algorithm */ + .derating = 45, }; -static const struct intel_sa_info xe2_hpd_ecc_sa_info = { - .derating = 45, - .deprogbwlimit = 53, - /* Other values not used by simplified algorithm */ +static const struct intel_soc_bw_params ptl_bw_params = { + .deprogbwlimit = 65, + .derating = 10, }; -static const struct intel_sa_info xe3lpd_sa_info = { - .deburst = 32, - .deprogbwlimit = 65, /* GB/s */ - .displayrtids = 256, +static const struct intel_soc_bw_params wcl_bw_params = { + .deprogbwlimit = 22, .derating = 10, }; -static const struct intel_sa_info xe3lpd_3002_sa_info = { +static const struct intel_soc_bw_params *get_soc_bw_params(struct intel_display *display, + const struct dram_info *dram_info) +{ + if (display->platform.icelake || + display->platform.jasperlake || + display->platform.elkhartlake) + return &icl_bw_params; + else if (display->platform.tigerlake || + display->platform.dg1) + return &tgl_bw_params; + else if (display->platform.rocketlake) + return &rkl_bw_params; + else if (display->platform.alderlake_s || + display->platform.meteorlake || + display->platform.lunarlake) + return &adl_s_bw_params; + else if (display->platform.alderlake_p) + return &adl_p_bw_params; + else if (display->platform.battlemage && + dram_info->type == INTEL_DRAM_GDDR_ECC) + return &bmg_ecc_bw_params; + else if (display->platform.battlemage) + return &bmg_bw_params; + else if (display->platform.pantherlake_wildcatlake) + return &wcl_bw_params; + else if (display->platform.pantherlake || + display->platform.novalake) + return &ptl_bw_params; + + return NULL; +} + +/* + * Bandwidth parameters that are tied to the display IP (as opposed to struct + * intel_soc_bw_params). + */ +struct intel_display_bw_params { + u16 displayrtids; + u8 deburst; +}; + +static const struct intel_display_bw_params gen11_bw_params = { + .deburst = 8, + .displayrtids = 128, +}; + +static const struct intel_display_bw_params gen12_bw_params = { + .deburst = 16, + .displayrtids = 256, +}; + +static const struct intel_display_bw_params xelpdp_bw_params = { .deburst = 32, - .deprogbwlimit = 22, /* GB/s */ .displayrtids = 256, - .derating = 10, }; +static const struct intel_display_bw_params *get_display_bw_params(struct intel_display *display) +{ + if (DISPLAY_VER(display) >= 14) { + return &xelpdp_bw_params; + } else if (DISPLAY_VER(display) >= 12) { + /* + * RKL's SoC was based on ICL and the display, even though being + * gen12, had changes to the memory interface to match gen11's, + * consequently inheriting gen11's display-specific bandwidth + * parameters. + */ + if (display->platform.rocketlake) + return &gen11_bw_params; + else + return &gen12_bw_params; + } else if (DISPLAY_VER(display) == 11) { + return &gen11_bw_params; + } + + return NULL; +} + static int icl_get_bw_info(struct intel_display *display, const struct dram_info *dram_info, - const struct intel_sa_info *sa) + const struct intel_soc_bw_params *soc_bw_params, + const struct intel_display_bw_params *display_bw_params) { struct intel_qgv_info qi = {}; - bool is_y_tile = true; /* assume y tile may be used */ int num_channels = max_t(u8, 1, dram_info->num_channels); int ipqdepth, ipqdepthpch = 16; int dclk_max; @@ -458,7 +524,7 @@ static int icl_get_bw_info(struct intel_display *display, int num_groups = ARRAY_SIZE(display->bw.max); int i, ret; - ret = icl_get_qgv_points(display, dram_info, &qi, is_y_tile); + ret = icl_get_qgv_points(display, dram_info, &qi); if (ret) { drm_dbg_kms(display->drm, "Failed to get memory subsystem information, ignoring bandwidth limits"); @@ -466,16 +532,16 @@ static int icl_get_bw_info(struct intel_display *display, } dclk_max = icl_sagv_max_dclk(&qi); - maxdebw = min(sa->deprogbwlimit * 1000, dclk_max * 16 * 6 / 10); - ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels); - qi.deinterleave = DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2); + maxdebw = min(soc_bw_params->deprogbwlimit * 1000, dclk_max * 16 * 6 / 10); + ipqdepth = min(ipqdepthpch, display_bw_params->displayrtids / num_channels); + qi.deinterleave = DIV_ROUND_UP(num_channels, is_y_tile(display) ? 4 : 2); for (i = 0; i < num_groups; i++) { struct intel_bw_info *bi = &display->bw.max[i]; int clpchgroup; int j; - clpchgroup = (sa->deburst * qi.deinterleave / num_channels) << i; + clpchgroup = (display_bw_params->deburst * qi.deinterleave / num_channels) << i; bi->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1; bi->num_qgv_points = qi.num_points; @@ -493,10 +559,10 @@ static int icl_get_bw_info(struct intel_display *display, */ ct = max_t(int, sp->t_rc, sp->t_rp + sp->t_rcd + (clpchgroup - 1) * qi.t_bl + sp->t_rdpre); - bw = DIV_ROUND_UP(sp->dclk * clpchgroup * 32 * num_channels, ct); + bw = sp->dclk * clpchgroup * 32 * num_channels / ct; bi->deratedbw[j] = min(maxdebw, - bw * (100 - sa->derating) / 100); + bw * (100 - soc_bw_params->derating) / 100); drm_dbg_kms(display->drm, "BW%d / QGV %d: num_planes=%d deratedbw=%u\n", @@ -516,21 +582,25 @@ static int icl_get_bw_info(struct intel_display *display, return 0; } +static int tgl_peakbw(int num_channels, int channel_width, int dclk) +{ + return num_channels * (channel_width / 8) * dclk; +} + static int tgl_get_bw_info(struct intel_display *display, const struct dram_info *dram_info, - const struct intel_sa_info *sa) + const struct intel_soc_bw_params *soc_bw_params, + const struct intel_display_bw_params *display_bw_params) { struct intel_qgv_info qi = {}; - bool is_y_tile = true; /* assume y tile may be used */ int num_channels = max_t(u8, 1, dram_info->num_channels); int ipqdepth, ipqdepthpch = 16; - int dclk_max; int maxdebw, peakbw; int clperchgroup; int num_groups = ARRAY_SIZE(display->bw.max); int i, ret; - ret = icl_get_qgv_points(display, dram_info, &qi, is_y_tile); + ret = icl_get_qgv_points(display, dram_info, &qi); if (ret) { drm_dbg_kms(display->drm, "Failed to get memory subsystem information, ignoring bandwidth limits"); @@ -541,27 +611,23 @@ static int tgl_get_bw_info(struct intel_display *display, (dram_info->type == INTEL_DRAM_LPDDR4 || dram_info->type == INTEL_DRAM_LPDDR5)) num_channels *= 2; - qi.deinterleave = qi.deinterleave ? : DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2); - if (num_channels < qi.max_numchannels && DISPLAY_VER(display) >= 12) - qi.deinterleave = max(DIV_ROUND_UP(qi.deinterleave, 2), 1); + qi.deinterleave = max(qi.deinterleave / 2, 1); if (DISPLAY_VER(display) >= 12 && num_channels > qi.max_numchannels) drm_warn(display->drm, "Number of channels exceeds max number of channels."); if (qi.max_numchannels != 0) num_channels = min_t(u8, num_channels, qi.max_numchannels); - dclk_max = icl_sagv_max_dclk(&qi); - - peakbw = num_channels * DIV_ROUND_UP(qi.channel_width, 8) * dclk_max; - maxdebw = min(sa->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 100); + peakbw = tgl_peakbw(num_channels, qi.channel_width, icl_sagv_max_dclk(&qi)); + maxdebw = min(soc_bw_params->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 100); - ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels); + ipqdepth = min(ipqdepthpch, display_bw_params->displayrtids / num_channels); /* * clperchgroup = 4kpagespermempage * clperchperblock, * clperchperblock = 8 / num_channels * interleave */ - clperchgroup = 4 * DIV_ROUND_UP(8, num_channels) * qi.deinterleave; + clperchgroup = 4 * (8 / num_channels) * qi.deinterleave; for (i = 0; i < num_groups; i++) { struct intel_bw_info *bi = &display->bw.max[i]; @@ -569,14 +635,13 @@ static int tgl_get_bw_info(struct intel_display *display, int clpchgroup; int j; - clpchgroup = (sa->deburst * qi.deinterleave / num_channels) << i; + clpchgroup = (display_bw_params->deburst * qi.deinterleave / num_channels) << i; if (i < num_groups - 1) { bi_next = &display->bw.max[i + 1]; if (clpchgroup < clperchgroup) - bi_next->num_planes = (ipqdepth - clpchgroup) / - clpchgroup + 1; + bi_next->num_planes = (ipqdepth - clpchgroup) / clpchgroup; else bi_next->num_planes = 0; } @@ -596,13 +661,11 @@ static int tgl_get_bw_info(struct intel_display *display, */ ct = max_t(int, sp->t_rc, sp->t_rp + sp->t_rcd + (clpchgroup - 1) * qi.t_bl + sp->t_rdpre); - bw = DIV_ROUND_UP(sp->dclk * clpchgroup * 32 * num_channels, ct); + bw = sp->dclk * clpchgroup * 32 * num_channels / ct; bi->deratedbw[j] = min(maxdebw, - bw * (100 - sa->derating) / 100); - bi->peakbw[j] = DIV_ROUND_CLOSEST(sp->dclk * - num_channels * - qi.channel_width, 8); + bw * (100 - soc_bw_params->derating) / 100); + bi->peakbw[j] = tgl_peakbw(num_channels, qi.channel_width, sp->dclk); drm_dbg_kms(display->drm, "BW%d / QGV %d: num_planes=%d deratedbw=%u peakbw: %u\n", @@ -661,29 +724,29 @@ static void dg2_get_bw_info(struct intel_display *display) static int xe2_hpd_get_bw_info(struct intel_display *display, const struct dram_info *dram_info, - const struct intel_sa_info *sa) + const struct intel_soc_bw_params *soc_bw_params) { struct intel_qgv_info qi = {}; int num_channels = dram_info->num_channels; int peakbw, maxdebw; int ret, i; - ret = icl_get_qgv_points(display, dram_info, &qi, true); + ret = icl_get_qgv_points(display, dram_info, &qi); if (ret) { drm_dbg_kms(display->drm, "Failed to get memory subsystem information, ignoring bandwidth limits"); return ret; } - peakbw = num_channels * qi.channel_width / 8 * icl_sagv_max_dclk(&qi); - maxdebw = min(sa->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 10); + peakbw = tgl_peakbw(num_channels, qi.channel_width, icl_sagv_max_dclk(&qi)); + maxdebw = min(soc_bw_params->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 100); for (i = 0; i < qi.num_points; i++) { - const struct intel_qgv_point *point = &qi.points[i]; - int bw = num_channels * (qi.channel_width / 8) * point->dclk; + const struct intel_qgv_point *sp = &qi.points[i]; + int bw = tgl_peakbw(num_channels, qi.channel_width, sp->dclk); display->bw.max[0].deratedbw[i] = - min(maxdebw, (100 - sa->derating) * bw / 100); + min(maxdebw, (100 - soc_bw_params->derating) * bw / 100); display->bw.max[0].peakbw[i] = bw; drm_dbg_kms(display->drm, "QGV %d: deratedbw=%u peakbw: %u\n", @@ -741,11 +804,6 @@ static unsigned int tgl_max_bw_index(struct intel_display *display, { int i; - /* - * Let's return max bw for 0 planes - */ - num_planes = max(1, num_planes); - for (i = ARRAY_SIZE(display->bw.max) - 1; i >= 0; i--) { const struct intel_bw_info *bi = &display->bw.max[i]; @@ -791,11 +849,17 @@ static unsigned int icl_qgv_bw(struct intel_display *display, void intel_bw_init_hw(struct intel_display *display) { - const struct dram_info *dram_info = intel_dram_info(display); + const struct dram_info *dram_info; + const struct intel_soc_bw_params *soc_bw_params; + const struct intel_display_bw_params *display_bw_params; if (!HAS_DISPLAY(display)) return; + dram_info = intel_dram_info(display); + soc_bw_params = get_soc_bw_params(display, dram_info); + display_bw_params = get_display_bw_params(display); + /* * Starting with Xe3p_LPD, the hardware tells us whether memory has ECC * enabled that would impact display bandwidth. However, so far there @@ -805,30 +869,14 @@ void intel_bw_init_hw(struct intel_display *display) if (DISPLAY_VER(display) >= 35) drm_WARN_ON(display->drm, dram_info->ecc_impacting_de_bw); - if (DISPLAY_VER(display) >= 30) { - if (DISPLAY_VERx100(display) == 3002) - tgl_get_bw_info(display, dram_info, &xe3lpd_3002_sa_info); - else - tgl_get_bw_info(display, dram_info, &xe3lpd_sa_info); - } else if (DISPLAY_VERx100(display) >= 1401 && display->platform.dgfx) { - if (dram_info->type == INTEL_DRAM_GDDR_ECC) - xe2_hpd_get_bw_info(display, dram_info, &xe2_hpd_ecc_sa_info); - else - xe2_hpd_get_bw_info(display, dram_info, &xe2_hpd_sa_info); - } else if (DISPLAY_VER(display) >= 14) { - tgl_get_bw_info(display, dram_info, &mtl_sa_info); + if (DISPLAY_VERx100(display) >= 1401 && display->platform.dgfx) { + xe2_hpd_get_bw_info(display, dram_info, soc_bw_params); } else if (display->platform.dg2) { dg2_get_bw_info(display); - } else if (display->platform.alderlake_p) { - tgl_get_bw_info(display, dram_info, &adlp_sa_info); - } else if (display->platform.alderlake_s) { - tgl_get_bw_info(display, dram_info, &adls_sa_info); - } else if (display->platform.rocketlake) { - tgl_get_bw_info(display, dram_info, &rkl_sa_info); - } else if (DISPLAY_VER(display) == 12) { - tgl_get_bw_info(display, dram_info, &tgl_sa_info); + } else if (DISPLAY_VER(display) >= 12) { + tgl_get_bw_info(display, dram_info, soc_bw_params, display_bw_params); } else if (DISPLAY_VER(display) == 11) { - icl_get_bw_info(display, dram_info, &icl_sa_info); + icl_get_bw_info(display, dram_info, soc_bw_params, display_bw_params); } } @@ -1103,7 +1151,7 @@ static int mtl_find_qgv_points(struct intel_display *display, } /* MTL PM DEMAND expects QGV BW parameter in multiples of 100 mbps */ - new_bw_state->qgv_point_peakbw = DIV_ROUND_CLOSEST(qgv_peak_bw, 100); + new_bw_state->qgv_point_peakbw = qgv_peak_bw / 100; return 0; } @@ -1219,10 +1267,8 @@ static int intel_bw_check_data_rate(struct intel_atomic_state *state, bool *chan struct intel_display *display = to_intel_display(state); const struct intel_crtc_state *new_crtc_state, *old_crtc_state; struct intel_crtc *crtc; - int i; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { unsigned int old_data_rate = intel_crtc_bw_data_rate(old_crtc_state); unsigned int new_data_rate = @@ -1268,10 +1314,9 @@ static int intel_bw_check_sagv_mask(struct intel_atomic_state *state) const struct intel_bw_state *old_bw_state = NULL; struct intel_bw_state *new_bw_state = NULL; struct intel_crtc *crtc; - int ret, i; + int ret; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { if (intel_crtc_can_enable_sagv(old_crtc_state) == intel_crtc_can_enable_sagv(new_crtc_state)) continue; @@ -1378,7 +1423,7 @@ void intel_bw_update_hw_state(struct intel_display *display) bw_state->pipe_sagv_reject = 0; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); enum pipe pipe = crtc->pipe; diff --git a/drivers/gpu/drm/i915/display/intel_casf.c b/drivers/gpu/drm/i915/display/intel_casf.c index c2d2746c5f041..cafd21a036320 100644 --- a/drivers/gpu/drm/i915/display/intel_casf.c +++ b/drivers/gpu/drm/i915/display/intel_casf.c @@ -88,7 +88,7 @@ static void intel_casf_compute_win_size(struct intel_crtc_state *crtc_state) crtc_state->pch_pfit.casf.win_size = SHARPNESS_FILTER_SIZE_7X7; } -static void intel_casf_scaler_compute_coef(struct intel_crtc_state *crtc_state); +static void intel_casf_scaler_compute_coeff(struct intel_crtc_state *crtc_state); int intel_casf_compute_config(struct intel_crtc_state *crtc_state) { @@ -118,7 +118,7 @@ int intel_casf_compute_config(struct intel_crtc_state *crtc_state) intel_casf_compute_win_size(crtc_state); - intel_casf_scaler_compute_coef(crtc_state); + intel_casf_scaler_compute_coeff(crtc_state); return 0; } @@ -148,12 +148,12 @@ static int casf_coeff_tap(int i) return i % SCALER_FILTER_NUM_TAPS; } -static u32 casf_coeff(const struct intel_crtc_state *crtc_state, int t) +static u32 casf_coeff(const struct intel_crtc_state *crtc_state, int tap) { struct scaler_filter_coeff value; u32 coeff; - value = crtc_state->pch_pfit.casf.coeff[t]; + value = crtc_state->pch_pfit.casf.coeff[tap]; value.sign = 0; coeff = value.sign << 15 | value.exp << 12 | value.mantissa << 3; @@ -162,7 +162,7 @@ static u32 casf_coeff(const struct intel_crtc_state *crtc_state, int t) /* * 17 phase of 7 taps requires 119 coefficients in 60 dwords per set. - * To enable casf: program scaler coefficients with the coeffients + * To enable casf: program scaler coefficients with the coefficients * that are calculated and stored in pch_pfit.casf.coeff as per * SCALER_COEFFICIENT_FORMAT */ @@ -183,20 +183,20 @@ static void intel_casf_write_coeff(const struct intel_crtc_state *crtc_state) for (i = 0; i < 17 * SCALER_FILTER_NUM_TAPS; i += 2) { u32 tmp; - int t; + int tap; - t = casf_coeff_tap(i); - tmp = casf_coeff(crtc_state, t); + tap = casf_coeff_tap(i); + tmp = casf_coeff(crtc_state, tap); - t = casf_coeff_tap(i + 1); - tmp |= casf_coeff(crtc_state, t) << 16; + tap = casf_coeff_tap(i + 1); + tmp |= casf_coeff(crtc_state, tap) << 16; intel_de_write_fw(display, GLK_PS_COEF_DATA_SET(crtc->pipe, id, 0), tmp); } } -static void convert_sharpness_coef_binary(struct scaler_filter_coeff *coeff, +static void convert_sharpness_coeff_binary(struct scaler_filter_coeff *coeff, u16 coefficient) { if (coefficient < 25) { @@ -214,11 +214,11 @@ static void convert_sharpness_coef_binary(struct scaler_filter_coeff *coeff, } } -static void intel_casf_scaler_compute_coef(struct intel_crtc_state *crtc_state) +static void intel_casf_scaler_compute_coeff(struct intel_crtc_state *crtc_state) { const u16 *filtercoeff; u16 filter_coeff[SCALER_FILTER_NUM_TAPS]; - u16 sumcoeff = 0; + u16 sum_coeff = 0; int i; if (crtc_state->pch_pfit.casf.win_size == 0) @@ -229,11 +229,11 @@ static void intel_casf_scaler_compute_coef(struct intel_crtc_state *crtc_state) filtercoeff = filtercoeff_3; for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++) - sumcoeff += *(filtercoeff + i); + sum_coeff += *(filtercoeff + i); for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++) { - filter_coeff[i] = (*(filtercoeff + i) * 100 / sumcoeff); - convert_sharpness_coef_binary(&crtc_state->pch_pfit.casf.coeff[i], + filter_coeff[i] = (*(filtercoeff + i) * 100 / sum_coeff); + convert_sharpness_coeff_binary(&crtc_state->pch_pfit.casf.coeff[i], filter_coeff[i]); } } diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index a1bf01021d65d..189ae2d3cfc9e 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -3124,10 +3124,9 @@ static int bxt_compute_min_voltage_level(struct intel_atomic_state *state) struct intel_crtc *crtc; struct intel_crtc_state *crtc_state; u8 min_voltage_level; - int i; enum pipe pipe; - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { int ret; if (crtc_state->hw.enable) @@ -3219,13 +3218,13 @@ static int skl_dpll0_vco(struct intel_atomic_state *state) intel_atomic_get_new_cdclk_state(state); struct intel_crtc *crtc; struct intel_crtc_state *crtc_state; - int vco, i; + int vco; vco = cdclk_state->logical.vco; if (!vco) vco = display->cdclk.skl_preferred_vco_freq; - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { if (!crtc_state->hw.enable) continue; @@ -3424,10 +3423,9 @@ static int intel_crtcs_calc_min_cdclk(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state; const struct intel_crtc_state *new_crtc_state; struct intel_crtc *crtc; - int i, ret; + int ret; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { ret = intel_cdclk_update_crtc_min_cdclk(state, crtc, old_crtc_state->min_cdclk, new_crtc_state->min_cdclk, @@ -3647,7 +3645,7 @@ void intel_cdclk_update_hw_state(struct intel_display *display) cdclk_state->enabled_pipes = 0; cdclk_state->active_pipes = 0; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); enum pipe pipe = crtc->pipe; diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 3bfe09d81a4c0..7ef870cd9a169 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1102,19 +1102,37 @@ static void skl_get_config(struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + u32 color; crtc_state->gamma_mode = hsw_read_gamma_mode(crtc); crtc_state->csc_mode = ilk_read_csc_mode(crtc); + color = intel_de_read(display, SKL_BOTTOM_COLOR(crtc->pipe)); if (DISPLAY_VER(display) < 35) { - u32 tmp = intel_de_read(display, SKL_BOTTOM_COLOR(crtc->pipe)); - - if (tmp & SKL_BOTTOM_COLOR_GAMMA_ENABLE) + if (color & SKL_BOTTOM_COLOR_GAMMA_ENABLE) crtc_state->gamma_enable = true; - if (tmp & SKL_BOTTOM_COLOR_CSC_ENABLE) + if (color & SKL_BOTTOM_COLOR_CSC_ENABLE) crtc_state->csc_enable = true; } + + crtc_state->hw.background_color = color & GENMASK(29, 0); +} + +u32 intel_color_background_color_drm_to_hw(u64 drm_background_color) +{ + return (DRM_ARGB64_GETR_BPC(drm_background_color, 10) << 20) | + (DRM_ARGB64_GETG_BPC(drm_background_color, 10) << 10) | + (DRM_ARGB64_GETB_BPC(drm_background_color, 10)); +} + +u64 intel_color_background_color_hw_to_drm(u32 hw_background_color) +{ + u16 r = (hw_background_color >> 20) & 0x3ff; + u16 g = (hw_background_color >> 10) & 0x3ff; + u16 b = hw_background_color & 0x3ff; + + return DRM_ARGB64_PREP_BPC(0x3ff, r, g, b, 10); } static void skl_color_commit_arm(struct intel_dsb *dsb, @@ -1123,16 +1141,11 @@ static void skl_color_commit_arm(struct intel_dsb *dsb, struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum pipe pipe = crtc->pipe; - u32 val = 0; + u32 val = crtc_state->hw.background_color; if (crtc_state->has_psr) ilk_load_csc_matrix(dsb, 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 - * so that its handling will match how we program our planes. - */ if (crtc_state->gamma_enable) val |= SKL_BOTTOM_COLOR_GAMMA_ENABLE; if (crtc_state->csc_enable) @@ -1151,11 +1164,7 @@ static void icl_color_commit_arm(struct intel_dsb *dsb, struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 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_dsb(display, dsb, SKL_BOTTOM_COLOR(pipe), 0); + intel_de_write_dsb(display, dsb, SKL_BOTTOM_COLOR(pipe), crtc_state->hw.background_color); intel_de_write_dsb(display, dsb, GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode); @@ -2107,9 +2116,15 @@ int intel_color_check(struct intel_atomic_state *state, * May need to update pipe gamma enable bits * when C8 planes are getting enabled/disabled. */ - if (!old_crtc_state->c8_planes != !new_crtc_state->c8_planes) + if (!old_crtc_state->c8_planes != !new_crtc_state->c8_planes || + old_crtc_state->hw.background_color != new_crtc_state->hw.background_color) new_crtc_state->uapi.color_mgmt_changed = true; + if (DRM_ARGB64_GETA(new_crtc_state->uapi.background_color) != 0xffff) { + drm_dbg_kms(display->drm, "New background not completely opaque\n"); + return -EINVAL; + } + if (!intel_crtc_needs_color_update(new_crtc_state)) return 0; diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index c21b9bdf7bb8a..f3963a8d1239f 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -47,4 +47,7 @@ void intel_color_plane_program_pipeline(struct intel_dsb *dsb, void intel_color_plane_commit_arm(struct intel_dsb *dsb, const struct intel_plane_state *plane_state); bool intel_color_crtc_has_3dlut(struct intel_display *display, enum pipe pipe); +u32 intel_color_background_color_drm_to_hw(u64 drm_background_color); +u64 intel_color_background_color_hw_to_drm(u32 hw_background_color); + #endif /* __INTEL_COLOR_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 03de219f7a645..7ce2b52297d17 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -7,6 +7,7 @@ #include <linux/slab.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_fourcc.h> #include <drm/drm_plane.h> #include <drm/drm_print.h> @@ -55,7 +56,7 @@ struct intel_crtc *intel_crtc_for_pipe(struct intel_display *display, { struct intel_crtc *crtc; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { if (crtc->pipe == pipe) return crtc; } @@ -405,6 +406,9 @@ static int __intel_crtc_init(struct intel_display *display, enum pipe pipe) BIT(DRM_SCALING_FILTER_DEFAULT) | BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); + if (DISPLAY_VER(display) >= 9) + drm_crtc_attach_background_color_property(&crtc->base); + intel_color_crtc_init(crtc); intel_drrs_crtc_init(crtc); intel_crtc_crc_init(crtc); @@ -534,9 +538,8 @@ void intel_wait_for_vblank_workers(struct intel_atomic_state *state) { struct intel_crtc_state *crtc_state; struct intel_crtc *crtc; - int i; - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { if (!intel_crtc_needs_vblank_work(crtc_state)) continue; @@ -828,10 +831,8 @@ bool intel_any_crtc_enable_changed(struct intel_atomic_state *state) { const struct intel_crtc_state *old_crtc_state, *new_crtc_state; struct intel_crtc *crtc; - int i; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { if (intel_crtc_enable_changed(old_crtc_state, new_crtc_state)) return true; } @@ -849,10 +850,8 @@ bool intel_any_crtc_active_changed(struct intel_atomic_state *state) { const struct intel_crtc_state *old_crtc_state, *new_crtc_state; struct intel_crtc *crtc; - int i; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { if (intel_crtc_active_changed(old_crtc_state, new_crtc_state)) return true; } diff --git a/drivers/gpu/drm/i915/display/intel_dbuf_bw.c b/drivers/gpu/drm/i915/display/intel_dbuf_bw.c index 0562d4df6a078..6cf674c586dc4 100644 --- a/drivers/gpu/drm/i915/display/intel_dbuf_bw.c +++ b/drivers/gpu/drm/i915/display/intel_dbuf_bw.c @@ -184,13 +184,12 @@ int intel_dbuf_bw_calc_min_cdclk(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state; const struct intel_crtc_state *new_crtc_state; struct intel_crtc *crtc; - int ret, i; + int ret; if (DISPLAY_VER(display) < 9) return 0; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { struct intel_dbuf_bw old_dbuf_bw, new_dbuf_bw; skl_crtc_calc_dbuf_bw(&old_dbuf_bw, old_crtc_state); @@ -236,7 +235,7 @@ void intel_dbuf_bw_update_hw_state(struct intel_display *display) if (DISPLAY_VER(display) < 9) return; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 86520848892e0..205978c9feb6d 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3230,9 +3230,8 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state, struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_crtc *pipe_crtc; bool is_hdmi = intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI); - int i; - for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) { + for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state) { const struct intel_crtc_state *old_pipe_crtc_state = intel_atomic_get_old_crtc_state(state, pipe_crtc); @@ -3259,7 +3258,7 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state, intel_ddi_disable_transcoder_func(old_crtc_state); - for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) { + for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state) { const struct intel_crtc_state *old_pipe_crtc_state = intel_atomic_get_old_crtc_state(state, pipe_crtc); @@ -3516,7 +3515,6 @@ static void intel_ddi_enable(struct intel_atomic_state *state, struct intel_crtc *pipe_crtc; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; bool is_hdmi = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI); - int i; /* 128b/132b SST */ if (!is_hdmi && intel_dp_is_uhbr(crtc_state)) { @@ -3550,7 +3548,7 @@ static void intel_ddi_enable(struct intel_atomic_state *state, intel_ddi_wait_for_fec_status(encoder, crtc_state, true); - for_each_pipe_crtc_modeset_enable(display, pipe_crtc, crtc_state, i) { + for_each_pipe_crtc_modeset_enable(display, pipe_crtc, crtc_state) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); @@ -3672,7 +3670,7 @@ void intel_ddi_update_active_dpll(struct intel_atomic_state *state, if (!intel_encoder_is_tc(encoder) || !display->dpll.mgr) return; - for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc, + for_each_intel_crtc_in_pipe_mask(display, pipe_crtc, intel_crtc_joined_pipe_mask(crtc_state)) intel_dpll_update_active(state, pipe_crtc, encoder); } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 9094ab4a9b6c1..8e269b71f18e4 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -714,22 +714,22 @@ static void icl_set_pipe_chicken(const struct intel_crtc_state *crtc_state) bool intel_has_pending_fb_unpin(struct intel_display *display) { - struct drm_crtc *crtc; + struct intel_crtc *crtc; bool cleanup_done; - drm_for_each_crtc(crtc, display->drm) { + for_each_intel_crtc(display, crtc) { struct drm_crtc_commit *commit; - spin_lock(&crtc->commit_lock); - commit = list_first_entry_or_null(&crtc->commit_list, + spin_lock(&crtc->base.commit_lock); + commit = list_first_entry_or_null(&crtc->base.commit_list, struct drm_crtc_commit, commit_entry); cleanup_done = commit ? try_wait_for_completion(&commit->cleanup_done) : true; - spin_unlock(&crtc->commit_lock); + spin_unlock(&crtc->base.commit_lock); if (cleanup_done) continue; - intel_crtc_wait_for_next_vblank(to_intel_crtc(crtc)); + intel_crtc_wait_for_next_vblank(crtc); return true; } @@ -737,6 +737,28 @@ bool intel_has_pending_fb_unpin(struct intel_display *display) return false; } +/* FIXME: remove this and just flush the cleanup wq where appropriate */ +void intel_display_flush_cleanup_work(struct intel_display *display) +{ + struct intel_crtc *crtc; + + for_each_intel_crtc(display, crtc) { + struct drm_crtc_commit *commit; + + spin_lock(&crtc->base.commit_lock); + commit = list_first_entry_or_null(&crtc->base.commit_list, + struct drm_crtc_commit, commit_entry); + if (commit) + drm_crtc_commit_get(commit); + spin_unlock(&crtc->base.commit_lock); + + if (commit) { + wait_for_completion(&commit->cleanup_done); + drm_crtc_commit_put(commit); + } + } +} + /* * Finds the encoder associated with the given CRTC. This can only be * used when we know that the CRTC isn't feeding multiple encoders! @@ -1295,14 +1317,13 @@ static void intel_encoders_update_prepare(struct intel_atomic_state *state) struct intel_display *display = to_intel_display(state); struct intel_crtc_state *new_crtc_state, *old_crtc_state; struct intel_crtc *crtc; - int i; /* * Make sure the DPLL state is up-to-date for fastset TypeC ports after non-blocking commits. * TODO: Update the DPLL state for all cases in the encoder->update_prepare() hook. */ if (display->dpll.mgr) { - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { if (intel_crtc_needs_modeset(new_crtc_state)) continue; @@ -1633,11 +1654,10 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder; struct intel_crtc *pipe_crtc; - int i; if (drm_WARN_ON(display->drm, crtc->active)) return; - for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) { + for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state) { const struct intel_crtc_state *new_pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); @@ -1651,7 +1671,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_encoders_pre_enable(state, crtc); - for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) { + for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); @@ -1669,7 +1689,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (!transcoder_is_dsi(cpu_transcoder)) hsw_configure_cpu_transcoder(new_crtc_state); - for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) { + for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); @@ -1699,7 +1719,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_encoders_enable(state, crtc); - for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) { + for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); enum pipe hsw_workaround_pipe; @@ -1767,7 +1787,6 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); struct intel_crtc *pipe_crtc; - int i; /* * FIXME collapse everything to one hook. @@ -1780,7 +1799,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_encoders_post_pll_disable(state, crtc); - for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) { + for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state) { const struct intel_crtc_state *old_pipe_crtc_state = intel_atomic_get_old_crtc_state(state, pipe_crtc); @@ -3505,7 +3524,7 @@ static void enabled_uncompressed_joiner_pipes(struct intel_display *display, if (!HAS_UNCOMPRESSED_JOINER(display)) return; - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, + for_each_intel_crtc_in_pipe_mask(display, crtc, joiner_pipes(display)) { enum intel_display_power_domain power_domain; enum pipe pipe = crtc->pipe; @@ -3533,7 +3552,7 @@ static void enabled_bigjoiner_pipes(struct intel_display *display, if (!HAS_BIGJOINER(display)) return; - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, + for_each_intel_crtc_in_pipe_mask(display, crtc, joiner_pipes(display)) { enum intel_display_power_domain power_domain; enum pipe pipe = crtc->pipe; @@ -3602,7 +3621,7 @@ static void enabled_ultrajoiner_pipes(struct intel_display *display, if (!HAS_ULTRAJOINER(display)) return; - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, + for_each_intel_crtc_in_pipe_mask(display, crtc, joiner_pipes(display)) { enum intel_display_power_domain power_domain; enum pipe pipe = crtc->pipe; @@ -4505,6 +4524,8 @@ intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_atomic_state *state, crtc_state->uapi.gamma_lut); drm_property_replace_blob(&crtc_state->hw.ctm, crtc_state->uapi.ctm); + crtc_state->hw.background_color = + intel_color_background_color_drm_to_hw(crtc_state->uapi.background_color); } static void @@ -4544,6 +4565,7 @@ copy_joiner_crtc_state_nomodeset(struct intel_atomic_state *state, primary_crtc_state->hw.gamma_lut); drm_property_replace_blob(&secondary_crtc_state->hw.ctm, primary_crtc_state->hw.ctm); + secondary_crtc_state->hw.background_color = primary_crtc_state->hw.background_color; secondary_crtc_state->uapi.color_mgmt_changed = primary_crtc_state->uapi.color_mgmt_changed; } @@ -4881,11 +4903,16 @@ static bool intel_compare_dp_as_sdp(const struct drm_dp_as_sdp *a, const struct drm_dp_as_sdp *b) { - return a->vtotal == b->vtotal && + return a->sdp_type == b->sdp_type && + a->revision == b->revision && + a->length == b->length && + a->vtotal == b->vtotal && a->target_rr == b->target_rr && a->duration_incr_ms == b->duration_incr_ms && a->duration_decr_ms == b->duration_decr_ms && - a->mode == b->mode; + a->target_rr_divider == b->target_rr_divider && + a->mode == b->mode && + a->coasting_vtotal == b->coasting_vtotal; } static bool @@ -5356,6 +5383,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, else PIPE_CONF_CHECK_X(csc_mode); PIPE_CONF_CHECK_BOOL(gamma_enable); + + PIPE_CONF_CHECK_X(hw.background_color); PIPE_CONF_CHECK_BOOL(csc_enable); PIPE_CONF_CHECK_BOOL(wgc_enable); @@ -5556,7 +5585,7 @@ int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state, struct intel_display *display = to_intel_display(state); struct intel_crtc *crtc; - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, mask) { + for_each_intel_crtc_in_pipe_mask(display, crtc, mask) { struct intel_crtc_state *crtc_state; int ret; @@ -5603,7 +5632,7 @@ int intel_modeset_all_pipes_late(struct intel_atomic_state *state, struct intel_display *display = to_intel_display(state); struct intel_crtc *crtc; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state; int ret; @@ -5644,7 +5673,7 @@ int intel_modeset_commit_pipes(struct intel_display *display, state->acquire_ctx = ctx; to_intel_atomic_state(state)->internal = true; - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) { + for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) { struct intel_crtc_state *crtc_state = intel_atomic_get_crtc_state(state, crtc); @@ -5671,15 +5700,15 @@ out: */ static int hsw_mode_set_planes_workaround(struct intel_atomic_state *state) { + struct intel_display *display = to_intel_display(state); struct intel_crtc_state *crtc_state; struct intel_crtc *crtc; struct intel_crtc_state *first_crtc_state = NULL; struct intel_crtc_state *other_crtc_state = NULL; enum pipe first_pipe = INVALID_PIPE, enabled_pipe = INVALID_PIPE; - int i; /* look at all crtc's that are going to be enabled in during modeset */ - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { if (!crtc_state->hw.active || !intel_crtc_needs_modeset(crtc_state)) continue; @@ -5698,7 +5727,7 @@ static int hsw_mode_set_planes_workaround(struct intel_atomic_state *state) return 0; /* w/a possibly needed, check how many crtc's are already enabled. */ - for_each_intel_crtc(state->base.dev, crtc) { + for_each_intel_crtc(display, crtc) { crtc_state = intel_atomic_get_crtc_state(&state->base, crtc); if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); @@ -5729,9 +5758,8 @@ u8 intel_calc_enabled_pipes(struct intel_atomic_state *state, { const struct intel_crtc_state *crtc_state; struct intel_crtc *crtc; - int i; - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { if (crtc_state->hw.enable) enabled_pipes |= BIT(crtc->pipe); else @@ -5746,9 +5774,8 @@ u8 intel_calc_active_pipes(struct intel_atomic_state *state, { const struct intel_crtc_state *crtc_state; struct intel_crtc *crtc; - int i; - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { if (crtc_state->hw.active) active_pipes |= BIT(crtc->pipe); else @@ -5819,9 +5846,8 @@ static int intel_atomic_check_crtcs(struct intel_atomic_state *state) struct intel_display *display = to_intel_display(state); struct intel_crtc_state __maybe_unused *crtc_state; struct intel_crtc *crtc; - int i; - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { int ret; ret = intel_crtc_atomic_check(state, crtc); @@ -5841,9 +5867,8 @@ static bool intel_cpu_transcoders_need_modeset(struct intel_atomic_state *state, { const struct intel_crtc_state *new_crtc_state; struct intel_crtc *crtc; - int i; - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { if (new_crtc_state->hw.enable && transcoders & BIT(new_crtc_state->cpu_transcoder) && intel_crtc_needs_modeset(new_crtc_state)) @@ -5858,9 +5883,8 @@ static bool intel_pipes_need_modeset(struct intel_atomic_state *state, { const struct intel_crtc_state *new_crtc_state; struct intel_crtc *crtc; - int i; - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { if (new_crtc_state->hw.enable && pipes & BIT(crtc->pipe) && intel_crtc_needs_modeset(new_crtc_state)) @@ -5895,7 +5919,7 @@ static int intel_atomic_check_joiner(struct intel_atomic_state *state, return -EINVAL; } - for_each_intel_crtc_in_pipe_mask(display->drm, secondary_crtc, + for_each_intel_crtc_in_pipe_mask(display, secondary_crtc, intel_crtc_joiner_secondary_pipes(primary_crtc_state)) { struct intel_crtc_state *secondary_crtc_state; int ret; @@ -5938,7 +5962,7 @@ static void kill_joiner_secondaries(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, primary_crtc); struct intel_crtc *secondary_crtc; - for_each_intel_crtc_in_pipe_mask(display->drm, secondary_crtc, + for_each_intel_crtc_in_pipe_mask(display, secondary_crtc, intel_crtc_joiner_secondary_pipes(primary_crtc_state)) { struct intel_crtc_state *secondary_crtc_state = intel_atomic_get_new_crtc_state(state, secondary_crtc); @@ -6231,19 +6255,19 @@ static int intel_joiner_add_affected_crtcs(struct intel_atomic_state *state) } /* Now pull in all joined crtcs */ - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { affected_pipes |= crtc_state->joiner_pipes; if (intel_crtc_needs_modeset(crtc_state)) modeset_pipes |= crtc_state->joiner_pipes; } - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, affected_pipes) { + for_each_intel_crtc_in_pipe_mask(display, crtc, affected_pipes) { crtc_state = intel_atomic_get_crtc_state(&state->base, crtc); if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); } - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, modeset_pipes) { + for_each_intel_crtc_in_pipe_mask(display, crtc, modeset_pipes) { int ret; crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -6259,7 +6283,7 @@ static int intel_joiner_add_affected_crtcs(struct intel_atomic_state *state) return ret; } - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { /* Kill old joiner link, we may re-establish afterwards */ if (intel_crtc_needs_modeset(crtc_state) && intel_crtc_is_joiner_primary(crtc_state)) @@ -6277,7 +6301,6 @@ static int intel_atomic_check_config(struct intel_atomic_state *state, struct intel_crtc_state *new_crtc_state; struct intel_crtc *crtc; int ret; - int i; *failed_pipe = INVALID_PIPE; @@ -6289,7 +6312,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state, if (ret) return ret; - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { if (!intel_crtc_needs_modeset(new_crtc_state)) { if (!intel_crtc_is_joiner_secondary(new_crtc_state)) intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc); @@ -6311,7 +6334,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state, goto fail; } - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { if (!intel_crtc_needs_modeset(new_crtc_state)) continue; @@ -6383,13 +6406,12 @@ int intel_atomic_check(struct drm_device *dev, struct intel_atomic_state *state = to_intel_atomic_state(_state); struct intel_crtc_state *old_crtc_state, *new_crtc_state; struct intel_crtc *crtc; - int ret, i; + int ret; if (!intel_display_driver_check_access(display)) return -ENODEV; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { /* * crtc's state no longer considered to be inherited * after the first userspace/client initiated commit. @@ -6415,7 +6437,7 @@ int intel_atomic_check(struct drm_device *dev, if (ret) goto fail; - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { ret = intel_async_flip_check_uapi(state, crtc); if (ret) return ret; @@ -6425,7 +6447,7 @@ int intel_atomic_check(struct drm_device *dev, if (ret) goto fail; - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { if (!intel_crtc_needs_modeset(new_crtc_state)) { if (intel_crtc_is_joiner_secondary(new_crtc_state)) copy_joiner_crtc_state_nomodeset(state, crtc); @@ -6442,8 +6464,7 @@ int intel_atomic_check(struct drm_device *dev, goto fail; } - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { if (!intel_crtc_needs_modeset(new_crtc_state)) continue; @@ -6463,7 +6484,7 @@ int intel_atomic_check(struct drm_device *dev, * needs a full modeset, all other synced crtcs should be * forced a full modeset. */ - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { if (!new_crtc_state->hw.enable || intel_crtc_needs_modeset(new_crtc_state)) continue; @@ -6493,8 +6514,7 @@ int intel_atomic_check(struct drm_device *dev, } } - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { if (!intel_crtc_needs_modeset(new_crtc_state)) continue; @@ -6511,7 +6531,7 @@ int intel_atomic_check(struct drm_device *dev, if (ret) goto fail; - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) new_crtc_state->min_cdclk = intel_crtc_min_cdclk(new_crtc_state); ret = intel_compute_global_watermarks(state); @@ -6544,8 +6564,7 @@ int intel_atomic_check(struct drm_device *dev, if (ret) goto fail; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { intel_color_assert_luts(new_crtc_state); ret = intel_async_flip_check_hw(state, crtc); @@ -6576,8 +6595,7 @@ int intel_atomic_check(struct drm_device *dev, * FIXME would probably be nice to know which crtc specifically * caused the failure, in cases where we can pinpoint it. */ - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) intel_crtc_state_dump(new_crtc_state, state, "failed"); return ret; @@ -6728,7 +6746,7 @@ static void intel_enable_crtc(struct intel_atomic_state *state, if (!intel_crtc_needs_modeset(new_crtc_state)) return; - for_each_intel_crtc_in_pipe_mask_reverse(display->drm, pipe_crtc, + for_each_intel_crtc_in_pipe_mask_reverse(display, pipe_crtc, intel_crtc_joined_pipe_mask(new_crtc_state)) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); @@ -6866,7 +6884,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, * We need to disable pipe CRC before disabling the pipe, * or we race against vblank off. */ - for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc, + for_each_intel_crtc_in_pipe_mask(display, pipe_crtc, intel_crtc_joined_pipe_mask(old_crtc_state)) intel_crtc_disable_pipe_crc(pipe_crtc); @@ -6874,7 +6892,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, display->modeset.funcs->crtc_disable(state, crtc); - for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc, + for_each_intel_crtc_in_pipe_mask(display, pipe_crtc, intel_crtc_joined_pipe_mask(old_crtc_state)) { const struct intel_crtc_state *new_pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); @@ -6893,10 +6911,8 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) const struct intel_crtc_state *new_crtc_state, *old_crtc_state; struct intel_crtc *crtc; u8 disable_pipes = 0; - int i; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { if (!intel_crtc_needs_modeset(new_crtc_state)) continue; @@ -6912,7 +6928,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) disable_pipes |= BIT(crtc->pipe); } - for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) { + for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state) { if ((disable_pipes & BIT(crtc->pipe)) == 0) continue; @@ -6922,7 +6938,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) } /* Only disable port sync and MST slaves */ - for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) { + for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state) { if ((disable_pipes & BIT(crtc->pipe)) == 0) continue; @@ -6944,7 +6960,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) } /* Disable everything else left on */ - for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) { + for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state) { if ((disable_pipes & BIT(crtc->pipe)) == 0) continue; @@ -6963,9 +6979,8 @@ static void intel_commit_modeset_enables(struct intel_atomic_state *state) { struct intel_crtc_state *new_crtc_state; struct intel_crtc *crtc; - int i; - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { if (!new_crtc_state->hw.active) continue; @@ -6973,7 +6988,7 @@ static void intel_commit_modeset_enables(struct intel_atomic_state *state) intel_pre_update_crtc(state, crtc); } - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { if (!new_crtc_state->hw.active) continue; @@ -6988,9 +7003,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) struct intel_crtc_state *old_crtc_state, *new_crtc_state; struct skl_ddb_entry entries[I915_MAX_PIPES] = {}; u8 update_pipes = 0, modeset_pipes = 0; - int i; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { enum pipe pipe = crtc->pipe; if (!new_crtc_state->hw.active) @@ -7014,7 +7028,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) * So first lets enable all pipes that do not need a fullmodeset as * those don't have any external dependency. */ - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { enum pipe pipe = crtc->pipe; if ((update_pipes & BIT(pipe)) == 0) @@ -7030,8 +7044,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) * Commit in reverse order to make joiner primary * send the uapi events after secondaries are done. */ - for_each_oldnew_intel_crtc_in_state_reverse(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state_reverse(state, crtc, old_crtc_state, new_crtc_state) { enum pipe pipe = crtc->pipe; if ((update_pipes & BIT(pipe)) == 0) @@ -7067,7 +7080,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) * Enable all pipes that needs a modeset and do not depends on other * pipes */ - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { enum pipe pipe = crtc->pipe; if ((modeset_pipes & BIT(pipe)) == 0) @@ -7089,7 +7102,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) * Then we enable all remaining pipes that depend on other * pipes: MST slaves and port sync masters */ - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { enum pipe pipe = crtc->pipe; if ((modeset_pipes & BIT(pipe)) == 0) @@ -7106,7 +7119,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) /* * Finally we do the plane updates/etc. for all pipes that got enabled. */ - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { enum pipe pipe = crtc->pipe; if ((update_pipes & BIT(pipe)) == 0) @@ -7119,7 +7132,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) * Commit in reverse order to make joiner primary * send the uapi events after secondaries are done. */ - for_each_new_intel_crtc_in_state_reverse(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state_reverse(state, crtc, new_crtc_state) { enum pipe pipe = crtc->pipe; if ((update_pipes & BIT(pipe)) == 0) @@ -7184,9 +7197,8 @@ static void intel_atomic_cleanup_work(struct work_struct *work) struct intel_display *display = to_intel_display(state); struct intel_crtc_state *old_crtc_state; struct intel_crtc *crtc; - int i; - for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) + for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state) intel_atomic_dsb_cleanup(old_crtc_state); drm_atomic_helper_cleanup_planes(display->drm, &state->base); @@ -7416,9 +7428,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) struct intel_crtc *crtc; struct intel_power_domain_mask put_domains[I915_MAX_PIPES] = {}; struct ref_tracker *wakeref = NULL; - int i; - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) intel_atomic_dsb_prepare(state, crtc); intel_atomic_commit_fence_wait(state); @@ -7427,10 +7438,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_atomic_prepare_plane_clear_colors(state); - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) intel_fbc_prepare_dirty_rect(state, crtc); - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) intel_atomic_dsb_finish(state, crtc); drm_atomic_helper_wait_for_dependencies(&state->base); @@ -7466,8 +7477,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) */ wakeref = intel_display_power_get(display, POWER_DOMAIN_DC_OFF); - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { if (intel_crtc_needs_modeset(new_crtc_state) || intel_crtc_needs_fastset(new_crtc_state)) intel_modeset_get_crtc_power_domains(new_crtc_state, &put_domains[crtc->pipe]); @@ -7478,7 +7488,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_dp_tunnel_atomic_alloc_bw(state); /* FIXME: Eventually get rid of our crtc->config pointer */ - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) crtc->config = new_crtc_state; /* @@ -7500,7 +7510,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_sagv_pre_plane_update(state); /* Complete the events for pipes that have now been disabled */ - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { bool modeset = intel_crtc_needs_modeset(new_crtc_state); /* Complete events for now disable pipes here. */ @@ -7518,7 +7528,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_dbuf_pre_plane_update(state); - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { if (new_crtc_state->do_async_flip) intel_crtc_enable_flip_done(state, crtc); } @@ -7542,7 +7552,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) */ drm_atomic_helper_wait_for_flip_done(display->drm, &state->base); - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { if (new_crtc_state->do_async_flip) intel_crtc_disable_flip_done(state, crtc); @@ -7562,8 +7572,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) * * TODO: Move this (and other cleanup) to an async worker eventually. */ - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { /* * Gen2 reports pipe underruns whenever all planes are disabled. * So re-enable underrun reporting after some planes get enabled. @@ -7580,7 +7589,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_dbuf_post_plane_update(state); - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { intel_post_plane_update(state, crtc); intel_modeset_put_crtc_power_domains(crtc, &put_domains[crtc->pipe]); @@ -7724,9 +7733,8 @@ int intel_atomic_commit(struct drm_device *dev, struct drm_atomic_commit *_state if (DISPLAY_VER(display) < 9 && state->base.legacy_cursor_update) { struct intel_crtc_state *new_crtc_state; struct intel_crtc *crtc; - int i; - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) if (new_crtc_state->wm.need_postvbl_update || new_crtc_state->update_wm_post) state->base.legacy_cursor_update = false; @@ -7786,7 +7794,7 @@ static u32 intel_encoder_possible_crtcs(struct intel_encoder *encoder) struct intel_crtc *crtc; u32 possible_crtcs = 0; - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, encoder->pipe_mask) + for_each_intel_crtc_in_pipe_mask(display, crtc, encoder->pipe_mask) possible_crtcs |= drm_crtc_mask(&crtc->base); return possible_crtcs; @@ -8279,7 +8287,7 @@ int intel_initial_commit(struct intel_display *display) to_intel_atomic_state(state)->internal = true; retry: - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = intel_atomic_get_crtc_state(state, crtc); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 45a90d2fe6ec5..1963dbc802217 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -212,22 +212,22 @@ enum phy_fia { base.head) \ for_each_if((intel_plane)->pipe == (intel_crtc)->pipe) -#define for_each_intel_crtc(dev, crtc) \ +#define for_each_intel_crtc(display, crtc) \ list_for_each_entry((crtc), \ - &to_intel_display(dev)->pipe_list, \ + &(display)->pipe_list, \ pipe_head) -#define for_each_intel_crtc_reverse(dev, crtc) \ +#define for_each_intel_crtc_reverse(display, crtc) \ list_for_each_entry_reverse((crtc), \ - &to_intel_display(dev)->pipe_list, \ + &(display)->pipe_list, \ pipe_head) -#define for_each_intel_crtc_in_pipe_mask(dev, crtc, pipe_mask) \ - for_each_intel_crtc((dev), (crtc)) \ +#define for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) \ + for_each_intel_crtc((display), (crtc)) \ for_each_if((pipe_mask) & BIT((crtc)->pipe)) -#define for_each_intel_crtc_in_pipe_mask_reverse(dev, crtc, pipe_mask) \ - for_each_intel_crtc_reverse((dev), (crtc)) \ +#define for_each_intel_crtc_in_pipe_mask_reverse(display, crtc, pipe_mask) \ + for_each_intel_crtc_reverse((display), (crtc)) \ for_each_if((pipe_mask) & BIT((crtc)->pipe)) #define for_each_intel_encoder(dev, intel_encoder) \ @@ -287,31 +287,26 @@ enum phy_fia { (__i)++) \ for_each_if(plane) -#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \ - for_each_intel_crtc((__state)->base.dev, (crtc)) \ - for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \ - (old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)))) +#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state) \ + for_each_intel_crtc(to_intel_display(__state), (crtc)) \ + for_each_if((old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc))) -#define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \ - for_each_intel_crtc((__state)->base.dev, (crtc)) \ - for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \ - (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc)))) +#define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state) \ + for_each_intel_crtc(to_intel_display(__state), (crtc)) \ + for_each_if((new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))) -#define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state, __i) \ - for_each_intel_crtc_reverse((__state)->base.dev, (crtc)) \ - for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \ - (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc)))) +#define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state) \ + for_each_intel_crtc_reverse(to_intel_display(__state), (crtc)) \ + for_each_if((new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))) -#define for_each_oldnew_intel_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \ - for_each_intel_crtc((__state)->base.dev, (crtc)) \ - for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \ - (old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \ +#define for_each_oldnew_intel_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state) \ + for_each_intel_crtc(to_intel_display(__state), (crtc)) \ + for_each_if(((old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \ (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc)))) -#define for_each_oldnew_intel_crtc_in_state_reverse(__state, crtc, old_crtc_state, new_crtc_state, __i) \ - for_each_intel_crtc_reverse((__state)->base.dev, (crtc)) \ - for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \ - (old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \ +#define for_each_oldnew_intel_crtc_in_state_reverse(__state, crtc, old_crtc_state, new_crtc_state) \ + for_each_intel_crtc_reverse(to_intel_display(__state), (crtc)) \ + for_each_if(((old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \ (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc)))) #define intel_atomic_crtc_state_for_each_plane_state( \ @@ -330,29 +325,29 @@ enum phy_fia { ((connector) = to_intel_connector((__state)->base.connectors[__i].ptr), \ (new_connector_state) = to_intel_digital_connector_state((__state)->base.connectors[__i].new_state), 1)) -#define for_each_crtc_in_masks(display, crtc, first_pipes, second_pipes, i) \ - for ((i) = 0; \ +#define __for_each_crtc_in_masks(display, crtc, first_pipes, second_pipes, i) \ + for (int (i) = 0; \ (i) < (I915_MAX_PIPES * 2) && ((crtc) = intel_crtc_for_pipe(display, (i) % I915_MAX_PIPES), 1); \ (i)++) \ for_each_if((crtc) && ((first_pipes) | ((second_pipes) << I915_MAX_PIPES)) & BIT(i)) -#define for_each_crtc_in_masks_reverse(display, crtc, first_pipes, second_pipes, i) \ - for ((i) = (I915_MAX_PIPES * 2 - 1); \ +#define __for_each_crtc_in_masks_reverse(display, crtc, first_pipes, second_pipes, i) \ + for (int (i) = (I915_MAX_PIPES * 2 - 1); \ (i) >= 0 && ((crtc) = intel_crtc_for_pipe(display, (i) % I915_MAX_PIPES), 1); \ (i)--) \ for_each_if((crtc) && ((first_pipes) | ((second_pipes) << I915_MAX_PIPES)) & BIT(i)) -#define for_each_pipe_crtc_modeset_disable(display, crtc, crtc_state, i) \ - for_each_crtc_in_masks(display, crtc, \ - _intel_modeset_primary_pipes(crtc_state), \ - _intel_modeset_secondary_pipes(crtc_state), \ - i) +#define for_each_pipe_crtc_modeset_disable(display, crtc, crtc_state) \ + __for_each_crtc_in_masks(display, crtc, \ + _intel_modeset_primary_pipes(crtc_state), \ + _intel_modeset_secondary_pipes(crtc_state), \ + __UNIQUE_ID(i)) -#define for_each_pipe_crtc_modeset_enable(display, crtc, crtc_state, i) \ - for_each_crtc_in_masks_reverse(display, crtc, \ - _intel_modeset_primary_pipes(crtc_state), \ - _intel_modeset_secondary_pipes(crtc_state), \ - i) +#define for_each_pipe_crtc_modeset_enable(display, crtc, crtc_state) \ + __for_each_crtc_in_masks_reverse(display, crtc, \ + _intel_modeset_primary_pipes(crtc_state), \ + _intel_modeset_secondary_pipes(crtc_state), \ + __UNIQUE_ID(i)) int intel_atomic_check(struct drm_device *dev, struct drm_atomic_commit *state); u8 intel_calc_enabled_pipes(struct intel_atomic_state *state, @@ -402,6 +397,7 @@ void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state); void i830_enable_pipe(struct intel_display *display, enum pipe pipe); void i830_disable_pipe(struct intel_display *display, enum pipe pipe); bool intel_has_pending_fb_unpin(struct intel_display *display); +void intel_display_flush_cleanup_work(struct intel_display *display); void intel_encoder_destroy(struct drm_encoder *encoder); struct drm_display_mode * intel_encoder_current_mode(struct intel_encoder *encoder); diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index adafe103c2b93..09ce25a6d4b11 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -475,6 +475,9 @@ struct intel_display { } ips; struct { + /* internal display irq functions */ + const struct intel_display_irq_funcs *funcs; + /* protects the irq masks */ spinlock_t lock; diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 81bef000a4e3e..08004c1ba03f4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -572,6 +572,12 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) intel_scaler_info(m, crtc); + if (DISPLAY_VER(display) >= 9) { + u32 background = crtc_state->hw.background_color; + + seq_printf(m, "\tbackground color (10bpc XRGB2101010): %08x\n", background); + } + if (crtc_state->joiner_pipes) seq_printf(m, "\tLinked to 0x%x pipes as a %s\n", crtc_state->joiner_pipes, @@ -606,7 +612,7 @@ static int i915_display_info(struct seq_file *m, void *unused) seq_printf(m, "CRTC info\n"); seq_printf(m, "---------\n"); - for_each_intel_crtc(display->drm, crtc) + for_each_intel_crtc(display, crtc) intel_crtc_info(m, crtc); seq_printf(m, "\n"); @@ -664,7 +670,7 @@ static int i915_ddb_info(struct seq_file *m, void *unused) seq_printf(m, "%-15s%8s%8s%8s\n", "", "Start", "End", "Size"); - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); enum pipe pipe = crtc->pipe; @@ -771,7 +777,7 @@ i915_fifo_underrun_reset_write(struct file *filp, if (!reset) return cnt; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct drm_crtc_commit *commit; struct intel_crtc_state *crtc_state; diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index 074e3ba8fb77d..12e5a522a2994 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -162,7 +162,6 @@ struct intel_display_platforms { #define HAS_DDI(__display) (DISPLAY_INFO(__display)->has_ddi) #define HAS_DISPLAY(__display) (DISPLAY_RUNTIME_INFO(__display)->pipe_mask != 0) #define HAS_DMC(__display) (DISPLAY_RUNTIME_INFO(__display)->has_dmc) -#define HAS_DMC_WAKELOCK(__display) (DISPLAY_VER(__display) >= 20) #define HAS_DOUBLE_BUFFERED_M_N(__display) (IS_DISPLAY_VER((__display), 9, 14) || (__display)->platform.broadwell) #define HAS_DOUBLE_BUFFERED_LUT(__display) (DISPLAY_VER(__display) >= 30) #define HAS_DOUBLE_WIDE(__display) (DISPLAY_VER(__display) < 4) diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 8e6c3dfab5c0c..d0729936f6816 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -212,13 +212,13 @@ int intel_display_driver_probe_noirq(struct intel_display *display) intel_psr_dc5_dc6_wa_init(display); /* FIXME: completely on the wrong abstraction layer */ - ret = intel_power_domains_init(display); + ret = intel_display_power_init(display); if (ret < 0) goto cleanup_bios; intel_pmdemand_init_early(display); - intel_power_domains_init_hw(display, false); + intel_display_power_init_hw(display); if (!HAS_DISPLAY(display)) return 0; @@ -300,7 +300,7 @@ cleanup_wq_dp: destroy_workqueue(display->hotplug.dp_wq); cleanup_pw_domain_dmc: intel_dmc_fini(display); - intel_power_domains_driver_remove(display); + intel_display_power_driver_remove(display); cleanup_bios: intel_bios_driver_remove(display); @@ -641,7 +641,7 @@ void intel_display_driver_remove_nogem(struct intel_display *display) { intel_dmc_fini(display); - intel_power_domains_driver_remove(display); + intel_display_power_driver_remove(display); intel_bios_driver_remove(display); } diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index ca72b799ba0a8..4a821b0674fda 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -23,6 +23,7 @@ #include "intel_fifo_underrun.h" #include "intel_gmbus.h" #include "intel_hotplug_irq.h" +#include "intel_lpe_audio.h" #include "intel_parent.h" #include "intel_pipe_crc_regs.h" #include "intel_plane.h" @@ -529,8 +530,8 @@ static void i9xx_pipestat_irq_reset(struct intel_display *display) } } -void i9xx_pipestat_irq_ack(struct intel_display *display, - u32 iir, u32 pipe_stats[I915_MAX_PIPES]) +static void i9xx_pipestat_irq_ack(struct intel_display *display, + u32 iir, u32 pipe_stats[I915_MAX_PIPES]) { enum pipe pipe; @@ -596,8 +597,8 @@ void i9xx_pipestat_irq_ack(struct intel_display *display, spin_unlock(&display->irq.lock); } -void i915_pipestat_irq_handler(struct intel_display *display, - u32 iir, u32 pipe_stats[I915_MAX_PIPES]) +static void i915_pipestat_irq_handler(struct intel_display *display, + u32 iir, const u32 pipe_stats[I915_MAX_PIPES]) { bool blc_event = false; enum pipe pipe; @@ -620,8 +621,8 @@ void i915_pipestat_irq_handler(struct intel_display *display, intel_opregion_asle_intr(display); } -void i965_pipestat_irq_handler(struct intel_display *display, - u32 iir, u32 pipe_stats[I915_MAX_PIPES]) +static void i965_pipestat_irq_handler(struct intel_display *display, + u32 iir, const u32 pipe_stats[I915_MAX_PIPES]) { bool blc_event = false; enum pipe pipe; @@ -647,8 +648,8 @@ void i965_pipestat_irq_handler(struct intel_display *display, intel_gmbus_irq_handler(display); } -void valleyview_pipestat_irq_handler(struct intel_display *display, - u32 pipe_stats[I915_MAX_PIPES]) +static void valleyview_pipestat_irq_handler(struct intel_display *display, + const u32 pipe_stats[I915_MAX_PIPES]) { enum pipe pipe; @@ -1020,7 +1021,8 @@ void ilk_display_irq_master_enable(struct intel_display *display, u32 de_ier, u3 intel_de_write_fw(display, SDEIER, sde_ier); } -bool ilk_display_irq_handler(struct intel_display *display) +static bool ilk_display_irq_handler(struct intel_display *display, + const struct intel_display_irq_state *state) { u32 de_iir; bool handled = false; @@ -1404,7 +1406,7 @@ static void gen8_read_and_ack_pch_irqs(struct intel_display *display, u32 *pch_i intel_de_write(display, PICAINTERRUPT_IER, pica_ier); } -void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl) +static void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl) { u32 iir; enum pipe pipe; @@ -1565,6 +1567,14 @@ void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl) } } +static bool gen8_display_irq_handler(struct intel_display *display, + const struct intel_display_irq_state *state) +{ + gen8_de_irq_handler(display, state->master_ctl); + + return true; +} + u32 gen11_gu_misc_irq_ack(struct intel_display *display, const u32 master_ctl) { u32 iir; @@ -1589,7 +1599,8 @@ void gen11_gu_misc_irq_handler(struct intel_display *display, const u32 iir) intel_opregion_asle_intr(display); } -void gen11_display_irq_handler(struct intel_display *display) +static bool gen11_display_irq_handler(struct intel_display *display, + const struct intel_display_irq_state *state) { u32 disp_ctl; @@ -1605,6 +1616,8 @@ void gen11_display_irq_handler(struct intel_display *display) intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); intel_display_rpm_assert_unblock(display); + + return true; } static void i915gm_irq_cstate_wa_enable(struct intel_display *display) @@ -1902,8 +1915,8 @@ static void vlv_page_table_error_irq_handler(struct intel_display *display, u32 } } -void vlv_display_error_irq_ack(struct intel_display *display, - u32 *eir, u32 *dpinvgtt) +static void vlv_display_error_irq_ack(struct intel_display *display, + u32 *eir, u32 *dpinvgtt) { u32 emr; @@ -1924,8 +1937,8 @@ void vlv_display_error_irq_ack(struct intel_display *display, intel_de_write(display, VLV_EMR, emr); } -void vlv_display_error_irq_handler(struct intel_display *display, - u32 eir, u32 dpinvgtt) +static void vlv_display_error_irq_handler(struct intel_display *display, + u32 eir, u32 dpinvgtt) { drm_dbg(display->drm, "Master Error, EIR 0x%08x\n", eir); @@ -1951,7 +1964,7 @@ static void _vlv_display_irq_reset(struct intel_display *display) display->irq.vlv_imr_mask = ~0u; } -void vlv_display_irq_reset(struct intel_display *display) +static void vlv_display_irq_reset(struct intel_display *display) { spin_lock_irq(&display->irq.lock); if (display->irq.vlv_display_irqs_enabled) @@ -1959,7 +1972,7 @@ void vlv_display_irq_reset(struct intel_display *display) spin_unlock_irq(&display->irq.lock); } -void i9xx_display_irq_reset(struct intel_display *display) +static void i9xx_display_irq_reset(struct intel_display *display) { if (HAS_HOTPLUG(display)) { i915_hotplug_interrupt_update(display, 0xffffffff, 0); @@ -1985,7 +1998,7 @@ u32 i9xx_display_irq_enable_mask(struct intel_display *display) return enable_mask; } -void i915_display_irq_postinstall(struct intel_display *display) +static void i915_display_irq_postinstall(struct intel_display *display) { /* * Interrupt setup is already guaranteed to be single-threaded, this is @@ -1999,7 +2012,7 @@ void i915_display_irq_postinstall(struct intel_display *display) i915_enable_asle_pipestat(display); } -void i965_display_irq_postinstall(struct intel_display *display) +static void i965_display_irq_postinstall(struct intel_display *display) { /* * Interrupt setup is already guaranteed to be single-threaded, this is @@ -2014,6 +2027,38 @@ void i965_display_irq_postinstall(struct intel_display *display) i915_enable_asle_pipestat(display); } +static void i9xx_display_irq_ack(struct intel_display *display, + struct intel_display_irq_state *state) +{ + if (state->iir & I915_DISPLAY_PORT_INTERRUPT) + state->hotplug_status = i9xx_hpd_irq_ack(display); + + /* Call regardless, as some status bits might not be signalled in IIR */ + i9xx_pipestat_irq_ack(display, state->iir, state->pipe_stats); +} + +static bool i965_display_irq_handler(struct intel_display *display, + const struct intel_display_irq_state *state) +{ + if (state->hotplug_status) + i9xx_hpd_irq_handler(display, state->hotplug_status); + + i965_pipestat_irq_handler(display, state->iir, state->pipe_stats); + + return true; +} + +static bool i915_display_irq_handler(struct intel_display *display, + const struct intel_display_irq_state *state) +{ + if (state->hotplug_status) + i9xx_hpd_irq_handler(display, state->hotplug_status); + + i915_pipestat_irq_handler(display, state->iir, state->pipe_stats); + + return true; +} + static u32 vlv_error_mask(void) { /* TODO enable other errors too? */ @@ -2061,7 +2106,7 @@ static void _vlv_display_irq_postinstall(struct intel_display *display) irq_init(display, VLV_IRQ_REGS, display->irq.vlv_imr_mask, enable_mask); } -void vlv_display_irq_postinstall(struct intel_display *display) +static void vlv_display_irq_postinstall(struct intel_display *display) { spin_lock_irq(&display->irq.lock); if (display->irq.vlv_display_irqs_enabled) @@ -2069,6 +2114,46 @@ void vlv_display_irq_postinstall(struct intel_display *display) spin_unlock_irq(&display->irq.lock); } +static u32 vlv_lpe_irq_mask(struct intel_display *display) +{ + if (display->platform.cherryview) + return I915_LPE_PIPE_A_INTERRUPT | I915_LPE_PIPE_B_INTERRUPT | + I915_LPE_PIPE_C_INTERRUPT; + else + return I915_LPE_PIPE_A_INTERRUPT | I915_LPE_PIPE_B_INTERRUPT; +} + +static void vlv_display_irq_ack(struct intel_display *display, + struct intel_display_irq_state *state) +{ + if (state->iir & I915_DISPLAY_PORT_INTERRUPT) + state->hotplug_status = i9xx_hpd_irq_ack(display); + + if (state->iir & I915_MASTER_ERROR_INTERRUPT) + vlv_display_error_irq_ack(display, &state->eir, &state->dpinvgtt); + + /* Call regardless, as some status bits might not be signalled in IIR */ + i9xx_pipestat_irq_ack(display, state->iir, state->pipe_stats); + + /* The handler acks the irq, so need to call the handler here */ + if (state->iir & vlv_lpe_irq_mask(display)) + intel_lpe_audio_irq_handler(display); +} + +static bool vlv_display_irq_handler(struct intel_display *display, + const struct intel_display_irq_state *state) +{ + if (state->hotplug_status) + i9xx_hpd_irq_handler(display, state->hotplug_status); + + if (state->iir & I915_MASTER_ERROR_INTERRUPT) + vlv_display_error_irq_handler(display, state->eir, state->dpinvgtt); + + valleyview_pipestat_irq_handler(display, state->pipe_stats); + + return true; +} + static void ibx_display_irq_reset(struct intel_display *display) { if (HAS_PCH_NOP(display)) @@ -2080,7 +2165,7 @@ static void ibx_display_irq_reset(struct intel_display *display) intel_de_write(display, SERR_INT, 0xffffffff); } -void ilk_display_irq_reset(struct intel_display *display) +static void ilk_display_irq_reset(struct intel_display *display) { irq_reset(display, DE_IRQ_REGS); display->irq.ilk_de_imr_mask = ~0u; @@ -2096,13 +2181,10 @@ void ilk_display_irq_reset(struct intel_display *display) ibx_display_irq_reset(display); } -void gen8_display_irq_reset(struct intel_display *display) +static void gen8_display_irq_reset(struct intel_display *display) { enum pipe pipe; - if (!HAS_DISPLAY(display)) - return; - intel_de_write(display, EDP_PSR_IMR, 0xffffffff); intel_de_write(display, EDP_PSR_IIR, 0xffffffff); @@ -2118,15 +2200,12 @@ void gen8_display_irq_reset(struct intel_display *display) ibx_display_irq_reset(display); } -void gen11_display_irq_reset(struct intel_display *display) +static void gen11_display_irq_reset(struct intel_display *display) { enum pipe pipe; u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_D); - if (!HAS_DISPLAY(display)) - return; - intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0); if (DISPLAY_VER(display) >= 12) { @@ -2272,7 +2351,7 @@ out: spin_unlock_irq(&display->irq.lock); } -void ilk_de_irq_postinstall(struct intel_display *display) +static void ilk_de_irq_postinstall(struct intel_display *display) { u32 display_mask, extra_mask; @@ -2316,7 +2395,7 @@ void ilk_de_irq_postinstall(struct intel_display *display) static void mtp_irq_postinstall(struct intel_display *display); static void icp_irq_postinstall(struct intel_display *display); -void gen8_de_irq_postinstall(struct intel_display *display) +static void gen8_de_irq_postinstall(struct intel_display *display) { u32 de_pipe_masked = gen8_de_pipe_fault_mask(display) | GEN8_PIPE_CDCLK_CRC_DONE; @@ -2443,28 +2522,92 @@ static void icp_irq_postinstall(struct intel_display *display) irq_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); } -void gen11_de_irq_postinstall(struct intel_display *display) +static void gen11_de_irq_postinstall(struct intel_display *display) { - if (!HAS_DISPLAY(display)) - return; - gen8_de_irq_postinstall(display); intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); } -void dg1_de_irq_postinstall(struct intel_display *display) +struct intel_display_irq_funcs { + void (*reset)(struct intel_display *display); + void (*postinstall)(struct intel_display *display); + void (*ack)(struct intel_display *display, struct intel_display_irq_state *state); + bool (*handler)(struct intel_display *display, const struct intel_display_irq_state *state); +}; + +static const struct intel_display_irq_funcs gen11_display_irq_funcs = { + .reset = gen11_display_irq_reset, + .postinstall = gen11_de_irq_postinstall, + .handler = gen11_display_irq_handler, +}; + +static const struct intel_display_irq_funcs gen8_display_irq_funcs = { + .reset = gen8_display_irq_reset, + .postinstall = gen8_de_irq_postinstall, + .handler = gen8_display_irq_handler, +}; + +static const struct intel_display_irq_funcs vlv_display_irq_funcs = { + .reset = vlv_display_irq_reset, + .postinstall = vlv_display_irq_postinstall, + .ack = vlv_display_irq_ack, + .handler = vlv_display_irq_handler, +}; + +static const struct intel_display_irq_funcs ilk_display_irq_funcs = { + .reset = ilk_display_irq_reset, + .postinstall = ilk_de_irq_postinstall, + .handler = ilk_display_irq_handler, +}; + +static const struct intel_display_irq_funcs i965_display_irq_funcs = { + .reset = i9xx_display_irq_reset, + .postinstall = i965_display_irq_postinstall, + .ack = i9xx_display_irq_ack, + .handler = i965_display_irq_handler, +}; + +static const struct intel_display_irq_funcs i915_display_irq_funcs = { + .reset = i9xx_display_irq_reset, + .postinstall = i915_display_irq_postinstall, + .ack = i9xx_display_irq_ack, + .handler = i915_display_irq_handler, +}; + +void intel_display_irq_reset(struct intel_display *display) +{ + if (!HAS_DISPLAY(display)) + return; + + display->irq.funcs->reset(display); +} + +void intel_display_irq_postinstall(struct intel_display *display) { if (!HAS_DISPLAY(display)) return; - gen8_de_irq_postinstall(display); - intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); + display->irq.funcs->postinstall(display); } -struct intel_display_irq_funcs { - void (*reset)(struct intel_display *display); -}; +void intel_display_irq_ack(struct intel_display *display, + struct intel_display_irq_state *state) +{ + if (!HAS_DISPLAY(display) || !display->irq.funcs->ack) + return; + + display->irq.funcs->ack(display, state); +} + +bool intel_display_irq_handler(struct intel_display *display, + const struct intel_display_irq_state *state) +{ + if (!HAS_DISPLAY(display) || !display->irq.funcs->handler) + return true; + + return display->irq.funcs->handler(display, state); +} void intel_display_irq_init(struct intel_display *display) { @@ -2476,6 +2619,19 @@ void intel_display_irq_init(struct intel_display *display) INIT_WORK(&display->irq.vblank_notify_work, intel_display_vblank_notify_work); + + if (DISPLAY_VER(display) >= 11) + display->irq.funcs = &gen11_display_irq_funcs; + else if (display->platform.cherryview || display->platform.valleyview) + display->irq.funcs = &vlv_display_irq_funcs; + else if (DISPLAY_VER(display) >= 8) + display->irq.funcs = &gen8_display_irq_funcs; + else if (DISPLAY_VER(display) >= 5) + display->irq.funcs = &ilk_display_irq_funcs; + else if (DISPLAY_VER(display) == 4) + display->irq.funcs = &i965_display_irq_funcs; + else + display->irq.funcs = &i915_display_irq_funcs; } struct intel_display_irq_snapshot { diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.h b/drivers/gpu/drm/i915/display/intel_display_irq.h index b25d180254d75..a1227cee885ae 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.h +++ b/drivers/gpu/drm/i915/display/intel_display_irq.h @@ -51,41 +51,30 @@ void bdw_disable_vblank(struct drm_crtc *crtc); void ilk_display_irq_master_disable(struct intel_display *display, u32 *de_ier, u32 *sde_ier); void ilk_display_irq_master_enable(struct intel_display *display, u32 de_ier, u32 sde_ier); -bool ilk_display_irq_handler(struct intel_display *display); -void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl); -void gen11_display_irq_handler(struct intel_display *display); u32 gen11_gu_misc_irq_ack(struct intel_display *display, const u32 master_ctl); void gen11_gu_misc_irq_handler(struct intel_display *display, const u32 iir); -void i9xx_display_irq_reset(struct intel_display *display); -void ilk_display_irq_reset(struct intel_display *display); -void vlv_display_irq_reset(struct intel_display *display); -void gen8_display_irq_reset(struct intel_display *display); -void gen11_display_irq_reset(struct intel_display *display); +struct intel_display_irq_state { + u32 master_ctl; + u32 iir; + u32 eir; + u32 hotplug_status; + u32 dpinvgtt; + u32 pipe_stats[I915_MAX_PIPES]; +}; + +void intel_display_irq_reset(struct intel_display *display); +void intel_display_irq_postinstall(struct intel_display *display); +void intel_display_irq_ack(struct intel_display *display, struct intel_display_irq_state *state); +bool intel_display_irq_handler(struct intel_display *display, const struct intel_display_irq_state *state); u32 i9xx_display_irq_enable_mask(struct intel_display *display); -void i915_display_irq_postinstall(struct intel_display *display); -void i965_display_irq_postinstall(struct intel_display *display); -void vlv_display_irq_postinstall(struct intel_display *display); -void ilk_de_irq_postinstall(struct intel_display *display); -void gen8_de_irq_postinstall(struct intel_display *display); -void gen11_de_irq_postinstall(struct intel_display *display); -void dg1_de_irq_postinstall(struct intel_display *display); u32 i915_pipestat_enable_mask(struct intel_display *display, enum pipe pipe); void i915_enable_pipestat(struct intel_display *display, enum pipe pipe, u32 status_mask); void i915_disable_pipestat(struct intel_display *display, enum pipe pipe, u32 status_mask); -void i9xx_pipestat_irq_ack(struct intel_display *display, u32 iir, u32 pipe_stats[I915_MAX_PIPES]); - -void i915_pipestat_irq_handler(struct intel_display *display, u32 iir, u32 pipe_stats[I915_MAX_PIPES]); -void i965_pipestat_irq_handler(struct intel_display *display, u32 iir, u32 pipe_stats[I915_MAX_PIPES]); -void valleyview_pipestat_irq_handler(struct intel_display *display, u32 pipe_stats[I915_MAX_PIPES]); - -void vlv_display_error_irq_ack(struct intel_display *display, u32 *eir, u32 *dpinvgtt); -void vlv_display_error_irq_handler(struct intel_display *display, u32 eir, u32 dpinvgtt); - void intel_display_irq_init(struct intel_display *display); void i915gm_irq_cstate_wa(struct intel_display *display, bool enable); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 751e6b7d4a292..2e51dfcd5dce2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1018,13 +1018,13 @@ static u32 get_allowed_dc_mask(struct intel_display *display, int enable_dc) } /** - * intel_power_domains_init - initializes the power domain structures + * intel_display_power_init - initializes the power domain structures * @display: display device instance * * Initializes the power domain structures for @display depending upon the * supported platform. */ -int intel_power_domains_init(struct intel_display *display) +int intel_display_power_init(struct intel_display *display) { struct i915_power_domains *power_domains = &display->power.domains; @@ -1045,12 +1045,12 @@ int intel_power_domains_init(struct intel_display *display) } /** - * intel_power_domains_cleanup - clean up power domains resources + * intel_display_power_cleanup - clean up power domains resources * @display: display device instance * - * Release any resources acquired by intel_power_domains_init() + * Release any resources acquired by intel_display_power_init() */ -void intel_power_domains_cleanup(struct intel_display *display) +void intel_display_power_cleanup(struct intel_display *display) { intel_display_power_map_cleanup(&display->power.domains); } @@ -1203,7 +1203,7 @@ static void assert_can_disable_lcpll(struct intel_display *display) { struct intel_crtc *crtc; - for_each_intel_crtc(display->drm, crtc) + for_each_intel_crtc(display, crtc) INTEL_DISPLAY_STATE_WARN(display, crtc->active, "CRTC for pipe %c enabled\n", pipe_name(crtc->pipe)); @@ -1917,23 +1917,7 @@ static void assert_isp_power_gated(struct intel_display *display) static void intel_power_domains_verify_state(struct intel_display *display); -/** - * intel_power_domains_init_hw - initialize hardware power domain state - * @display: display device instance - * @resume: Called from resume code paths or not - * - * This function initializes the hardware power domain state and enables all - * power wells belonging to the INIT power domain. Power wells in other - * domains (and not in the INIT domain) are referenced or disabled by - * intel_modeset_readout_hw_state(). After that the reference count of each - * power well must match its HW enabled state, see - * intel_power_domains_verify_state(). - * - * It will return with power domains disabled (to be enabled later by - * intel_power_domains_enable()) and must be paired with - * intel_power_domains_driver_remove(). - */ -void intel_power_domains_init_hw(struct intel_display *display, bool resume) +static void __intel_display_power_init_hw(struct intel_display *display, bool resume) { struct i915_power_domains *power_domains = &display->power.domains; @@ -1967,7 +1951,7 @@ void intel_power_domains_init_hw(struct intel_display *display, bool resume) * Keep all power wells enabled for any dependent HW access during * initialization and to make sure we keep BIOS enabled display HW * resources powered until display HW readout is complete. We drop - * this reference in intel_power_domains_enable(). + * this reference in intel_display_power_enable(). */ drm_WARN_ON(display->drm, power_domains->init_wakeref); power_domains->init_wakeref = @@ -1985,17 +1969,37 @@ void intel_power_domains_init_hw(struct intel_display *display, bool resume) } /** - * intel_power_domains_driver_remove - deinitialize hw power domain state + * intel_display_power_init_hw - initialize hardware power domain state + * @display: display device instance + * + * This function initializes the hardware power domain state and enables all + * power wells belonging to the INIT power domain. Power wells in other + * domains (and not in the INIT domain) are referenced or disabled by + * intel_modeset_readout_hw_state(). After that the reference count of each + * power well must match its HW enabled state, see + * intel_power_domains_verify_state(). + * + * It will return with power domains disabled (to be enabled later by + * intel_display_power_enable()) and must be paired with + * intel_display_power_driver_remove(). + */ +void intel_display_power_init_hw(struct intel_display *display) +{ + __intel_display_power_init_hw(display, false); +} + +/** + * intel_display_power_driver_remove - deinitialize hw power domain state * @display: display device instance * * De-initializes the display power domain HW state. It also ensures that the * device stays powered up so that the driver can be reloaded. * * It must be called with power domains already disabled (after a call to - * intel_power_domains_disable()) and must be paired with - * intel_power_domains_init_hw(). + * intel_display_power_disable()) and must be paired with + * intel_display_power_init_hw(). */ -void intel_power_domains_driver_remove(struct intel_display *display) +void intel_display_power_driver_remove(struct intel_display *display) { struct ref_tracker *wakeref __maybe_unused = fetch_and_zero(&display->power.domains.init_wakeref); @@ -2014,7 +2018,7 @@ void intel_power_domains_driver_remove(struct intel_display *display) } /** - * intel_power_domains_sanitize_state - sanitize power domains state + * intel_display_power_sanitize_state - sanitize power domains state * @display: display device instance * * Sanitize the power domains state during driver loading and system resume. @@ -2023,7 +2027,7 @@ void intel_power_domains_driver_remove(struct intel_display *display) * on it by the time this function is called, after the state of all the * pipe, encoder, etc. HW resources have been sanitized). */ -void intel_power_domains_sanitize_state(struct intel_display *display) +void intel_display_power_sanitize_state(struct intel_display *display) { struct i915_power_domains *power_domains = &display->power.domains; struct i915_power_well *power_well; @@ -2045,18 +2049,18 @@ void intel_power_domains_sanitize_state(struct intel_display *display) } /** - * intel_power_domains_enable - enable toggling of display power wells + * intel_display_power_enable - enable toggling of display power wells * @display: display device instance * * Enable the ondemand enabling/disabling of the display power wells. Note that * power wells not belonging to POWER_DOMAIN_INIT are allowed to be toggled * only at specific points of the display modeset sequence, thus they are not - * affected by the intel_power_domains_enable()/disable() calls. The purpose + * affected by the intel_display_power_enable()/disable() calls. The purpose * of these function is to keep the rest of power wells enabled until the end * of display HW readout (which will acquire the power references reflecting * the current HW state). */ -void intel_power_domains_enable(struct intel_display *display) +void intel_display_power_enable(struct intel_display *display) { struct ref_tracker *wakeref __maybe_unused = fetch_and_zero(&display->power.domains.init_wakeref); @@ -2066,13 +2070,13 @@ void intel_power_domains_enable(struct intel_display *display) } /** - * intel_power_domains_disable - disable toggling of display power wells + * intel_display_power_disable - disable toggling of display power wells * @display: display device instance * * Disable the ondemand enabling/disabling of the display power wells. See - * intel_power_domains_enable() for which power wells this call controls. + * intel_display_power_enable() for which power wells this call controls. */ -void intel_power_domains_disable(struct intel_display *display) +void intel_display_power_disable(struct intel_display *display) { struct i915_power_domains *power_domains = &display->power.domains; @@ -2092,9 +2096,9 @@ void intel_power_domains_disable(struct intel_display *display) * system suspend. * * It must be called with power domains already disabled (after a call to - * intel_power_domains_disable()) and paired with intel_power_domains_resume(). + * intel_display_power_disable()) and paired with intel_power_domains_resume(). */ -void intel_power_domains_suspend(struct intel_display *display, bool s2idle) +static void intel_power_domains_suspend(struct intel_display *display, bool s2idle) { struct i915_power_domains *power_domains = &display->power.domains; struct ref_tracker *wakeref __maybe_unused = @@ -2144,15 +2148,15 @@ void intel_power_domains_suspend(struct intel_display *display, bool s2idle) * This function resume the hardware power domain state during system resume. * * It will return with power domain support disabled (to be enabled later by - * intel_power_domains_enable()) and must be paired with + * intel_display_power_enable()) and must be paired with * intel_power_domains_suspend(). */ -void intel_power_domains_resume(struct intel_display *display) +static void intel_power_domains_resume(struct intel_display *display) { struct i915_power_domains *power_domains = &display->power.domains; if (power_domains->display_core_suspended) { - intel_power_domains_init_hw(display, true); + __intel_display_power_init_hw(display, true); power_domains->display_core_suspended = false; } else { drm_WARN_ON(display->drm, power_domains->init_wakeref); @@ -2285,7 +2289,7 @@ void intel_display_power_resume_early(struct intel_display *display) intel_power_domains_resume(display); } -void intel_display_power_suspend(struct intel_display *display) +void intel_display_power_runtime_suspend(struct intel_display *display) { if (DISPLAY_VER(display) >= 11) { icl_display_core_uninit(display); @@ -2298,7 +2302,7 @@ void intel_display_power_suspend(struct intel_display *display) } } -void intel_display_power_resume(struct intel_display *display) +void intel_display_power_runtime_resume(struct intel_display *display) { struct i915_power_domains *power_domains = &display->power.domains; diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index d616d5d09cbed..56dc89eed3f89 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -169,24 +169,23 @@ struct intel_display_power_domain_set { for ((__domain) = 0; (__domain) < POWER_DOMAIN_NUM; (__domain)++) \ for_each_if(test_bit((__domain), (__mask)->bits)) -int intel_power_domains_init(struct intel_display *display); -void intel_power_domains_cleanup(struct intel_display *display); -void intel_power_domains_init_hw(struct intel_display *display, bool resume); -void intel_power_domains_driver_remove(struct intel_display *display); -void intel_power_domains_enable(struct intel_display *display); -void intel_power_domains_disable(struct intel_display *display); -void intel_power_domains_suspend(struct intel_display *display, bool s2idle); -void intel_power_domains_resume(struct intel_display *display); -void intel_power_domains_sanitize_state(struct intel_display *display); +int intel_display_power_init(struct intel_display *display); +void intel_display_power_cleanup(struct intel_display *display); +void intel_display_power_init_hw(struct intel_display *display); +void intel_display_power_driver_remove(struct intel_display *display); +void intel_display_power_enable(struct intel_display *display); +void intel_display_power_disable(struct intel_display *display); +void intel_display_power_sanitize_state(struct intel_display *display); void intel_display_power_suspend_late(struct intel_display *display, bool s2idle); void intel_display_power_resume_early(struct intel_display *display); -void intel_display_power_suspend(struct intel_display *display); -void intel_display_power_resume(struct intel_display *display); void intel_display_power_set_target_dc_state(struct intel_display *display, u32 state); u32 intel_display_power_get_current_dc_state(struct intel_display *display); +void intel_display_power_runtime_suspend(struct intel_display *display); +void intel_display_power_runtime_resume(struct intel_display *display); + bool intel_display_power_is_enabled(struct intel_display *display, enum intel_display_power_domain domain); struct ref_tracker *intel_display_power_get(struct intel_display *display, diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h index 27ebc32cb61a5..504d105935bc0 100644 --- a/drivers/gpu/drm/i915/display/intel_display_trace.h +++ b/drivers/gpu/drm/i915/display/intel_display_trace.h @@ -84,7 +84,7 @@ TRACE_EVENT(intel_pipe_enable, sizeof(__entry->frame[0]) * I915_MAX_PIPES); memset(__entry->scanline, 0, sizeof(__entry->scanline[0]) * I915_MAX_PIPES); - for_each_intel_crtc(display->drm, it__) { + for_each_intel_crtc(display, it__) { __entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__); __entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__); } @@ -114,7 +114,7 @@ TRACE_EVENT(intel_pipe_disable, sizeof(__entry->frame[0]) * I915_MAX_PIPES); memset(__entry->scanline, 0, sizeof(__entry->scanline[0]) * I915_MAX_PIPES); - for_each_intel_crtc(display->drm, it__) { + for_each_intel_crtc(display, it__) { __entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__); __entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__); } @@ -244,7 +244,7 @@ TRACE_EVENT(intel_memory_cxsr, sizeof(__entry->frame[0]) * I915_MAX_PIPES); memset(__entry->scanline, 0, sizeof(__entry->scanline[0]) * I915_MAX_PIPES); - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { __entry->frame[crtc->pipe] = intel_crtc_get_vblank_counter(crtc); __entry->scanline[crtc->pipe] = intel_get_crtc_scanline(crtc); } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index b8ccd635c5751..c21e0c0ef0b12 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1035,6 +1035,7 @@ struct intel_crtc_state { /* logical state of LUTs */ struct drm_property_blob *degamma_lut, *gamma_lut, *ctm; struct drm_display_mode mode, pipe_mode, adjusted_mode; + u32 background_color; enum drm_scaling_filter scaling_filter; u8 sharpness_strength; } hw; @@ -1822,6 +1823,7 @@ struct intel_dp { /* intersection of source and sink rates */ int num_common_rates; int common_rates[DP_MAX_SUPPORTED_RATES]; + int max_common_lane_count; struct { /* TODO: move the rest of link specific fields to here */ bool active; @@ -1874,6 +1876,7 @@ struct intel_dp { /* connector directly attached - won't be use for modeset in mst world */ struct intel_connector *attached_connector; bool as_sdp_supported; + bool as_sdp_v2_supported; struct drm_dp_tunnel *tunnel; bool tunnel_suspended:1; diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.c b/drivers/gpu/drm/i915/display/intel_display_wa.c index 7d3d63a59882b..2094eda09c912 100644 --- a/drivers/gpu/drm/i915/display/intel_display_wa.c +++ b/drivers/gpu/drm/i915/display/intel_display_wa.c @@ -136,6 +136,8 @@ bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa, return DISPLAY_VER(display) == 20 && IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0); + case INTEL_DISPLAY_WA_16029024088: + return DISPLAY_VER(display) >= 35; case INTEL_DISPLAY_WA_18034343758: return DISPLAY_VER(display) == 20 || (display->platform.pantherlake && diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.h b/drivers/gpu/drm/i915/display/intel_display_wa.h index 15fec843f15e1..9cdd148ea4fad 100644 --- a/drivers/gpu/drm/i915/display/intel_display_wa.h +++ b/drivers/gpu/drm/i915/display/intel_display_wa.h @@ -52,6 +52,7 @@ enum intel_display_wa { INTEL_DISPLAY_WA_16023588340, INTEL_DISPLAY_WA_16025573575, INTEL_DISPLAY_WA_16025596647, + INTEL_DISPLAY_WA_16029024088, INTEL_DISPLAY_WA_18034343758, INTEL_DISPLAY_WA_22010178259, INTEL_DISPLAY_WA_22010947358, diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index 605a4a5556018..b007343721e12 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -39,6 +39,13 @@ * current implementation, we only need one wakelock, so only * DMC_WAKELOCK1_CTL is used. The other definitions are here for * potential future use. + * + * This is available starting with Xe2_LPD (display version 20) as an + * experimental feature and on Xe3_LPD (display version 30) as the + * first display release with official support. That means that we + * only enable the feature by default on the latter and using it on + * the former requires explicitly using the enable_dmc_wl module + * parameter. */ /* @@ -286,7 +293,7 @@ static void intel_dmc_wl_sanitize_param(struct intel_display *display) { const char *desc; - if (!HAS_DMC_WAKELOCK(display)) { + if (DISPLAY_VER(display) < 20) { display->params.enable_dmc_wl = ENABLE_DMC_WL_DISABLED; } else if (display->params.enable_dmc_wl < 0) { if (DISPLAY_VER(display) >= 30) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f01a6eed38395..0ce0c09835f6d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -362,19 +362,30 @@ int intel_dp_max_source_lane_count(struct intel_digital_port *dig_port) return max_lanes; } -/* Theoretical max between source and sink */ -int intel_dp_max_common_lane_count(struct intel_dp *intel_dp) +/* + * Theoretical max between source and sink. + * Return %true if the max common lane count changed. + */ +static bool intel_dp_set_max_common_lane_count(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); int source_max = intel_dp_max_source_lane_count(dig_port); int sink_max = intel_dp->max_sink_lane_count; int lane_max = intel_tc_port_max_lane_count(dig_port); int lttpr_max = drm_dp_lttpr_max_lane_count(intel_dp->lttpr_common_caps); + int old_max_common_lane_count = intel_dp->max_common_lane_count; if (lttpr_max) sink_max = min(sink_max, lttpr_max); - return min3(source_max, sink_max, lane_max); + intel_dp->max_common_lane_count = min3(source_max, sink_max, lane_max); + + return intel_dp->max_common_lane_count != old_max_common_lane_count; +} + +int intel_dp_max_common_lane_count(struct intel_dp *intel_dp) +{ + return intel_dp->max_common_lane_count; } static int forced_lane_count(struct intel_dp *intel_dp) @@ -787,13 +798,22 @@ int intel_dp_link_config_index(struct intel_dp *intel_dp, int link_rate, int lan return -1; } -static void intel_dp_set_common_rates(struct intel_dp *intel_dp) +/* Return %true if the common rates changed. */ +static bool intel_dp_set_common_rates(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); + int num_old_common_rates = intel_dp->num_common_rates; + int old_common_rates[DP_MAX_SUPPORTED_RATES]; drm_WARN_ON(display->drm, !intel_dp->num_source_rates || !intel_dp->num_sink_rates); + /* TODO: Add a struct containing both rates and number of rates. */ + static_assert(__same_type(old_common_rates[0], intel_dp->common_rates[0]) && + sizeof(old_common_rates) == sizeof(intel_dp->common_rates)); + memcpy(old_common_rates, intel_dp->common_rates, + num_old_common_rates * sizeof(old_common_rates[0])); + intel_dp->num_common_rates = intersect_rates(intel_dp->source_rates, intel_dp->num_source_rates, intel_dp->sink_rates, @@ -806,7 +826,25 @@ static void intel_dp_set_common_rates(struct intel_dp *intel_dp) intel_dp->num_common_rates = 1; } + return num_old_common_rates != intel_dp->num_common_rates || + memcmp(old_common_rates, intel_dp->common_rates, + num_old_common_rates * sizeof(old_common_rates[0])); +} + +/* Return %true if any common link param changed. */ +static bool intel_dp_set_common_link_params(struct intel_dp *intel_dp) +{ + bool params_changed = false; + + if (intel_dp_set_common_rates(intel_dp)) + params_changed = true; + + if (intel_dp_set_max_common_lane_count(intel_dp)) + params_changed = true; + intel_dp_link_config_init(intel_dp); + + return params_changed; } bool intel_dp_link_params_valid(struct intel_dp *intel_dp, int link_rate, @@ -3172,16 +3210,20 @@ static void intel_dp_compute_vsc_colorimetry(const struct intel_crtc_state *crtc static bool intel_dp_needs_as_sdp(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state) { - if (!intel_dp->as_sdp_supported) + if (!intel_dp->as_sdp_v2_supported) return false; /* - * #TODO Implement AS SDP for DP branch device. + * #TODO: Add AS SDP v1 support for PCONs (DP branch devices). */ if (drm_dp_is_branch(intel_dp->dpcd)) return false; - return crtc_state->vrr.enable; + if (intel_psr_needs_alpm_aux_less(intel_dp, crtc_state) && + !intel_psr_pr_async_video_timing_supported(intel_dp)) + return true; + + return intel_vrr_possible(crtc_state); } static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, @@ -3204,16 +3246,34 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC; as_sdp->length = 0x9; as_sdp->duration_incr_ms = 0; + as_sdp->revision = 0x2; as_sdp->vtotal = intel_vrr_vmin_vtotal(crtc_state); if (crtc_state->cmrr.enable) { as_sdp->mode = DP_AS_SDP_FAVT_TRR_REACHED; as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode); as_sdp->target_rr_divider = true; - } else { + } else if (crtc_state->vrr.enable) { as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL; - as_sdp->target_rr = 0; + } else { + as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL; } + + /* + * For Panel Replay with Async Video Timing support, the source can + * disable sending the AS SDP during PR Active state. In that case, + * the sink needs the coasting vtotal value to maintain the refresh + * rate. The HW only samples this on PR_ALPM_CTL[AS SDP Transmission + * in Active Disable], which we never program, so providing the value + * unconditionally when the sink advertises the capability is safe. + * + * #TODO: + * If we ever advertise support for coasting at other refresh targets, + * this logic could be revisited. For now, use the minimum refresh rate + * as the only safe coasting value. + */ + if (intel_psr_pr_async_video_timing_supported(intel_dp)) + as_sdp->coasting_vtotal = crtc_state->vrr.vmax; } static void intel_dp_compute_vsc_sdp(struct intel_dp *intel_dp, @@ -3688,8 +3748,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, pipe_config->dp_m_n.data_m *= pipe_config->splitter.link_count; intel_vrr_compute_config(pipe_config, conn_state); - intel_dp_compute_as_sdp(intel_dp, pipe_config); intel_psr_compute_config(intel_dp, pipe_config, conn_state); + intel_dp_compute_as_sdp(intel_dp, pipe_config); intel_alpm_lobf_compute_config(intel_dp, pipe_config, conn_state); intel_dp_drrs_compute_config(connector, pipe_config, link_bpp_x16); intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state); @@ -4874,9 +4934,21 @@ intel_dp_has_sink_count(struct intel_dp *intel_dp) void intel_dp_update_sink_caps(struct intel_dp *intel_dp) { + struct intel_display *display = to_intel_display(intel_dp); + intel_dp_set_sink_rates(intel_dp); intel_dp_set_max_sink_lane_count(intel_dp); - intel_dp_set_common_rates(intel_dp); + /* + * Handle unexpected sink cap changes, or a race between setting + * the deferred link params flag in the HPD IRQ handler and + * clearing the flag during connector detect. + */ + if (intel_dp_set_common_link_params(intel_dp) && + !intel_dp->reset_link_params) { + drm_dbg_kms(display->drm, + "DPRX capabilities changed before long HPD or RX_CAP_CHANGED signal\n"); + intel_dp->reset_link_params = true; + } } static bool @@ -5180,7 +5252,7 @@ static ssize_t intel_dp_as_sdp_pack(const struct drm_dp_as_sdp *as_sdp, /* Prepare AS (Adaptive Sync) SDP Header */ sdp->sdp_header.HB0 = 0; sdp->sdp_header.HB1 = as_sdp->sdp_type; - sdp->sdp_header.HB2 = 0x02; + sdp->sdp_header.HB2 = as_sdp->revision; sdp->sdp_header.HB3 = as_sdp->length; /* Fill AS (Adaptive Sync) SDP Payload */ @@ -5193,6 +5265,9 @@ static ssize_t intel_dp_as_sdp_pack(const struct drm_dp_as_sdp *as_sdp, if (as_sdp->target_rr_divider) sdp->db[4] |= 0x20; + sdp->db[7] = as_sdp->coasting_vtotal & 0xFF; + sdp->db[8] = (as_sdp->coasting_vtotal >> 8) & 0xFF; + return length; } @@ -5367,17 +5442,17 @@ int intel_dp_as_sdp_unpack(struct drm_dp_as_sdp *as_sdp, if (sdp->sdp_header.HB1 != DP_SDP_ADAPTIVE_SYNC) return -EINVAL; - if (sdp->sdp_header.HB2 != 0x02) - return -EINVAL; - if ((sdp->sdp_header.HB3 & 0x3F) != 9) return -EINVAL; + as_sdp->sdp_type = sdp->sdp_header.HB1; as_sdp->length = sdp->sdp_header.HB3 & DP_AS_SDP_LENGTH_MASK; + as_sdp->revision = sdp->sdp_header.HB2; as_sdp->mode = sdp->db[0] & DP_AS_SDP_OPERATION_MODE_MASK; as_sdp->vtotal = (sdp->db[2] << 8) | sdp->db[1]; as_sdp->target_rr = ((sdp->db[4] & 0x3) << 8) | sdp->db[3]; as_sdp->target_rr_divider = sdp->db[4] & 0x20 ? true : false; + as_sdp->coasting_vtotal = (sdp->db[8] << 8) | sdp->db[7]; return 0; } @@ -6000,8 +6075,10 @@ static bool intel_dp_handle_link_service_irq(struct intel_dp *intel_dp, u8 irq_m drm_WARN_ON(display->drm, irq_mask & ~(INTEL_DP_LINK_SERVICE_IRQ_MASK_SST | INTEL_DP_LINK_SERVICE_IRQ_MASK_MST)); - if (irq_mask & RX_CAP_CHANGED) + if (irq_mask & RX_CAP_CHANGED) { + intel_dp->reset_link_params = true; reprobe_needed = true; + } if (irq_mask & LINK_STATUS_CHANGED) intel_dp_check_link_state(intel_dp); @@ -6365,6 +6442,46 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) false); } +static bool +intel_dp_sink_supports_as_sdp_v2(struct intel_dp *intel_dp) +{ + u8 rx_features; + + /* + * The DP spec does not explicitly provide the AS SDP v2 capability. + * So based on the DP v2.1 SCR, we infer it from the following bits: + * + * DP_AS_SDP_FAVT_PAYLOAD_FIELDS_PARSING_SUPPORTED indicates support for + * FAVT, which is explicitly defined to use AS SDP v2. + * + * DP_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR indicates that the sink + * does not support asynchronous video timing while in PR Active, + * requiring the source to keep transmitting Adaptive-Sync SDPs. The + * spec mandates that such sinks shall support AS SDP v2. + * + * #TODO: Check the Adaptive-Sync DisplayID 2.1 block once DisplayID + * parsing is available. This may help detect AS SDP v2 support for + * native DP 2.1 sinks that do not expose FAVT or PR-based capability + * bits. + * + * In the presence of PCONs, check PCON support from DPCD and sink + * support from Display ID. + */ + + if (drm_dp_dpcd_read_byte(&intel_dp->aux, + DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1, + &rx_features) == 1) { + if (rx_features & DP_AS_SDP_FAVT_PAYLOAD_FIELDS_PARSING_SUPPORTED) + return true; + } + + if (intel_dp->psr.sink_panel_replay_support && + !intel_psr_pr_async_video_timing_supported(intel_dp)) + return true; + + return false; +} + static void intel_dp_detect_sdp_caps(struct intel_dp *intel_dp) { @@ -6372,6 +6489,15 @@ intel_dp_detect_sdp_caps(struct intel_dp *intel_dp) intel_dp->as_sdp_supported = HAS_AS_SDP(display) && drm_dp_as_sdp_supported(&intel_dp->aux, intel_dp->dpcd); + + if (!intel_dp->as_sdp_supported) + return; + + /* eDP Adaptive-Sync SDP always uses AS SDP v2 */ + if (intel_dp_is_edp(intel_dp)) + intel_dp->as_sdp_v2_supported = true; + else + intel_dp->as_sdp_v2_supported = intel_dp_sink_supports_as_sdp_v2(intel_dp); } static bool intel_dp_needs_dpcd_probe(struct intel_dp *intel_dp, bool force_on_external) @@ -6751,7 +6877,7 @@ static int intel_modeset_affected_transcoders(struct intel_atomic_state *state, if (transcoders == 0) return 0; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state; int ret; @@ -7316,7 +7442,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, } intel_dp_set_source_rates(intel_dp); - intel_dp_set_common_rates(intel_dp); + intel_dp_set_common_link_params(intel_dp); intel_dp_reset_link_params(intel_dp); /* init MST on ports that can support it */ @@ -7465,7 +7591,6 @@ int intel_dp_get_lines_for_sdp(const struct intel_crtc_state *crtc_state, u32 ty int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state, bool assume_all_enabled) { - struct intel_display *display = to_intel_display(crtc_state); int sdp_guardband = 0; if (assume_all_enabled || @@ -7480,8 +7605,8 @@ int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state, sdp_guardband = max(sdp_guardband, intel_dp_get_lines_for_sdp(crtc_state, DP_SDP_PPS)); - if ((assume_all_enabled && HAS_AS_SDP(display)) || - crtc_state->infoframes.enable & intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC)) + if (crtc_state->infoframes.enable & + intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC)) sdp_guardband = max(sdp_guardband, intel_dp_get_lines_for_sdp(crtc_state, DP_SDP_ADAPTIVE_SYNC)); @@ -7506,3 +7631,14 @@ bool intel_dp_joiner_candidate_valid(struct intel_connector *connector, return true; } + +u8 intel_dp_as_sdp_transmission_time(void) +{ + /* + * DP allows AS SDP position to move during PR active in some cases, but + * software-controlled refresh rate changes with DC6v / ALPM require the + * AS SDP to remain at T1. Use T1 unconditionally for now. + */ + + return DP_PR_AS_SDP_SETUP_TIME_T1; +} diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index f41480d247142..46a7f5c70981f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -241,4 +241,6 @@ bool intel_dp_joiner_candidate_valid(struct intel_connector *connector, for ((__num_joined_pipes) = 1; (__num_joined_pipes) <= (I915_MAX_PIPES); (__num_joined_pipes)++) \ for_each_if(intel_dp_joiner_candidate_valid(__connector, (__mode)->hdisplay, __num_joined_pipes)) +u8 intel_dp_as_sdp_transmission_time(void); + #endif /* __INTEL_DP_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index a8d56ebf06a2f..7a6c07f6aaeb4 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -691,10 +691,9 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) struct intel_dp *intel_dp = intel_attached_dp(connector); struct drm_device *dev = connector->base.dev; struct intel_panel *panel = &connector->panel; - bool try_intel_interface = false; + bool try_intel_interface = false, try_vesa_interface = false; - /* - * Check the VBT and user's module parameters to figure out which + /* Check the VBT and user's module parameters to figure out which * interfaces to probe */ switch (display->params.enable_dpcd_backlight) { @@ -703,6 +702,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) case INTEL_DP_AUX_BACKLIGHT_AUTO: switch (panel->vbt.backlight.type) { case INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE: + try_vesa_interface = true; break; case INTEL_BACKLIGHT_DISPLAY_DDI: try_intel_interface = true; @@ -715,12 +715,20 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) if (panel->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE) try_intel_interface = true; + try_vesa_interface = true; + break; + case INTEL_DP_AUX_BACKLIGHT_FORCE_VESA: + try_vesa_interface = true; break; case INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL: try_intel_interface = true; break; } + /* For eDP 1.5 and above we are supposed to use VESA interface for brightness control */ + if (intel_dp->edp_dpcd[0] >= DP_EDP_15) + try_vesa_interface = true; + /* * Since Intel has their own backlight control interface, the majority of machines out there * using DPCD backlight controls with Intel GPUs will be using this interface as opposed to @@ -733,9 +741,6 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) * panel with Intel's OUI - which is also required for us to be able to detect Intel's * backlight interface at all. This means that the only sensible way for us to detect both * interfaces is to probe for Intel's first, and VESA's second. - * - * Also there is a chance some VBTs may advertise false Intel backlight support even if the - * TCON DPCD says otherwise. This means we keep VESA interface as fallback in that case. */ if (try_intel_interface && intel_dp->edp_dpcd[0] <= DP_EDP_14b && intel_dp_aux_supports_hdr_backlight(connector)) { @@ -745,7 +750,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) return 0; } - if (intel_dp_aux_supports_vesa_backlight(connector)) { + if (try_vesa_interface && intel_dp_aux_supports_vesa_backlight(connector)) { drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Using VESA eDP backlight controls\n", connector->base.base.id, connector->base.name); panel->backlight.funcs = &intel_dp_vesa_bl_funcs; diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index a26094223f780..e566f2b49594a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -34,8 +34,10 @@ #include "intel_dp.h" #include "intel_dp_link_training.h" #include "intel_encoder.h" +#include "intel_hdmi.h" #include "intel_hotplug.h" #include "intel_panel.h" +#include "intel_psr.h" #define LT_MSG_PREFIX "[CONNECTOR:%d:%s][ENCODER:%d:%s][%s] " #define LT_MSG_ARGS(_intel_dp, _dp_phy) (_intel_dp)->attached_connector->base.base.id, \ @@ -710,16 +712,28 @@ static bool intel_dp_link_max_vswing_reached(struct intel_dp *intel_dp, return true; } -void intel_dp_link_training_set_mode(struct intel_dp *intel_dp, int link_rate, bool is_vrr) +void intel_dp_link_training_set_mode(struct intel_dp *intel_dp, int link_rate, + bool is_vrr, + bool pr_with_as_sdp_enable) { u8 link_config[2]; link_config[0] = is_vrr ? DP_MSA_TIMING_PAR_IGNORE_EN : 0; + link_config[0] |= pr_with_as_sdp_enable ? DP_FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE : 0; link_config[1] = drm_dp_is_uhbr_rate(link_rate) ? DP_SET_ANSI_128B132B : DP_SET_ANSI_8B10B; drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2); } +static bool +intel_dp_pr_with_as_sdp_enabled(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + return intel_psr_needs_alpm_aux_less(intel_dp, crtc_state) && + (crtc_state->infoframes.enable & + intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC)); +} + static void intel_dp_update_downspread_ctrl(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { @@ -737,7 +751,9 @@ static void intel_dp_update_downspread_ctrl(struct intel_dp *intel_dp, * especially on the first real commit when clearing the inherited flag. */ intel_dp_link_training_set_mode(intel_dp, - crtc_state->port_clock, crtc_state->vrr.in_range); + crtc_state->port_clock, + crtc_state->vrr.in_range, + intel_dp_pr_with_as_sdp_enabled(intel_dp, crtc_state)); } void intel_dp_link_training_set_bw(struct intel_dp *intel_dp, diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.h b/drivers/gpu/drm/i915/display/intel_dp_link_training.h index 33dcbde6a4089..18c34c1a472fa 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h @@ -18,7 +18,8 @@ int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp); bool intel_dp_lttpr_transparent_mode_enabled(struct intel_dp *intel_dp); void intel_dp_link_training_set_mode(struct intel_dp *intel_dp, - int link_rate, bool is_vrr); + int link_rate, bool is_vrr, + bool pr_with_as_sdp_enable); void intel_dp_link_training_set_bw(struct intel_dp *intel_dp, int link_bw, int rate_select, int lane_count, bool enhanced_framing, bool post_lt_adj_req); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 8f73e01db17c9..bcdc504913471 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -837,7 +837,7 @@ static int intel_dp_mst_check_dsc_change(struct intel_atomic_state *state, mst_pipe_mask = get_pipes_downstream_of_mst_port(state, mst_mgr, NULL); - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, mst_pipe_mask) { + for_each_intel_crtc_in_pipe_mask(display, crtc, mst_pipe_mask) { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -1065,14 +1065,13 @@ static void mst_stream_post_disable(struct intel_atomic_state *state, drm_atomic_get_mst_payload_state(new_mst_state, connector->mst.port); struct intel_crtc *pipe_crtc; bool last_mst_stream; - int i; last_mst_stream = intel_dp_mst_dec_active_streams(intel_dp); drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 12 && last_mst_stream && !intel_dp_mst_is_master_trans(old_crtc_state)); - for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) { + for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state) { const struct intel_crtc_state *old_pipe_crtc_state = intel_atomic_get_old_crtc_state(state, pipe_crtc); @@ -1099,7 +1098,7 @@ static void mst_stream_post_disable(struct intel_atomic_state *state, intel_ddi_disable_transcoder_func(old_crtc_state); - for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) { + for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state) { const struct intel_crtc_state *old_pipe_crtc_state = intel_atomic_get_old_crtc_state(state, pipe_crtc); @@ -1310,7 +1309,7 @@ static void mst_stream_enable(struct intel_atomic_state *state, enum transcoder trans = pipe_config->cpu_transcoder; bool first_mst_stream = intel_dp_mst_active_streams(intel_dp) == 1; struct intel_crtc *pipe_crtc; - int ret, i; + int ret; drm_WARN_ON(display->drm, pipe_config->has_pch_encoder); @@ -1355,7 +1354,7 @@ static void mst_stream_enable(struct intel_atomic_state *state, intel_enable_transcoder(pipe_config); - for_each_pipe_crtc_modeset_enable(display, pipe_crtc, pipe_config, i) { + for_each_pipe_crtc_modeset_enable(display, pipe_crtc, pipe_config) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); @@ -2145,7 +2144,7 @@ void intel_dp_mst_prepare_probe(struct intel_dp *intel_dp) intel_dp_compute_rate(intel_dp, link_rate, &link_bw, &rate_select); - intel_dp_link_training_set_mode(intel_dp, link_rate, false); + intel_dp_link_training_set_mode(intel_dp, link_rate, false, false); intel_dp_link_training_set_bw(intel_dp, link_bw, rate_select, lane_count, drm_dp_enhanced_frame_cap(intel_dp->dpcd), false); diff --git a/drivers/gpu/drm/i915/display/intel_dp_test.c b/drivers/gpu/drm/i915/display/intel_dp_test.c index 5cfa1dd411dab..ba44769c9cfbe 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_test.c +++ b/drivers/gpu/drm/i915/display/intel_dp_test.c @@ -471,7 +471,7 @@ static int intel_dp_do_phy_test(struct intel_encoder *encoder, drm_dbg_kms(display->drm, "[ENCODER:%d:%s] PHY test\n", encoder->base.base.id, encoder->base.name); - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) { + for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) { const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); diff --git a/drivers/gpu/drm/i915/display/intel_dp_tunnel.c b/drivers/gpu/drm/i915/display/intel_dp_tunnel.c index 11712a151f729..d6bd1f7e01e18 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_tunnel.c +++ b/drivers/gpu/drm/i915/display/intel_dp_tunnel.c @@ -146,7 +146,7 @@ static int allocate_initial_tunnel_bw_for_pipes(struct intel_dp *intel_dp, u8 pi int tunnel_bw = 0; int err; - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) { + for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) { const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); int stream_bw = intel_dp_config_required_rate(crtc_state); @@ -740,9 +740,8 @@ static void atomic_decrease_bw(struct intel_atomic_state *state) struct intel_crtc *crtc; const struct intel_crtc_state *old_crtc_state; const struct intel_crtc_state *new_crtc_state; - int i; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { const struct drm_dp_tunnel_state *new_tunnel_state; struct drm_dp_tunnel *tunnel; int old_bw; @@ -795,9 +794,8 @@ static void atomic_increase_bw(struct intel_atomic_state *state) { struct intel_crtc *crtc; const struct intel_crtc_state *crtc_state; - int i; - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { struct drm_dp_tunnel_state *tunnel_state; struct drm_dp_tunnel *tunnel = crtc_state->dp_tunnel_ref.tunnel; int bw; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index bb487e647f767..0f933101b7dd1 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4965,7 +4965,7 @@ static void readout_dpll_hw_state(struct intel_display *display, pll->wakeref = intel_display_power_get(display, pll->info->power_domain); pll->state.pipe_mask = 0; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 0fdb32ef241cd..6c95d4ae1ea90 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -137,7 +137,7 @@ static unsigned int intel_drrs_frontbuffer_bits(const struct intel_crtc_state *c frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, + for_each_intel_crtc_in_pipe_mask(display, crtc, crtc_state->joiner_pipes) frontbuffer_bits |= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); @@ -227,7 +227,7 @@ static void intel_drrs_frontbuffer_update(struct intel_display *display, { struct intel_crtc *crtc; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { unsigned int frontbuffer_bits; mutex_lock(&crtc->drrs.mutex); diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index df1d3d9dc3e5b..c8d4e3a5ce6b1 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -380,7 +380,7 @@ static bool intel_fbdev_init_bios(struct intel_display *display, unsigned int max_size = 0; /* Find the largest fb */ - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); struct intel_plane *plane = @@ -419,7 +419,7 @@ static bool intel_fbdev_init_bios(struct intel_display *display, } /* Now make sure all the pipes will fit into it */ - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); struct intel_plane *plane = @@ -489,7 +489,7 @@ static bool intel_fbdev_init_bios(struct intel_display *display, drm_framebuffer_get(&ifbdev->fb->base); /* Final pass to check if any active pipes don't have fbs */ - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); struct intel_plane *plane = diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index f8876aa23c9ff..c170d3104e4cb 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -368,9 +368,8 @@ int intel_fdi_atomic_check_link(struct intel_atomic_state *state, { struct intel_crtc *crtc; struct intel_crtc_state *crtc_state; - int i; - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { int ret; if (!crtc_state->has_pch_encoder || diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c index 02013e89d8f2e..eca016d725d25 100644 --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c @@ -527,7 +527,7 @@ void intel_check_cpu_fifo_underruns(struct intel_display *display) spin_lock_irq(&display->irq.lock); - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { if (crtc->cpu_fifo_underrun_disabled) continue; @@ -554,7 +554,7 @@ void intel_check_pch_fifo_underruns(struct intel_display *display) spin_lock_irq(&display->irq.lock); - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { if (crtc->pch_fifo_underrun_disabled) continue; diff --git a/drivers/gpu/drm/i915/display/intel_flipq.c b/drivers/gpu/drm/i915/display/intel_flipq.c index 333d28faf4caa..bf278f60bba78 100644 --- a/drivers/gpu/drm/i915/display/intel_flipq.c +++ b/drivers/gpu/drm/i915/display/intel_flipq.c @@ -132,7 +132,7 @@ void intel_flipq_init(struct intel_display *display) intel_dmc_wait_fw_load(display); - for_each_intel_crtc(display->drm, crtc) + for_each_intel_crtc(display, crtc) intel_flipq_crtc_init(crtc); } diff --git a/drivers/gpu/drm/i915/display/intel_global_state.c b/drivers/gpu/drm/i915/display/intel_global_state.c index 9e1369c834e49..886caf29c9ae8 100644 --- a/drivers/gpu/drm/i915/display/intel_global_state.c +++ b/drivers/gpu/drm/i915/display/intel_global_state.c @@ -140,7 +140,7 @@ static void assert_global_state_write_locked(struct intel_display *display) { struct intel_crtc *crtc; - for_each_intel_crtc(display->drm, crtc) + for_each_intel_crtc(display, crtc) drm_modeset_lock_assert_held(&crtc->base.mutex); } @@ -163,7 +163,7 @@ static void assert_global_state_read_locked(struct intel_atomic_state *state) struct drm_modeset_acquire_ctx *ctx = state->base.acquire_ctx; struct intel_crtc *crtc; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { if (modeset_lock_is_held(ctx, &crtc->base.mutex)) return; } @@ -301,7 +301,7 @@ int intel_atomic_lock_global_state(struct intel_global_state *obj_state) struct intel_display *display = to_intel_display(state); struct intel_crtc *crtc; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { int ret; ret = drm_modeset_lock(&crtc->base.mutex, @@ -334,7 +334,7 @@ intel_atomic_global_state_is_serialized(struct intel_atomic_state *state) struct intel_display *display = to_intel_display(state); struct intel_crtc *crtc; - for_each_intel_crtc(display->drm, crtc) + for_each_intel_crtc(display, crtc) if (!intel_atomic_get_new_crtc_state(state, crtc)) return false; return true; diff --git a/drivers/gpu/drm/i915/display/intel_initial_plane.c b/drivers/gpu/drm/i915/display/intel_initial_plane.c index 034fe199c2a15..6aa253678ec94 100644 --- a/drivers/gpu/drm/i915/display/intel_initial_plane.c +++ b/drivers/gpu/drm/i915/display/intel_initial_plane.c @@ -50,7 +50,7 @@ intel_reuse_initial_plane_obj(struct intel_crtc *this, struct intel_display *display = to_intel_display(this); struct intel_crtc *crtc; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_plane *plane = to_intel_plane(crtc->base.primary); const struct intel_plane_state *plane_state = @@ -208,7 +208,7 @@ void intel_initial_plane_config(struct intel_display *display) struct intel_initial_plane_configs all_plane_configs = {}; struct intel_crtc *crtc; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); struct intel_initial_plane_config *plane_config = diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c index d2862de894fa7..b47474a3e9fec 100644 --- a/drivers/gpu/drm/i915/display/intel_link_bw.c +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c @@ -108,7 +108,7 @@ static int __intel_link_bw_reduce_bpp(struct intel_atomic_state *state, struct intel_crtc *crtc; int max_bpp_x16 = 0; - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) { + for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) { struct intel_crtc_state *crtc_state; int link_bpp_x16; diff --git a/drivers/gpu/drm/i915/display/intel_load_detect.c b/drivers/gpu/drm/i915/display/intel_load_detect.c index 2f767b15a7f9b..3fef1ebc63570 100644 --- a/drivers/gpu/drm/i915/display/intel_load_detect.c +++ b/drivers/gpu/drm/i915/display/intel_load_detect.c @@ -89,7 +89,7 @@ intel_load_detect_get_pipe(struct drm_connector *connector, } /* Find an unused one (if possible) */ - for_each_intel_crtc(display->drm, possible_crtc) { + for_each_intel_crtc(display, possible_crtc) { if (!(encoder->base.possible_crtcs & drm_crtc_mask(&possible_crtc->base))) continue; diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index e88082c8caace..e8730b5baf2a4 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -71,7 +71,7 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc, to_intel_atomic_state(state)->internal = true; /* Everything's already locked, -EDEADLK can't happen. */ - for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, + for_each_intel_crtc_in_pipe_mask(display, temp_crtc, BIT(pipe) | intel_crtc_joiner_secondary_pipes(crtc_state)) { struct intel_crtc_state *temp_crtc_state = @@ -192,7 +192,7 @@ static u8 get_transcoder_pipes(struct intel_display *display, struct intel_crtc *temp_crtc; u8 pipes = 0; - for_each_intel_crtc(display->drm, temp_crtc) { + for_each_intel_crtc(display, temp_crtc) { struct intel_crtc_state *temp_crtc_state = to_intel_crtc_state(temp_crtc->base.state); @@ -248,7 +248,7 @@ static u8 get_joiner_secondary_pipes(struct intel_display *display, u8 primary_p struct intel_crtc *primary_crtc; u8 pipes = 0; - for_each_intel_crtc_in_pipe_mask(display->drm, primary_crtc, primary_pipes_mask) { + for_each_intel_crtc_in_pipe_mask(display, primary_crtc, primary_pipes_mask) { struct intel_crtc_state *primary_crtc_state = to_intel_crtc_state(primary_crtc->base.state); @@ -278,16 +278,16 @@ static void intel_crtc_disable_noatomic(struct intel_crtc *crtc, portsync_master_mask & joiner_secondaries_mask || portsync_slaves_mask & joiner_secondaries_mask); - for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, joiner_secondaries_mask) + for_each_intel_crtc_in_pipe_mask(display, temp_crtc, joiner_secondaries_mask) intel_crtc_disable_noatomic_begin(temp_crtc, ctx); - for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, portsync_slaves_mask) + for_each_intel_crtc_in_pipe_mask(display, temp_crtc, portsync_slaves_mask) intel_crtc_disable_noatomic_begin(temp_crtc, ctx); - for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, portsync_master_mask) + for_each_intel_crtc_in_pipe_mask(display, temp_crtc, portsync_master_mask) intel_crtc_disable_noatomic_begin(temp_crtc, ctx); - for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, + for_each_intel_crtc_in_pipe_mask(display, temp_crtc, joiner_secondaries_mask | portsync_slaves_mask | portsync_master_mask) @@ -334,6 +334,8 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode; crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter; crtc_state->uapi.sharpness_strength = crtc_state->hw.sharpness_strength; + crtc_state->uapi.background_color = + intel_color_background_color_hw_to_drm(crtc_state->hw.background_color); if (DISPLAY_INFO(display)->color.degamma_lut_size) { /* assume 1:1 mapping */ @@ -376,7 +378,7 @@ intel_sanitize_plane_mapping(struct intel_display *display) if (DISPLAY_VER(display) >= 4) return; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_plane *plane = to_intel_plane(crtc->base.primary); struct intel_crtc *plane_crtc; @@ -532,7 +534,7 @@ static void intel_sanitize_all_crtcs(struct intel_display *display, for (;;) { u32 old_mask = crtcs_forced_off; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { u32 crtc_mask = drm_crtc_mask(&crtc->base); if (crtcs_forced_off & crtc_mask) @@ -545,7 +547,7 @@ static void intel_sanitize_all_crtcs(struct intel_display *display, break; } - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); @@ -681,7 +683,7 @@ static void readout_plane_state(struct intel_display *display) str_enabled_disabled(visible), pipe_name(pipe)); } - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); @@ -699,7 +701,7 @@ static void intel_modeset_readout_hw_state(struct intel_display *display) struct intel_connector *connector; struct drm_connector_list_iter conn_iter; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); @@ -741,7 +743,7 @@ static void intel_modeset_readout_hw_state(struct intel_display *display) /* encoder should read be linked to joiner primary */ WARN_ON(intel_crtc_is_joiner_secondary(crtc_state)); - for_each_intel_crtc_in_pipe_mask(display->drm, secondary_crtc, + for_each_intel_crtc_in_pipe_mask(display, secondary_crtc, intel_crtc_joiner_secondary_pipes(crtc_state)) { struct intel_crtc_state *secondary_crtc_state; @@ -814,7 +816,7 @@ static void intel_modeset_readout_hw_state(struct intel_display *display) } drm_connector_list_iter_end(&conn_iter); - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); struct intel_plane *plane; @@ -961,7 +963,7 @@ void intel_modeset_setup_hw_state(struct intel_display *display, * intel_sanitize_plane_mapping() may need to do vblank * waits, so we need vblank interrupts restored beforehand. */ - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); @@ -997,7 +999,7 @@ void intel_modeset_setup_hw_state(struct intel_display *display, intel_wm_get_hw_state(display); intel_wm_sanitize(display); - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); struct intel_power_domain_mask put_domains; @@ -1009,5 +1011,5 @@ void intel_modeset_setup_hw_state(struct intel_display *display, intel_display_power_put(display, POWER_DOMAIN_INIT, wakeref); - intel_power_domains_sanitize_state(display); + intel_display_power_sanitize_state(display); } diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c index a1f9558d53af2..2a52b36c646c7 100644 --- a/drivers/gpu/drm/i915/display/intel_plane.c +++ b/drivers/gpu/drm/i915/display/intel_plane.c @@ -1794,6 +1794,7 @@ static u8 intel_joiner_affected_planes(struct intel_atomic_state *state, static int intel_joiner_add_affected_planes(struct intel_atomic_state *state, u8 joined_pipes) { + struct intel_display *display = to_intel_display(state); u8 prev_affected_planes, affected_planes = 0; /* @@ -1811,7 +1812,7 @@ static int intel_joiner_add_affected_planes(struct intel_atomic_state *state, do { struct intel_crtc *crtc; - for_each_intel_crtc_in_pipe_mask(state->base.dev, crtc, joined_pipes) { + for_each_intel_crtc_in_pipe_mask(display, crtc, joined_pipes) { int ret; ret = intel_crtc_add_planes_to_state(state, crtc, affected_planes); @@ -1830,9 +1831,8 @@ static int intel_add_affected_planes(struct intel_atomic_state *state) { const struct intel_crtc_state *crtc_state; struct intel_crtc *crtc; - int i; - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { int ret; ret = intel_joiner_add_affected_planes(state, intel_crtc_joined_pipe_mask(crtc_state)); @@ -1866,8 +1866,7 @@ int intel_plane_atomic_check(struct intel_atomic_state *state) } } - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { u8 old_active_planes, new_active_planes; ret = icl_check_nv12_planes(state, crtc); diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c index 7819b724795bb..6d32c52269a66 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.c +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c @@ -190,7 +190,7 @@ intel_pmdemand_update_max_ddiclk(struct intel_display *display, struct intel_crtc *crtc; int i; - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) intel_pmdemand_update_port_clock(display, pmdemand_state, crtc->pipe, new_crtc_state->port_clock); @@ -299,7 +299,6 @@ static bool intel_pmdemand_needs_update(struct intel_atomic_state *state) { const struct intel_crtc_state *new_crtc_state, *old_crtc_state; struct intel_crtc *crtc; - int i; if (intel_bw_pmdemand_needs_update(state)) return true; @@ -310,8 +309,7 @@ static bool intel_pmdemand_needs_update(struct intel_atomic_state *state) if (intel_cdclk_pmdemand_needs_update(state)) return true; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) if (new_crtc_state->port_clock != old_crtc_state->port_clock) return true; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 34eff85f4ea27..e138982dc91f6 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -793,27 +793,30 @@ static bool psr2_su_region_et_valid(struct intel_connector *connector, bool pane static void _panel_replay_enable_sink(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { - u8 val = DP_PANEL_REPLAY_ENABLE | - DP_PANEL_REPLAY_VSC_SDP_CRC_EN | - DP_PANEL_REPLAY_UNRECOVERABLE_ERROR_EN | - DP_PANEL_REPLAY_RFB_STORAGE_ERROR_EN | - DP_PANEL_REPLAY_ACTIVE_FRAME_CRC_ERROR_EN; - u8 panel_replay_config2 = DP_PANEL_REPLAY_CRC_VERIFICATION; + u8 panel_replay_config[2]; + u8 panel_replay_config_3; + panel_replay_config[0] = DP_PANEL_REPLAY_ENABLE | + DP_PANEL_REPLAY_VSC_SDP_CRC_EN | + DP_PANEL_REPLAY_UNRECOVERABLE_ERROR_EN | + DP_PANEL_REPLAY_RFB_STORAGE_ERROR_EN | + DP_PANEL_REPLAY_ACTIVE_FRAME_CRC_ERROR_EN; + panel_replay_config[1] = DP_PANEL_REPLAY_CRC_VERIFICATION; if (crtc_state->has_sel_update) - val |= DP_PANEL_REPLAY_SU_ENABLE; + panel_replay_config[0] |= DP_PANEL_REPLAY_SU_ENABLE; if (crtc_state->enable_psr2_su_region_et) - val |= DP_PANEL_REPLAY_ENABLE_SU_REGION_ET; + panel_replay_config[0] |= DP_PANEL_REPLAY_ENABLE_SU_REGION_ET; if (crtc_state->req_psr2_sdp_prior_scanline) - panel_replay_config2 |= + panel_replay_config[1] |= DP_PANEL_REPLAY_SU_REGION_SCANLINE_CAPTURE; - drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG, val); + drm_dp_dpcd_write(&intel_dp->aux, PANEL_REPLAY_CONFIG, + panel_replay_config, sizeof(panel_replay_config)); - drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG2, - panel_replay_config2); + panel_replay_config_3 = intel_dp_as_sdp_transmission_time(); + drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG3, panel_replay_config_3); } static void _psr_enable_sink(struct intel_dp *intel_dp, @@ -1508,15 +1511,21 @@ int _intel_psr_min_set_context_latency(const struct intel_crtc_state *crtc_state * SRD_STATUS is used by PSR1 and Panel Replay DP on LunarLake. */ - if (DISPLAY_VER(display) >= 30 && (needs_panel_replay || - needs_sel_update)) + if (needs_sel_update) return 0; - else if (DISPLAY_VER(display) < 30 && (needs_sel_update || - intel_crtc_has_type(crtc_state, - INTEL_OUTPUT_EDP))) + + if (DISPLAY_VER(display) < 30 && + intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) return 0; - else - return 1; + + if (DISPLAY_VER(display) >= 30 && + needs_panel_replay) + return 0; + + if (intel_vrr_always_use_vrr_tg(display)) + return 0; + + return 1; } static bool _wake_lines_fit_into_vblank(const struct intel_crtc_state *crtc_state, @@ -1902,7 +1911,7 @@ void intel_psr_set_non_psr_pipes(struct intel_dp *intel_dp, return; /* We ignore possible secondary PSR/Panel Replay capable eDP */ - for_each_intel_crtc(display->drm, crtc) + for_each_intel_crtc(display, crtc) active_pipes |= crtc->active ? BIT(crtc->pipe) : 0; active_pipes = intel_calc_active_pipes(state, active_pipes); @@ -2913,6 +2922,11 @@ intel_psr_apply_su_area_workarounds(struct intel_crtc_state *crtc_state) crtc_state->splitter.enable) crtc_state->psr2_su_area.y1 = 0; + if (intel_display_wa(display, INTEL_DISPLAY_WA_16029024088) && + crtc_state->req_psr2_sdp_prior_scanline && + !crtc_state->enable_psr2_su_region_et) + crtc_state->psr2_su_area.y1 = 0; + /* Wa 14019834836 */ if (DISPLAY_VER(display) == 30) intel_psr_apply_pr_link_on_su_wa(crtc_state); @@ -4684,3 +4698,14 @@ bool intel_psr_use_trans_push(const struct intel_crtc_state *crtc_state) return HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display) && crtc_state->has_psr; } + +bool intel_psr_pr_async_video_timing_supported(struct intel_dp *intel_dp) +{ + struct intel_connector *connector = intel_dp->attached_connector; + u8 *dpcd = connector->dp.panel_replay_caps.dpcd; + u8 pr_support = dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)]; + u8 pr_cap = dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)]; + + return (pr_support & DP_PANEL_REPLAY_SUPPORT) && + !(pr_cap & DP_PANEL_REPLAY_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR); +} diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h index 394b641840b39..29723e63888f8 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.h +++ b/drivers/gpu/drm/i915/display/intel_psr.h @@ -86,5 +86,6 @@ void intel_psr_compute_config_late(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state); int intel_psr_min_guardband(struct intel_crtc_state *crtc_state); bool intel_psr_use_trans_push(const struct intel_crtc_state *crtc_state); +bool intel_psr_pr_async_video_timing_supported(struct intel_dp *intel_dp); #endif /* __INTEL_PSR_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index 2880f2aa42437..f2d86b29c4154 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -1779,7 +1779,7 @@ static int reset_link_commit(struct intel_tc_port *tc, if (!pipe_mask) return 0; - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) { + for_each_intel_crtc_in_pipe_mask(display, crtc, pipe_mask) { struct intel_crtc_state *crtc_state; crtc_state = intel_atomic_get_crtc_state(&state->base, crtc); diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 1b09992ce9fdd..e03b5daac5be0 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -94,12 +94,10 @@ bool intel_vrr_possible(const struct intel_crtc_state *crtc_state) void intel_vrr_check_modeset(struct intel_atomic_state *state) { - int i; struct intel_crtc_state *old_crtc_state, *new_crtc_state; struct intel_crtc *crtc; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { if (new_crtc_state->uapi.vrr_enabled != old_crtc_state->uapi.vrr_enabled) new_crtc_state->uapi.mode_changed = true; diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 308b8d363bba0..7994b983d509d 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -661,9 +661,9 @@ static int glk_coef_tap(int i) return i % 7; } -static u16 glk_nearest_filter_coef(int t) +static u16 glk_nearest_filter_coef(int tap) { - return t == 3 ? 0x0800 : 0x3000; + return tap == 3 ? 0x0800 : 0x3000; } /* @@ -715,13 +715,13 @@ static void glk_program_nearest_filter_coefs(struct intel_display *display, for (i = 0; i < 17 * 7; i += 2) { u32 tmp; - int t; + int tap; - t = glk_coef_tap(i); - tmp = glk_nearest_filter_coef(t); + tap = glk_coef_tap(i); + tmp = glk_nearest_filter_coef(tap); - t = glk_coef_tap(i + 1); - tmp |= glk_nearest_filter_coef(t) << 16; + tap = glk_coef_tap(i + 1); + tmp |= glk_nearest_filter_coef(tap) << 16; intel_de_write_dsb(display, dsb, GLK_PS_COEF_DATA_SET(pipe, id, set), tmp); @@ -836,6 +836,22 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state) PS_WIN_XSIZE(width) | PS_WIN_YSIZE(height)); } +static int skl_pipe_scaler_get_hw_state(struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + for (int scaler_id = 0; scaler_id < crtc->num_scalers; scaler_id++) { + u32 ctl; + + ctl = intel_de_read(display, SKL_PS_CTRL(crtc->pipe, scaler_id)); + if ((ctl & (PS_SCALER_EN | PS_BINDING_MASK)) == (PS_SCALER_EN | PS_BINDING_PIPE)) + return scaler_id; + } + + return -1; +} + void skl_program_plane_scaler(struct intel_dsb *dsb, struct intel_plane *plane, @@ -950,42 +966,32 @@ void skl_scaler_get_config(struct intel_crtc_state *crtc_state) struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; - int id = -1; - int i; + int scaler_id; + u32 pos, size; /* find scaler attached to this pipe */ - for (i = 0; i < crtc->num_scalers; i++) { - u32 ctl, pos, size; - - ctl = intel_de_read(display, SKL_PS_CTRL(crtc->pipe, i)); - if ((ctl & (PS_SCALER_EN | PS_BINDING_MASK)) != (PS_SCALER_EN | PS_BINDING_PIPE)) - continue; - - id = i; + scaler_id = skl_pipe_scaler_get_hw_state(crtc_state); + if (scaler_id < 0) + return; - if (scaler_has_casf(display, i)) - intel_casf_sharpness_get_config(crtc_state); + if (scaler_has_casf(display, scaler_id)) + intel_casf_sharpness_get_config(crtc_state); - crtc_state->pch_pfit.enabled = true; + crtc_state->pch_pfit.enabled = true; - pos = intel_de_read(display, SKL_PS_WIN_POS(crtc->pipe, i)); - size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, i)); + pos = intel_de_read(display, SKL_PS_WIN_POS(crtc->pipe, scaler_id)); + size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, scaler_id)); - drm_rect_init(&crtc_state->pch_pfit.dst, - REG_FIELD_GET(PS_WIN_XPOS_MASK, pos), - REG_FIELD_GET(PS_WIN_YPOS_MASK, pos), - REG_FIELD_GET(PS_WIN_XSIZE_MASK, size), - REG_FIELD_GET(PS_WIN_YSIZE_MASK, size)); + drm_rect_init(&crtc_state->pch_pfit.dst, + REG_FIELD_GET(PS_WIN_XPOS_MASK, pos), + REG_FIELD_GET(PS_WIN_YPOS_MASK, pos), + REG_FIELD_GET(PS_WIN_XSIZE_MASK, size), + REG_FIELD_GET(PS_WIN_YSIZE_MASK, size)); - scaler_state->scalers[i].in_use = true; - break; - } + scaler_state->scalers[scaler_id].in_use = true; - scaler_state->scaler_id = id; - if (id >= 0) - scaler_state->scaler_users |= (1 << SKL_CRTC_INDEX); - else - scaler_state->scaler_users &= ~(1 << SKL_CRTC_INDEX); + scaler_state->scaler_id = scaler_id; + scaler_state->scaler_users |= (1 << SKL_CRTC_INDEX); } void adl_scaler_ecc_mask(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index ef431dd32e74a..ad4bfff6903da 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1532,7 +1532,7 @@ static void icl_plane_update_sel_fetch_noarm(struct intel_dsb *dsb, if (!color_plane) y = plane_state->view.color_plane[color_plane].y + clip->y1; else - y = plane_state->view.color_plane[color_plane].y + clip->y1 / 2; + y = plane_state->view.color_plane[color_plane].y + DIV_ROUND_UP(clip->y1, 2); val = y << 16 | x; diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 96d2dcbe7bbcf..5a3677ea25b07 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -2495,9 +2495,9 @@ skl_compute_ddb(struct intel_atomic_state *state) struct intel_dbuf_state *new_dbuf_state = NULL; struct intel_crtc_state *new_crtc_state; struct intel_crtc *crtc; - int ret, i; + int ret; - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { new_dbuf_state = intel_atomic_get_dbuf_state(state); if (IS_ERR(new_dbuf_state)) return PTR_ERR(new_dbuf_state); @@ -2529,7 +2529,7 @@ skl_compute_ddb(struct intel_atomic_state *state) } } - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { enum pipe pipe = crtc->pipe; new_dbuf_state->slices[pipe] = @@ -2561,7 +2561,7 @@ skl_compute_ddb(struct intel_atomic_state *state) str_yes_no(new_dbuf_state->joined_mbus)); } - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { enum pipe pipe = crtc->pipe; new_dbuf_state->weight[pipe] = intel_crtc_ddb_weight(new_crtc_state); @@ -2574,13 +2574,13 @@ skl_compute_ddb(struct intel_atomic_state *state) return ret; } - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { ret = skl_crtc_allocate_ddb(state, crtc); if (ret) return ret; } - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { ret = skl_crtc_allocate_plane_ddb(state, crtc); if (ret) return ret; @@ -2687,13 +2687,11 @@ skl_print_wm_changes(struct intel_atomic_state *state) const struct intel_crtc_state *new_crtc_state; struct intel_plane *plane; struct intel_crtc *crtc; - int i; if (!drm_debug_enabled(DRM_UT_KMS)) return; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state) { const struct skl_pipe_wm *old_pipe_wm, *new_pipe_wm; old_pipe_wm = &old_crtc_state->wm.skl.optimal; @@ -2833,19 +2831,19 @@ static int pkgc_max_linetime(struct intel_atomic_state *state) struct intel_display *display = to_intel_display(state); const struct intel_crtc_state *crtc_state; struct intel_crtc *crtc; - int i, max_linetime; + int max_linetime; /* * Apparenty the hardware uses WM_LINETIME internally for * this stuff, compute everything based on that. */ - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, crtc_state) { display->pkgc.disable[crtc->pipe] = crtc_state->vrr.enable; display->pkgc.linetime[crtc->pipe] = DIV_ROUND_UP(crtc_state->linetime, 8); } max_linetime = 0; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { if (display->pkgc.disable[crtc->pipe]) return 0; @@ -2909,9 +2907,9 @@ skl_compute_wm(struct intel_atomic_state *state) struct intel_display *display = to_intel_display(state); struct intel_crtc *crtc; struct intel_crtc_state __maybe_unused *new_crtc_state; - int ret, i; + int ret; - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { ret = skl_build_pipe_wm(state, crtc); if (ret) return ret; @@ -2926,7 +2924,7 @@ skl_compute_wm(struct intel_atomic_state *state) * based on how much ddb is available. Now we can actually * check if the final watermarks changed. */ - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { struct skl_pipe_wm *pipe_wm = &new_crtc_state->wm.skl.optimal; /* @@ -3033,7 +3031,7 @@ static void skl_wm_get_hw_state(struct intel_display *display) dbuf_state->mdclk_cdclk_ratio = intel_mdclk_cdclk_ratio(display, &display->cdclk.hw); dbuf_state->active_pipes = 0; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); enum pipe pipe = crtc->pipe; @@ -3446,7 +3444,7 @@ static void pipe_mbus_dbox_ctl_update(struct intel_display *display, { struct intel_crtc *crtc; - for_each_intel_crtc_in_pipe_mask(display->drm, crtc, dbuf_state->active_pipes) + for_each_intel_crtc_in_pipe_mask(display, crtc, dbuf_state->active_pipes) intel_de_write(display, PIPE_MBUS_DBOX_CTL(crtc->pipe), pipe_mbus_dbox_ctl(crtc, dbuf_state)); } @@ -3758,14 +3756,14 @@ static bool skl_dbuf_is_misconfigured(struct intel_display *display) struct skl_ddb_entry entries[I915_MAX_PIPES] = {}; struct intel_crtc *crtc; - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); entries[crtc->pipe] = crtc_state->wm.skl.ddb; } - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); u8 slices; @@ -3803,7 +3801,7 @@ static void skl_dbuf_sanitize(struct intel_display *display) drm_dbg_kms(display->drm, "BIOS has misprogrammed the DBUF, disabling all planes\n"); - for_each_intel_crtc(display->drm, crtc) { + for_each_intel_crtc(display, crtc) { struct intel_plane *plane = to_intel_plane(crtc->base.primary); const struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index f06b2e8cf7d4b..58081b52461ac 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -297,7 +297,7 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv) struct intel_display *display = dev_priv->display; intel_irq_fini(dev_priv); - intel_power_domains_cleanup(display); + intel_display_power_cleanup(display); i915_gem_cleanup_early(dev_priv); intel_gt_driver_late_release_all(dev_priv); intel_region_ttm_device_fini(dev_priv); @@ -660,7 +660,7 @@ static int i915_driver_register(struct drm_i915_private *dev_priv) intel_display_driver_register(display); - intel_power_domains_enable(display); + intel_display_power_enable(display); intel_runtime_pm_enable(&dev_priv->runtime_pm); if (i915_switcheroo_register(dev_priv)) @@ -682,7 +682,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv) i915_switcheroo_unregister(dev_priv); intel_runtime_pm_disable(&dev_priv->runtime_pm); - intel_power_domains_disable(display); + intel_display_power_disable(display); intel_display_driver_unregister(display); @@ -971,6 +971,7 @@ void i915_driver_remove(struct drm_i915_private *i915) intel_display_driver_remove(display); intel_irq_uninstall(i915); + intel_hpd_cancel_work(display); intel_display_driver_remove_noirq(display); @@ -1042,7 +1043,7 @@ void i915_driver_shutdown(struct drm_i915_private *i915) disable_rpm_wakeref_asserts(&i915->runtime_pm); intel_runtime_pm_disable(&i915->runtime_pm); - intel_power_domains_disable(display); + intel_display_power_disable(display); drm_client_dev_suspend(&i915->drm); if (intel_display_device_present(display)) { @@ -1078,7 +1079,7 @@ void i915_driver_shutdown(struct drm_i915_private *i915) * - unify the driver remove and system/runtime suspend sequences with * the above unified shutdown/poweroff sequence. */ - intel_power_domains_driver_remove(display); + intel_display_power_driver_remove(display); enable_rpm_wakeref_asserts(&i915->runtime_pm); intel_runtime_pm_driver_last_release(&i915->runtime_pm); @@ -1125,7 +1126,7 @@ static int i915_drm_suspend(struct drm_device *dev) /* We do a lot of poking in a lot of registers, make sure they work * properly. */ - intel_power_domains_disable(display); + intel_display_power_disable(display); drm_client_dev_suspend(dev); if (intel_display_device_present(display)) { drm_kms_helper_poll_disable(dev); @@ -1325,7 +1326,7 @@ static int i915_drm_resume(struct drm_device *dev) drm_client_dev_resume(dev); - intel_power_domains_enable(display); + intel_display_power_enable(display); intel_gvt_resume(dev_priv); @@ -1557,7 +1558,7 @@ static int i915_pm_restore(struct device *kdev) return i915_pm_resume(kdev); } -static int intel_runtime_suspend(struct device *kdev) +static int i915_pm_runtime_suspend(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_display *display = dev_priv->display; @@ -1590,7 +1591,7 @@ static int intel_runtime_suspend(struct device *kdev) for_each_gt(gt, dev_priv, i) intel_uncore_suspend(gt->uncore); - intel_display_power_suspend(display); + intel_display_power_runtime_suspend(display); ret = vlv_suspend_complete(dev_priv); if (ret) { @@ -1631,7 +1632,7 @@ static int intel_runtime_suspend(struct device *kdev) if (IS_BROADWELL(dev_priv)) { /* * On Broadwell, if we use PCI_D1 the PCH DDI ports will stop - * being detected, and the call we do at intel_runtime_resume() + * being detected, and the call we do at i915_pm_runtime_resume() * won't be able to restore them. Since PCI_D3hot matches the * actual specification and appears to be working, use it. */ @@ -1656,7 +1657,7 @@ static int intel_runtime_suspend(struct device *kdev) return 0; } -static int intel_runtime_resume(struct device *kdev) +static int i915_pm_runtime_resume(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_display *display = dev_priv->display; @@ -1684,7 +1685,7 @@ static int intel_runtime_resume(struct device *kdev) drm_dbg(&dev_priv->drm, "Unclaimed access during suspend, bios?\n"); - intel_display_power_resume(display); + intel_display_power_runtime_resume(display); ret = vlv_resume_prepare(dev_priv, true); @@ -1764,8 +1765,8 @@ const struct dev_pm_ops i915_pm_ops = { .restore = i915_pm_restore, /* S0ix (via runtime suspend) event handlers */ - .runtime_suspend = intel_runtime_suspend, - .runtime_resume = intel_runtime_resume, + .runtime_suspend = i915_pm_runtime_suspend, + .runtime_resume = i915_pm_runtime_resume, }; static const struct file_operations i915_driver_fops = { @@ -1869,9 +1870,6 @@ static const struct drm_ioctl_desc i915_ioctls[] = { #define DRIVER_PATCHLEVEL 0 static const struct drm_driver i915_drm_driver = { - /* Don't use MTRRs here; the Xserver or userspace app should - * deal with them for Intel hardware. - */ .driver_features = DRIVER_GEM | DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_SYNCOBJ | diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index d4d8dd0a41749..932409b943ad2 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -37,9 +37,6 @@ #include <drm/intel/intel_gmd_interrupt_regs.h> #include "display/intel_display_irq.h" -#include "display/intel_hotplug.h" -#include "display/intel_hotplug_irq.h" -#include "display/intel_lpe_audio.h" #include "gt/intel_breadcrumbs.h" #include "gt/intel_gt.h" @@ -236,17 +233,15 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); do { - u32 iir, gt_iir, pm_iir; - u32 eir = 0, dpinvgtt = 0; - u32 pipe_stats[I915_MAX_PIPES] = {}; - u32 hotplug_status = 0; + struct intel_display_irq_state state = {}; + u32 gt_iir, pm_iir; u32 ier = 0; gt_iir = intel_uncore_read(&dev_priv->uncore, GTIIR); pm_iir = intel_uncore_read(&dev_priv->uncore, GEN6_PMIIR); - iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); + state.iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); - if (gt_iir == 0 && pm_iir == 0 && iir == 0) + if (gt_iir == 0 && pm_iir == 0 && state.iir == 0) break; ret = IRQ_HANDLED; @@ -272,26 +267,14 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) if (pm_iir) intel_uncore_write(&dev_priv->uncore, GEN6_PMIIR, pm_iir); - if (iir & I915_DISPLAY_PORT_INTERRUPT) - hotplug_status = i9xx_hpd_irq_ack(display); - - if (iir & I915_MASTER_ERROR_INTERRUPT) - vlv_display_error_irq_ack(display, &eir, &dpinvgtt); - - /* Call regardless, as some status bits might not be - * signalled in IIR */ - i9xx_pipestat_irq_ack(display, iir, pipe_stats); - - if (iir & (I915_LPE_PIPE_A_INTERRUPT | - I915_LPE_PIPE_B_INTERRUPT)) - intel_lpe_audio_irq_handler(display); + intel_display_irq_ack(display, &state); /* * VLV_IIR is single buffered, and reflects the level * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. */ - if (iir) - intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir); + if (state.iir) + intel_uncore_write(&dev_priv->uncore, VLV_IIR, state.iir); intel_uncore_write(&dev_priv->uncore, VLV_IER, ier); intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); @@ -301,13 +284,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) if (pm_iir) gen6_rps_irq_handler(&to_gt(dev_priv)->rps, pm_iir); - if (hotplug_status) - i9xx_hpd_irq_handler(display, hotplug_status); - - if (iir & I915_MASTER_ERROR_INTERRUPT) - vlv_display_error_irq_handler(display, eir, dpinvgtt); - - valleyview_pipestat_irq_handler(display, pipe_stats); + intel_display_irq_handler(display, &state); } while (0); pmu_irq_stats(dev_priv, ret); @@ -330,16 +307,14 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); do { - u32 master_ctl, iir; - u32 eir = 0, dpinvgtt = 0; - u32 pipe_stats[I915_MAX_PIPES] = {}; - u32 hotplug_status = 0; + struct intel_display_irq_state state = {}; + u32 master_ctl; u32 ier = 0; master_ctl = intel_uncore_read(&dev_priv->uncore, GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; - iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); + state.iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); - if (master_ctl == 0 && iir == 0) + if (master_ctl == 0 && state.iir == 0) break; ret = IRQ_HANDLED; @@ -362,38 +337,19 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) gen8_gt_irq_handler(to_gt(dev_priv), master_ctl); - if (iir & I915_DISPLAY_PORT_INTERRUPT) - hotplug_status = i9xx_hpd_irq_ack(display); - - if (iir & I915_MASTER_ERROR_INTERRUPT) - vlv_display_error_irq_ack(display, &eir, &dpinvgtt); - - /* Call regardless, as some status bits might not be - * signalled in IIR */ - i9xx_pipestat_irq_ack(display, iir, pipe_stats); - - if (iir & (I915_LPE_PIPE_A_INTERRUPT | - I915_LPE_PIPE_B_INTERRUPT | - I915_LPE_PIPE_C_INTERRUPT)) - intel_lpe_audio_irq_handler(display); + intel_display_irq_ack(display, &state); /* * VLV_IIR is single buffered, and reflects the level * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. */ - if (iir) - intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir); + if (state.iir) + intel_uncore_write(&dev_priv->uncore, VLV_IIR, state.iir); intel_uncore_write(&dev_priv->uncore, VLV_IER, ier); intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); - if (hotplug_status) - i9xx_hpd_irq_handler(display, hotplug_status); - - if (iir & I915_MASTER_ERROR_INTERRUPT) - vlv_display_error_irq_handler(display, eir, dpinvgtt); - - valleyview_pipestat_irq_handler(display, pipe_stats); + intel_display_irq_handler(display, &state); } while (0); pmu_irq_stats(dev_priv, ret); @@ -440,7 +396,7 @@ static irqreturn_t ilk_irq_handler(int irq, void *arg) ret = IRQ_HANDLED; } - if (ilk_display_irq_handler(display)) + if (intel_display_irq_handler(display, NULL)) ret = IRQ_HANDLED; if (GRAPHICS_VER(i915) >= 6) { @@ -502,8 +458,11 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) /* IRQs are synced during runtime_suspend, we don't require a wakeref */ if (master_ctl & ~GEN8_GT_IRQS) { + const struct intel_display_irq_state state = { + .master_ctl = master_ctl, + }; disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); - gen8_de_irq_handler(display, master_ctl); + intel_display_irq_handler(display, &state); enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); } @@ -555,7 +514,7 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg) /* IRQs are synced during runtime_suspend, we don't require a wakeref */ if (master_ctl & GEN11_DISPLAY_IRQ) - gen11_display_irq_handler(display); + intel_display_irq_handler(display, NULL); gu_misc_iir = gen11_gu_misc_irq_ack(display, master_ctl); @@ -622,7 +581,7 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg) gen11_gt_irq_handler(gt, master_ctl); if (master_ctl & GEN11_DISPLAY_IRQ) - gen11_display_irq_handler(display); + intel_display_irq_handler(display, NULL); gu_misc_iir = gen11_gu_misc_irq_ack(display, master_ctl); @@ -640,7 +599,7 @@ static void ilk_irq_reset(struct drm_i915_private *dev_priv) struct intel_display *display = dev_priv->display; /* The master interrupt enable is in DEIER, reset display irq first */ - ilk_display_irq_reset(display); + intel_display_irq_reset(display); gen5_gt_irq_reset(to_gt(dev_priv)); } @@ -653,7 +612,7 @@ static void valleyview_irq_reset(struct drm_i915_private *dev_priv) gen5_gt_irq_reset(to_gt(dev_priv)); - vlv_display_irq_reset(display); + intel_display_irq_reset(display); } static void gen8_irq_reset(struct drm_i915_private *dev_priv) @@ -664,7 +623,7 @@ static void gen8_irq_reset(struct drm_i915_private *dev_priv) gen8_master_intr_disable(intel_uncore_regs(uncore)); gen8_gt_irq_reset(to_gt(dev_priv)); - gen8_display_irq_reset(display); + intel_display_irq_reset(display); gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS); } @@ -677,7 +636,7 @@ static void gen11_irq_reset(struct drm_i915_private *dev_priv) gen11_master_intr_disable(intel_uncore_regs(&dev_priv->uncore)); gen11_gt_irq_reset(gt); - gen11_display_irq_reset(display); + intel_display_irq_reset(display); gen2_irq_reset(uncore, GEN11_GU_MISC_IRQ_REGS); gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS); @@ -695,7 +654,7 @@ static void dg1_irq_reset(struct drm_i915_private *dev_priv) for_each_gt(gt, dev_priv, i) gen11_gt_irq_reset(gt); - gen11_display_irq_reset(display); + intel_display_irq_reset(display); gen2_irq_reset(uncore, GEN11_GU_MISC_IRQ_REGS); gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS); @@ -715,7 +674,7 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv) gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS); - vlv_display_irq_reset(display); + intel_display_irq_reset(display); } static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) @@ -724,7 +683,7 @@ static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) gen5_gt_irq_postinstall(to_gt(dev_priv)); - ilk_de_irq_postinstall(display); + intel_display_irq_postinstall(display); } static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) @@ -733,7 +692,7 @@ static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) gen5_gt_irq_postinstall(to_gt(dev_priv)); - vlv_display_irq_postinstall(display); + intel_display_irq_postinstall(display); intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); @@ -744,7 +703,7 @@ static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) struct intel_display *display = dev_priv->display; gen8_gt_irq_postinstall(to_gt(dev_priv)); - gen8_de_irq_postinstall(display); + intel_display_irq_postinstall(display); gen8_master_intr_enable(intel_uncore_regs(&dev_priv->uncore)); } @@ -757,7 +716,7 @@ static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) u32 gu_misc_masked = GEN11_GU_MISC_GSE; gen11_gt_irq_postinstall(gt); - gen11_de_irq_postinstall(display); + intel_display_irq_postinstall(display); gen2_irq_init(uncore, GEN11_GU_MISC_IRQ_REGS, ~gu_misc_masked, gu_misc_masked); @@ -778,7 +737,7 @@ static void dg1_irq_postinstall(struct drm_i915_private *dev_priv) gen2_irq_init(uncore, GEN11_GU_MISC_IRQ_REGS, ~gu_misc_masked, gu_misc_masked); - dg1_de_irq_postinstall(display); + intel_display_irq_postinstall(display); dg1_master_intr_enable(intel_uncore_regs(uncore)); intel_uncore_posting_read(uncore, DG1_MSTR_TILE_INTR); @@ -790,7 +749,7 @@ static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv) gen8_gt_irq_postinstall(to_gt(dev_priv)); - vlv_display_irq_postinstall(display); + intel_display_irq_postinstall(display); intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); @@ -864,7 +823,7 @@ static void i915_irq_reset(struct drm_i915_private *dev_priv) struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; - i9xx_display_irq_reset(display); + intel_display_irq_reset(display); gen2_error_reset(uncore, GEN2_ERROR_REGS); gen2_irq_reset(uncore, GEN2_IRQ_REGS); @@ -888,7 +847,7 @@ static void i915_irq_postinstall(struct drm_i915_private *dev_priv) gen2_irq_init(uncore, GEN2_IRQ_REGS, dev_priv->gen2_imr_mask, enable_mask); - i915_display_irq_postinstall(display); + intel_display_irq_postinstall(display); } static irqreturn_t i915_irq_handler(int irq, void *arg) @@ -904,39 +863,29 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); do { - u32 pipe_stats[I915_MAX_PIPES] = {}; + struct intel_display_irq_state state = {}; u32 eir = 0, eir_stuck = 0; - u32 hotplug_status = 0; - u32 iir; - iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); - if (iir == 0) + state.iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); + if (state.iir == 0) break; ret = IRQ_HANDLED; - if (iir & I915_DISPLAY_PORT_INTERRUPT) - hotplug_status = i9xx_hpd_irq_ack(display); + intel_display_irq_ack(display, &state); - /* Call regardless, as some status bits might not be - * signalled in IIR */ - i9xx_pipestat_irq_ack(display, iir, pipe_stats); - - if (iir & I915_MASTER_ERROR_INTERRUPT) + if (state.iir & I915_MASTER_ERROR_INTERRUPT) i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); - intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir); + intel_uncore_write(&dev_priv->uncore, GEN2_IIR, state.iir); - if (iir & I915_USER_INTERRUPT) - intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir); + if (state.iir & I915_USER_INTERRUPT) + intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], state.iir); - if (iir & I915_MASTER_ERROR_INTERRUPT) + if (state.iir & I915_MASTER_ERROR_INTERRUPT) i9xx_error_irq_handler(dev_priv, eir, eir_stuck); - if (hotplug_status) - i9xx_hpd_irq_handler(display, hotplug_status); - - i915_pipestat_irq_handler(display, iir, pipe_stats); + intel_display_irq_handler(display, &state); } while (0); pmu_irq_stats(dev_priv, ret); @@ -951,7 +900,7 @@ static void i965_irq_reset(struct drm_i915_private *dev_priv) struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; - i9xx_display_irq_reset(display); + intel_display_irq_reset(display); gen2_error_reset(uncore, GEN2_ERROR_REGS); gen2_irq_reset(uncore, GEN2_IRQ_REGS); @@ -997,7 +946,7 @@ static void i965_irq_postinstall(struct drm_i915_private *dev_priv) gen2_irq_init(uncore, GEN2_IRQ_REGS, dev_priv->gen2_imr_mask, enable_mask); - i965_display_irq_postinstall(display); + intel_display_irq_postinstall(display); } static irqreturn_t i965_irq_handler(int irq, void *arg) @@ -1013,44 +962,34 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); do { - u32 pipe_stats[I915_MAX_PIPES] = {}; + struct intel_display_irq_state state = {}; u32 eir = 0, eir_stuck = 0; - u32 hotplug_status = 0; - u32 iir; - iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); - if (iir == 0) + state.iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); + if (state.iir == 0) break; ret = IRQ_HANDLED; - if (iir & I915_DISPLAY_PORT_INTERRUPT) - hotplug_status = i9xx_hpd_irq_ack(display); + intel_display_irq_ack(display, &state); - /* Call regardless, as some status bits might not be - * signalled in IIR */ - i9xx_pipestat_irq_ack(display, iir, pipe_stats); - - if (iir & I915_MASTER_ERROR_INTERRUPT) + if (state.iir & I915_MASTER_ERROR_INTERRUPT) i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); - intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir); + intel_uncore_write(&dev_priv->uncore, GEN2_IIR, state.iir); - if (iir & I915_USER_INTERRUPT) + if (state.iir & I915_USER_INTERRUPT) intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], - iir); + state.iir); - if (iir & I915_BSD_USER_INTERRUPT) + if (state.iir & I915_BSD_USER_INTERRUPT) intel_engine_cs_irq(to_gt(dev_priv)->engine[VCS0], - iir >> 25); + state.iir >> 25); - if (iir & I915_MASTER_ERROR_INTERRUPT) + if (state.iir & I915_MASTER_ERROR_INTERRUPT) i9xx_error_irq_handler(dev_priv, eir, eir_stuck); - if (hotplug_status) - i9xx_hpd_irq_handler(display, hotplug_status); - - i965_pipestat_irq_handler(display, iir, pipe_stats); + intel_display_irq_handler(display, &state); } while (0); pmu_irq_stats(dev_priv, IRQ_HANDLED); @@ -1200,7 +1139,6 @@ int intel_irq_install(struct drm_i915_private *dev_priv) */ void intel_irq_uninstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = dev_priv->display; int irq = to_pci_dev(dev_priv->drm.dev)->irq; if (drm_WARN_ON(&dev_priv->drm, !dev_priv->irqs_enabled)) @@ -1210,7 +1148,6 @@ void intel_irq_uninstall(struct drm_i915_private *dev_priv) free_irq(irq, dev_priv); - intel_hpd_cancel_work(display); dev_priv->irqs_enabled = false; } diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index d11c2814b787b..0d5b2624fe661 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -442,7 +442,7 @@ void intel_runtime_pm_put(struct intel_runtime_pm *rpm, intel_wakeref_t wref) * * Note that this function does currently not enable runtime pm for the * subordinate display power domains. That is done by - * intel_power_domains_enable(). + * intel_display_power_enable(). */ void intel_runtime_pm_enable(struct intel_runtime_pm *rpm) { diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 053abd6f65146..810d93fefcbcc 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -88,7 +88,7 @@ static void xe_display_fini_early(void *arg) intel_display_driver_remove_nogem(display); intel_display_driver_remove_noirq(display); intel_opregion_cleanup(display); - intel_power_domains_cleanup(display); + intel_display_power_cleanup(display); } int xe_display_init_early(struct xe_device *xe) @@ -104,6 +104,15 @@ int xe_display_init_early(struct xe_device *xe) intel_display_driver_early_probe(display); + intel_display_device_info_runtime_init(display); + + /* Display may have been disabled at runtime init */ + if (!intel_display_device_present(display)) { + xe->info.probe_display = false; + unset_display_features(xe); + return 0; + } + /* Early display init.. */ intel_opregion_setup(display); @@ -117,8 +126,6 @@ int xe_display_init_early(struct xe_device *xe) intel_bw_init_hw(display); - intel_display_device_info_runtime_init(display); - err = intel_display_driver_probe_noirq(display); if (err) goto err_opregion; @@ -130,7 +137,7 @@ int xe_display_init_early(struct xe_device *xe) return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_early, xe); err_noirq: intel_display_driver_remove_noirq(display); - intel_power_domains_cleanup(display); + intel_display_power_cleanup(display); err_opregion: intel_opregion_cleanup(display); return err; @@ -170,7 +177,7 @@ void xe_display_register(struct xe_device *xe) return; intel_display_driver_register(display); - intel_power_domains_enable(display); + intel_display_power_enable(display); } void xe_display_unregister(struct xe_device *xe) @@ -180,7 +187,7 @@ void xe_display_unregister(struct xe_device *xe) if (!xe->info.probe_display) return; - intel_power_domains_disable(display); + intel_display_power_disable(display); intel_display_driver_unregister(display); } @@ -194,7 +201,7 @@ void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl) return; if (master_ctl & DISPLAY_IRQ) - gen11_display_irq_handler(display); + intel_display_irq_handler(display, NULL); } void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir) @@ -215,7 +222,7 @@ void xe_display_irq_reset(struct xe_device *xe) if (!xe->info.probe_display) return; - gen11_display_irq_reset(display); + intel_display_irq_reset(display); } void xe_display_irq_postinstall(struct xe_device *xe) @@ -225,7 +232,7 @@ void xe_display_irq_postinstall(struct xe_device *xe) if (!xe->info.probe_display) return; - gen11_de_irq_postinstall(display); + intel_display_irq_postinstall(display); } static bool suspend_to_idle(void) @@ -237,27 +244,6 @@ static bool suspend_to_idle(void) return false; } -static void xe_display_flush_cleanup_work(struct xe_device *xe) -{ - struct intel_crtc *crtc; - - for_each_intel_crtc(&xe->drm, crtc) { - struct drm_crtc_commit *commit; - - spin_lock(&crtc->base.commit_lock); - commit = list_first_entry_or_null(&crtc->base.commit_list, - struct drm_crtc_commit, commit_entry); - if (commit) - drm_crtc_commit_get(commit); - spin_unlock(&crtc->base.commit_lock); - - if (commit) { - wait_for_completion(&commit->cleanup_done); - drm_crtc_commit_put(commit); - } - } -} - static void xe_display_enable_d3cold(struct xe_device *xe) { struct intel_display *display = xe->display; @@ -269,9 +255,9 @@ static void xe_display_enable_d3cold(struct xe_device *xe) * We do a lot of poking in a lot of registers, make sure they work * properly. */ - intel_power_domains_disable(display); + intel_display_power_disable(display); - xe_display_flush_cleanup_work(xe); + intel_display_flush_cleanup_work(display); intel_opregion_suspend(display, PCI_D3cold); @@ -302,7 +288,7 @@ static void xe_display_disable_d3cold(struct xe_device *xe) intel_opregion_resume(display); - intel_power_domains_enable(display); + intel_display_power_enable(display); } void xe_display_pm_suspend(struct xe_device *xe) @@ -317,7 +303,7 @@ void xe_display_pm_suspend(struct xe_device *xe) * We do a lot of poking in a lot of registers, make sure they work * properly. */ - intel_power_domains_disable(display); + intel_display_power_disable(display); drm_client_dev_suspend(&xe->drm); if (intel_display_device_present(display)) { @@ -326,7 +312,7 @@ void xe_display_pm_suspend(struct xe_device *xe) intel_display_driver_suspend(display); } - xe_display_flush_cleanup_work(xe); + intel_display_flush_cleanup_work(display); intel_encoder_block_all_hpds(display); @@ -349,7 +335,7 @@ void xe_display_pm_shutdown(struct xe_device *xe) if (!xe->info.probe_display) return; - intel_power_domains_disable(display); + intel_display_power_disable(display); drm_client_dev_suspend(&xe->drm); if (intel_display_device_present(display)) { @@ -358,7 +344,7 @@ void xe_display_pm_shutdown(struct xe_device *xe) intel_display_driver_suspend(display); } - xe_display_flush_cleanup_work(xe); + intel_display_flush_cleanup_work(display); intel_dp_mst_suspend(display); intel_encoder_block_all_hpds(display); intel_hpd_cancel_work(display); @@ -430,7 +416,7 @@ void xe_display_pm_shutdown_late(struct xe_device *xe) * for now leaving all display power wells in the INIT power domain * enabled. */ - intel_power_domains_driver_remove(display); + intel_display_power_driver_remove(display); } void xe_display_pm_resume_early(struct xe_device *xe) @@ -477,7 +463,7 @@ void xe_display_pm_resume(struct xe_device *xe) drm_client_dev_resume(&xe->drm); - intel_power_domains_enable(display); + intel_display_power_enable(display); } void xe_display_pm_runtime_resume(struct xe_device *xe) |
